Format Python Code Using YAPF
leimao.github.io
leimao.github.io
Seriously, use Black. I my experience, and to my taste, it works perfectly all the time, and the result is beautiful.
It's also pep8 compliant, for the parts of pep8 that are concerned by a reformatter.
Black removes any additional parentheses added to enable a line split at a reasonable position (such as "and"). With those removed, black has to split at weird locations like at a function call.
But switching to black just for the speed increase is reasonable.
Thus I "like" black's opinionated take.
"I see some rude code and I want to paint it black, " -- Sir Mick Jagger, probably.
call(
{
"key": "value",
"key": "value",
}
) items = {
"key": "value",
"key": "value",
}
call(items)
it's a bit annoying with exception messages, but again, writing long args before works great, and i've become a fan of this (unintended?) nudge: if error:
raise ValueError(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vel ligula nec eros finibus metus."
)
if error:
msg = (
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"Maecenas vel ligula nec eros finibus metus."
)
raise ValueError(msg)
just to be clear, i don't think working around a formatter is good. in this case, i feel like the uncompromising rules were exposing a bit of an anti-pattern. obviously, your opinion on this may vary wildly. raise ValueError(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"Maecenas vel ligula nec eros finibus metus."
)
No need for the extra variable.My aesthetic taste is less important than getting things done.
If you are not using it, stop arguing and nit picking about your preferences, we, as a community, have more important things to do. It will hurt only a little, I promise.
This is one area Golang got it right with gofmt.
Oh you don't have a pyproject.toml? Well then we have a different problem :)
I'm not how this is related to not having any knobs to tune. Aren't there many ways for code to be consistent with pep8? Isn't advocating for only one version of pep8-consistent code in essence an attempt to supercede pep8?
If there are no knobs to turn (like in gofmt) everyone just has the same settings and you don't have to make sure everyone sets the knobs to the same values.
In this case, if black becomes the standard for defining appropriate style then it is superceding pep8 as the standard for style (many styles consistent with pep8 are not black outputs, so if black's style becomes mandatory, it is a ruling against these previously accepted alternatives).
I really liked it, a lot. What set Black above is it is most of the decisions (if not all, really) makes is how we setup YAPF anyway. I do think it does some small things better, like reformatting function arguments in certain cases (as is highlighted elsewhere in this thread)
If you need configurability, YAPF is the best choice, in my opinion. We still use isort though, because it sorts imports in a much more readable way.
I just wish I could find a suitable replacement for C# development. StyleCop is okay, but I find we have to use `<NoWarn></NoWarn>` .csproj settings on so many little rules and it doesn't auto format (in as so far as I can tell). If your editor supports it, it will use it as a formatting source of truth, though. I just want something that also has a runnable console binary we can use in CI. Maybe I haven't looked at it closely enough.
Sometimes you can convince them to processes an existing file as if it is being typed in and so apply the "as you type" formatter, effectively giving you a stand-alone formatter.
I used to do this with Emacs for C formatting. I don't remember how since I'm a vim user who only figured out enough Emacs for this one thing, and it was a long time ago, but I remember it worked very well. The Emacs C "as you type" formatter was very configurable and I was able to make it almost perfectly match my employer's style.
How's Emacs "as you type" Python formatting?
I personally love black though.
Rust's "cargo fmt" tool is similarly good.
I tried to PR a --use-tabs flag but the PR was rejected without comments. Had to fork Black to be able to use it. Tan is a drop-in replacement that allows --use-tabs (and use-tabs = true in pyproject.toml).
It's not like they can be effective at their job either without the ability to read 3rd party code, which overwhelmingly will be space indented.
https://www.emacswiki.org/emacs/redshift-indent.el
(Haven't tried the above, but I've done fairly extensive display hacks with emacs in the distant past, so I have a fair amount of confidence that it's not hard).
Furthermore, prettier has a python plugin which does support tabs.
> Differences from Black
> - The default line length is 99 instead of 88 (configurable with --line-length).
> - Single quoted strings are preferred (configurable with --string-normalization none/single/double).
> - Empty lines between classes and defs are treated no differently from other code. The old behavior, which sometimes inserts double empty lines between them, remains available via --special-case-def-empty-lines.
> - The Vim plugin configuration variable for line length is named g:lavender_line_length instead of g:lavender_linelength, for consistency with the other configuration variable names.
https://black.readthedocs.io/en/stable/the_black_code_style....
Black however could fall into this category of worse than no formatter. On my team we have a strong style guide with a lot of well-reasoned, detailed, and consistent rules. One of the main differences to other style guides is that we design our style to make review easier. One of the primary ways of doing this is minimising diff noise.
While Black's vision is to reduce diff noise and design for easier review through a consistent style, it creates more diff noise and has a less consistent style than our style guide, and so we've had many discussions internally about whether it's right for us.
I have no doubt that Black is better than weak/no style guide, and for open source projects the automation it brings would absolutely be the right choice. I just wish it was better at what it sets out to do.
Edit: to address some of the questions raised:
- Yes Black does save time over code review picking on style details, but we already have automated linters for most things we'd raise about style anyway, which negates some of the time saving.
- The easiest example of where Black differs from our style guide and falls down on its promises is formatting lists/function calls/definitions.
For example:
foo = [bar, bar]
When reaching the line length limit, we will turn this into: foo = [
bar,
baz,
quux,
]
However Black will format this first as: foo = [
bar, baz, quux
]
Only when it goes on a few more characters does it then format into the way we'd go straight to. This means that there's more diff noise more of the time, and when reading code there are 3 forms of this construction that one must be aware of, rather than the 2 forms that we have, meaning the code is less consistently formatted.This is picky, yes, but the point of Black is to be picky, and in a team where we can have a very good shared understanding of a style, and where we do already have that style, Black is much less convincing.
I’m a very big fan of black, and had disliked a few choices. But it’s saved our team literally dozens of hours of nit picking and style fixes. It’s so good to never have to critique style and just focus on function.
- Split to as many lines as possible in order to avoid suddenly going from one line to many lines and vice versa when a line crosses a specified line length
- Add trailing commas wherever possible
I'm also curious about the issues you've had with it.
Many discussions? I've never been on a project where code style required anything more than 10 minutes. The tech lead would ask: "everybody okay with the defaults of this linter/editor/whatever" and we'd reply "sure".
How much time did those many discussions take, and what were the reasons you needed to put in that effort?