YAPF – A formatter for Python files
github.com
github.com
--style STYLE specify formatting style: either a style name (for
example "pep8" or "google"), or the name of a file
with style settings. pep8 is the default.
> pep8 is the default.I can breathe again.
The warning about choking on large data literals (which are probably one of the places where prettifying would be most useful, at least to me) also seems ominous.
edit: for my personal use, I tend to use flycheck with flake8 in emacs. This keeps me honest. Is the primary use case for something like this cleaning your own code or other people's?
for example:
some_function(long_variable_name_and_stuff, long_variable_name_and_stuff,
long_variable_name_and_stuff)
The lower indentation level doesnt actually matter at all says flake8edit: To below, that's possible. I can't remember the exact case right now but there are things along these lines that are valid and shouldn't be. Multiple possible indentation formats is not necessarily something you want to allow as an org, which is where something like YAPF comes into play
edit: if there are bugs in PEP 8, work to get them fixed rather than promoting alternative styles like the Google style, please!
The latter is widely used to format C, C++ (and even JS and Java) code. Many projects these days require all code to be clang-format'ed and even enforce it in commit hooks and such.
After working on such projects for a while, you get so used to the convenience of an auto-formatting tool, that you want it in all languages you code in. It's extremely useful to be able to just type a bunch of code quickly into the editor, copy-pasting, renaming, and know that the tool will nicely format it for you. Another advantage is that the whole code in a projects starts being and looking very consistent, which is important. Holy wars about brace placement and indentation just disappear.
So yapf is essentially that, for Python.
As yapf documentation has pointed out, pep8 is vague about certain things (i.e. indention). Yelp prefers an indention style where multiple arguments are broken up 1 per line and has a pre-commit hook to automatically enforce that. yapf is also opinionated about indentation, preferring vertical alignment. I've run it on an open source project to illustrated the differences (YelpDent vs yapf indent):
def remove_user_data(dryrun=False):
if platform.system() == 'Darwin':
- data_home = os.path.join(
- os.path.expanduser('~'),
- 'Library',
- 'autojump')
+ data_home = os.path.join(os.path.expanduser('~'), 'Library',
+ 'autojump')
elif platform.system() == 'Windows':
data_home = os.path.join(os.getenv('APPDATA'), 'autojump')
else:
- data_home = os.getenv(
- 'XDG_DATA_HOME',
- os.path.join(
- os.path.expanduser('~'),
- '.local',
- 'share',
- 'autojump'))
+ data_home = os.getenv('XDG_DATA_HOME',
+ os.path.join(os.path.expanduser('~'), '.local',
+ 'share', 'autojump'))Ultimately, we'd like to have these things configurable via the style settings of yapf, so multiple detailed styles can be selected.
Patches welcome :)
def OtherLongFunctionName(One,
Two,
Three
):
print "Does stuff"
def MyFunction(Param1,
OtherParam,
FooParam,
EtcParam
):
if ((Param1 * 1000) > 5000 &&
OtherParam is not None &&
len(FooParam) > 50
):
new_instance_dict = {
"TestingFoo": Param1,
"NewFoo": OtherParam,
"LongFooBar": FooParam,
}
recursive = MyFunction(
OtherLongFunctionName(
Param1,
OtherParam,
FooParam
)
)
It doesn't comply to PEP8 due to the indentation of nested params and stuff on the new lines. PEP8 apparently wants them aligned with the opening/starting bracket. This looks horrible, and just right-aligns all your code into little columns. And doesn't work very well with nested function calls.Therefore, YAPF (and even clang-format) balk on them. They will handle them of course. But the result will almost certainly not look like what you want.
That's why we give you the ability to disable formatting for sections of code.
Paul Graham once said that you should use the tools that programmers build to solve their own problems, not the tools that big corporations build to solve their ideas of what other peoples' problems are. That doesn't mean every little library is a good one (Sturgeon's Law applies - 90% of everything is crap), but it does mean that being "official" is usually a negative signal on product quality.
This applies to other companies' code as well; I've never used a buggy piece of shit quite so bad as Sun's JSF (which was supposed to be the "official" way to build webapps with Java, circa 2004-2006), while BSD and Linux continue to be great pieces of software 25 years later.
Do anyone of you guys know what the name YAPF comes from? (The only thing I can think of is "Yet Another Python Formatter", but I'm just guessing)
I found that running this tool over it resulted in some strange new lines.
For example, this was my old hideously long line:
query_qual = "INSERT OR REPLACE INTO Qualifying (poleid, seasonid, race_week_num, carclassid, pole) values (%s%s, %s, %s, %s, %s)" % (race[u'seasonid'], race[u'race_week_num'], race[u'seasonid'], race[u'race_week_num'], race[u'carclassid'], pole)
Changed to this:
query_qual = "INSERT OR REPLACE INTO Qualifying (poleid, seasonid, race_week_num, carclassid, pole) values (%s%s, %s, %s, %s, %s)" % ( race[u'seasonid'], race[u'race_week_num'], race[ u'seasonid' ], race[u'race_week_num'], race[u'carclassid'], pole)
Every word in this sentence was entered on a different line.
it appears like thisWhen I see people write
'some %s %s text ' %('x', 'y')
my first thought is "% is not not a function".I'm reminded also of (and agree with) the Crockford convention in JavaScript recommending a space in
function () {...}
but not in function foo(object) {...}
But conventions are are a choice made; most times it's easier to adopt them and move on.Which brings me to a related question. Just like color-schemes are preferences in editors and IDEs, why isn't such spacing too. Then it would not be a "choice made" a priori for all individuals.
I suppose you could run all the code you receive and have to read through a code-formatter such as YAPF. That way, no matter what "way" someone writes their code, when you read it, it'll be in your comfortable/preferred format.
I find your question interesting - why SHOULD programming language syntax match English syntax? Programming languages borrow symbols from natural languages for convenience, but there's generally only a very loose analogy between their purposes in each.
Question, does it bug you when you see function calls without spaces in the same way it would if(for example) someone left out a space in writing?
To answer your second question, with English, it certainly bugs me. With programming languages, I use the space but of course do not expect the same from anyone else. No one so far has complained about me using it either. :-)
There are two factors involved: I reckon most people (a) see a function call as a single logical unit and write it as such and (b) feel compelled to follow conventions. The result is that once there's a clear majority, most code will converge on that style. Clearly you do neither :)
Personally I just try to adopt the conventions of the language or ecosystem I'm working in as closely as possible and try not to let my personal leanings get in the way. The most important thing is that others can easily read my code.
I would love to write Python like this, but sadly for me PEP8 and society frown upon it:
some_dict = {'a_key': an_expression,
'another_key': another_expression}Indeed, that is one of those "big argument" type of minor formatting discussions. Despite my OCD, it doesn't bother me, and in fact, I prefer formatting them as below:
some_dict = {
'a_key': an_expression,
'another_key': another_expression,
}
Question, if you add another entry, and it throws off the formatting, do you go up and change all the other entries prior so they all align? Because that does bring up questions about code-commits. I.e. you're touching code that hasn't changed. some_dict = {
'a_key': an_expression,
'another_key': another_expression,
'a_really_long_key_that_throws_you_off': expression,
}
As opposed to: some_dict = {'a_key': an_expression,
'another_key': another_expression,
'a_really_long_key_that_throws_you_off': expression}Would be cool if IDEs could do this for you at the display level without touching the underlying code!
https://github.com/jason-kane/PyYapf
It isn't in Sublime package control yet.
echo 'foo="\\"' | PYTHONPATH=/tmp/yapf/yapf python /tmp/yapf
Raises a lib2to3.pgen2.parse.ParseError.
Also crashes on \n, but not, strangely, on \t.
I’m guessing that the backslashes get interpreted twice, somehow.
Apparently I need to “Sign in” to report a Github issue, so I won’t.
And yapf runs just fine on it. Does this file work for you?
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/tmp/yapf/yapf/__main__.py", line 18, in <module>
sys.exit(yapf.main(sys.argv))
File "/tmp/yapf/yapf/__init__.py", line 104, in main
verify=args.verify))
File "/tmp/yapf/yapf/yapflib/yapf_api.py", line 99, in FormatCode
tree = pytree_utils.ParseCodeToTree(unformatted_source.rstrip() + '\n')
File "/tmp/yapf/yapf/yapflib/pytree_utils.py", line 100, in ParseCodeToTree
tree = parser_driver.parse_string(code, debug=False)
File "/usr/lib/python2.7/lib2to3/pgen2/driver.py", line 106, in parse_string
return self.parse_tokens(tokens, debug)
File "/usr/lib/python2.7/lib2to3/pgen2/driver.py", line 71, in parse_tokens
if p.addtoken(type, value, (prefix, start)):
File "/usr/lib/python2.7/lib2to3/pgen2/parse.py", line 116, in addtoken
ilabel = self.classify(type, value, context)
File "/usr/lib/python2.7/lib2to3/pgen2/parse.py", line 172, in classify
raise ParseError("bad token", type, value, context)
lib2to3.pgen2.parse.ParseError: bad token: type=55, value=u' ', context=('', (1, 5))Mine is 2.7.6
I'm asking because bugs get fixed in lib2to3 occasionally, and we see differences between minor Python versions in this regard.
I guess we should be recommending the latest Python 2.7 possible, since it's very difficult for us to work around lib2to3 bugs in yapf - we're basically limited to whatever it can parse. Some things can be monkey-patched, but core parsing bugs are challenging.
Just in case anyone thought "by Google" meant "a Google product" like me.
And it seems like that's used in YAPF as well: https://github.com/google/yapf/blob/master/yapf/yapflib/styl...
https://news.ycombinator.com/item?id=9260786
I suggested to the author that they restore "google" style to the public one and rename the existing one to "chromium" style, since that's the most prominent public project still on Google's internal style.
We mention in the documentation that data literals are a sticking point to most people and most automatic formatters. Even clang-format tends to balk on them. We try our best at them, but it might be best to just disable formatting them if they are already formatted to something you like. :-)
edit: this is directly relevant to the thread, which is about Python formatting and Google promoting its weird style