This is great except for the enforcement of double-quotes around all strings and spaces around slice operators. These two choices contradict the standard Python documentation, most of the standard library, and the behaviour of the interpreter itself.
When the language itself has an established convention, Black should follow that convention, not fight it. These two weird choices just generate needless churn, which is surprising as it seems Black has quite the opposite goal.
It's a shame, because all the other design choices in Black are pretty good!
Colons in slices are implemented to the letter of PEP 8. Your disagreement here probably stems from pycodestyle mistakenly enforcing a different rule (no spaces before colons on if-statements, defs, and so on) in the slice context.
The language itself doesn't have an established standard in terms of string quote usage. If it did, Black would follow it. What repr() does is a weak indicator and how the documentation is written is random, there was not only no enforcement as to which quotes to use, there wasn't even a recommendation. Black standardizes on double quotes since it has clear benefits whereas the other option does not.
I have to admit that I was very excited to begin enforcing black on all of our projects at work - until the double quotes decision. I’m used to single quotes everywhere (except docstrings!).
I’m probably going to still move to black but I know I’m likely to face some pushback now on this one choice, and I don’t yet have the will to defend it.
I also know I’m being mostly unreasonable .. “why is this opinionated tool not perfectly aligned with MY opinions??” .. but feelings.
That's the #1 complaint I have (and hear) about Black. Everything else, I can live with. And honestly, I can live with using double quotes everywhere, especially when I can type single quotes and then let it re-write them. It's just that they currently look really, really odd to me because that's not how Python is traditionally written.
Actually I prefer standardizing on double quotes and I do that in my code on a regular basis. I know some people use a mix, sometimes single quotes and sometimes double quotes, which is fine, but I prefer consistency in this case.
Coming from a C background I always stuck with double quotes for strings. Single quotes are used for characters in C. I think double quotes are better anyway because an apostrophe is much more likely to turn up in a string than a double quote itself. I rarely have to manually escape quotes inside strings.
At Facebook, we are now using prettier[1] on all our JavaScript files, a growing number of Hack files are formatted with Hackfmt[2] and now black is being rolled out for Python. It's a really exciting time :)
Hey Vjeux. What does black mean for the prettier python plugin[1]? I had high hopes to move over all projects to prettier (for JS/Python). Is there going to be any merging between prettier python and black? Do you recommend one over the other?
Wow, that website is hard to use! You can’t touch scroll down on iOS unless you click towards the bottom of the page as scrolls in the animation zone are ignored.
In case of credit where credit’s due, is gofmt where the concept of auto-formatting syntax became mainstream? At first I hated it because I thought I had a style, but later on I enjoyed the consistency far more than I enjoyed my signature approach.
A programming language has an opinion on how you build software with it, so it’s appreciated that it also has an opinion on how you should write it so that it remains consistent and easy to follow. No debate about where to put braces or semicolons or whatever else doesn’t matter when putting something in front of your users.
It feels like dumbing down in a way, which is sad, but I think this is more for the benefit of collaboration than individualism or artistic intent. In that case you either disable the tool or refuse to use it.
In every other case, you’ve automated away almost every nitpick from a code review.
When i heard about gofmt, i hated it. I wanted choice. Then i realised i loved python because it forced people to indent. I gave black a try. I still hate some style decisions, but who cares ? The benefits are far too great to pass up.
I think the unconfigurability of gofmt may be its greatest strength. Indent, etc. have existed for years but getting everyone to just agree on a reasonable style is invaluable. GNU Indent's default style is one that (almost) nobody uses and the number of available options is overwhelming. rustfmt's default style is fine, but it also has an overwhelming number of options, in addition to not handling line wrapping well. ocp-indent is the only other formatter I've used that's as painless as gofmt.
In the Perl world auto-formatting syntax is old hat, though of course (it being Perl) the formatter is highly configurable[0]. So in practice you get consistency within an organization, but perhaps not over time.
Coming from that background I was initially put off by the lack of options with gofmt, but once I realized the whole world of go coders would be using the same formatting I immediately fell in love with it.
Visual studio has done auto formatting of c# since at least 2005. Ive used many other tool chains that does it before go became popular. As others noted, the biggest difference with gofmt is probably the lack of configuration.
As usual the practice can be traced back a long time to Lisp. It's completely expected that Lisp code will be formatted in the standard way. This isn't a Go thing.
I really want to use Black, but we have a particular style point that we’d miss so much that we haven’t adopted it yet...
Double quotes for strings that need to be human readable, single quotes otherwise.
This makes it so obvious when something is going to be sent to the user, we find it really useful. That said, I think Black’s appeal is it’s uncompromising nature, so I wouldn’t ask it to change. Adding the option to turn off quote formatting would probably go against its vision. Also, it could be argued that we should use the internationalisation functions to denote strings sent to the user, but hey we don’t do i18n yet.
For now, this, and one or two places that it fails to have an opinion (number of lines after imports) are keeping us from using it.
Do you find your team enforcing the string quote rule consistently? It seems to me like it's easy to miss at times as automatic enforcement is impossible. Are there no cases where a string that wasn't originally planned to be user-visible ends up being so? I've heard this idea at times but when I looked at actual codebases it turns out it's more of an aspiration than an actual rule. And if you can't depend on it, why have it?
As for number of lines after imports, how is a lack of enforcement there stopping you from using the tool? Black enforces one line but is fine if you put two (on module level). In general, if you give up on the tool due to a missing rule, you end up having to manually enforce tens of other rules that you'd otherwise be free from.
One idea you might want to consider is to create a global function, let’s call it h() and pass all your human readable strings through it, like so h(“hello world”). This function, simply returns the same string. This is more explicit than relying on quote types. It also allows you to do interesting things such as logging everything to a text file and running a spell checker on it, or checking for wrongly encoded string, ...etc.
Why would you have strings that are not supposed to be human readable? Machine to machine should ideally use bytearray (b""-strings) or integer enums for that purpose.
Then you also have the ambiguity of what is considered human readable, is an xml document human readable? Http headers? File paths? Urls? Is a programmer considered human?
I love it. Something I always wish for with linters is an easy way to run them only for the lines changed in a particular diff, to allow a codebase to gradually converge on consistency without breaking git blame by reformatting everything. Is there a nice way to do that for any Python linter?
At Facebook we only tell you about lint violations for the lines you touch using arcanist from phabricator[1]. While it works great for most lint warnings, this hasn't worked that well for code formatters.
The most successful strategy was to add a flag in the file (@format in the header) to tell that a file is automatically formatted. The immediate benefit is that we enable format on save for developers on those files when they use Nuclide (>90% of penetration for JavaScript and Hack).
The other advantage is that when we release a new version of the formatter, we can re-run it on all those files so that people don't have lint warnings on code they already formatted in the past.
With that setup, there's a strong incentive for individual engineers to run the formatter on their team codebase in one PR and then everyone benefits from now on.
I'm so glad this is a thing. I get so tired of people arguing about the small stuff. Sometimes too much freedom is a bad thing. It seems okay at first, and you try to be as democratic as you can with your team, and then someone wants something really wonky, and PEP8 and PEP257 don't say it's absolutely wrong after all, and shit just wastes time.
I don't agree with every detail--double quotes as default is going to be hard for me to adjust to--but the things I don't agree with aren't as important to me as being able to set it and forget it and stop debating it every so often.
This is the gofmt the python world needs. As far as I'm concerned this is the new standard.
Even if your team is totally on board with your style guide, everyone wants to stay pep8/257 compliant, no arguments, you use linters to warn about errors, etc. you will still have some instances of people committing code that breaks the guidelines.
Either it gets caught in code review and you have to waste time with nitpicking, or worse it makes it through to the repo and now you have to make a commit to fix what amounts to a typo.
Autoformatting with a unified, consistent tool means that you remove all those problems.
> I don't agree with every detail--double quotes as default is going to be hard for me to adjust to--but the things I don't agree with aren't as important to me as being able to set it and forget it and stop debating it every so often.
That's the key part for me, too: Black offers the freedom of not needing to waste time talking about things which really don't matter. No more wasting time on code review where the real issues are obscured by sloppy whitespace, idiosyncratic formatting preferences, etc.
I also had a preference for single quotes but … every file in every project I work on is consistent as soon as I hit save and I certainly don't care enough not to let that outweigh a minor aesthetic point.
Love the idea of eliminating formatting debates when writing Python.
At the risk of being redundant, I also raise an eyebrow at the choice to prefer double quotes for strings. My company standardized on single quotes, mainly to be consistent with repr and also encourage the use of double quotes in messages displayed to the user.
Everything else seems in order. I might increase the line width to 90 just to use an easier value to remember when configuring editors and other tools ;)
The problem with code formatters for Python is that you can't just break lines using whitespace; you need to insert symbols, ideally parentheses. For example, if you need to break this line of code:
I wanted to add a bit of positivity and mention that I'm really liking how the black project is approaching problems. For example, a few people brought up fluent interfaces[0] as an issue. There were many opinions about the right and wrong thing to do, but discussion got to a very pragmatic decision I feel.
Then there were requests to add command line arguments specifically so that tools could integrate with black that were added almost immediately.
Congrats on gaining so much traction so quickly, and thanks for listening to users (when it makes sense).
Has anyone rolled this out to an existing codebase? What's the best practice? A single commit that reformats the whole codebase? How do you avoid creating merge hell?
You can see how this was done for Fabric, PyPA/Warehouse, and pytest.
General guidelines:
1. One commit with only the automatic formatting. Afterwards you'll be able to skip over it easily with `git hyper-blame` or `git blame $BLACK_REV^ -- $FILE`.
2. Avoid leaving open pull requests. If you do, after landing the blackening commit, blacken all pull requests, too. They shouldn't conflict then.
3. Set up enforcement with pre-commit or CI (you can run `black --check` on Travis or similar).
[+] [-] zestyping|7 years ago|reply
When the language itself has an established convention, Black should follow that convention, not fight it. These two weird choices just generate needless churn, which is surprising as it seems Black has quite the opposite goal.
It's a shame, because all the other design choices in Black are pretty good!
[+] [-] ambivalence|7 years ago|reply
The language itself doesn't have an established standard in terms of string quote usage. If it did, Black would follow it. What repr() does is a weak indicator and how the documentation is written is random, there was not only no enforcement as to which quotes to use, there wasn't even a recommendation. Black standardizes on double quotes since it has clear benefits whereas the other option does not.
[+] [-] jsmeaton|7 years ago|reply
I’m probably going to still move to black but I know I’m likely to face some pushback now on this one choice, and I don’t yet have the will to defend it.
I also know I’m being mostly unreasonable .. “why is this opinionated tool not perfectly aligned with MY opinions??” .. but feelings.
[+] [-] kstrauser|7 years ago|reply
[+] [-] waleedka|7 years ago|reply
[+] [-] fishywang|7 years ago|reply
> It will replace the latter with the former as long as it does not result in more backslash escapes than before.
And I think that's good enough (and in compliance with PEP8)
[+] [-] unknown|7 years ago|reply
[deleted]
[+] [-] icebraining|7 years ago|reply
[+] [-] aphextron|7 years ago|reply
[+] [-] cup-of-tea|7 years ago|reply
[+] [-] vjeux|7 years ago|reply
[1] https://prettier.io/ [2] https://github.com/facebook/hhvm/blob/master/hphp/hack/src/h...
[+] [-] nickpresta|7 years ago|reply
Thanks
[1] https://github.com/prettier/plugin-python
[+] [-] ComputerGuru|7 years ago|reply
[+] [-] philip1209|7 years ago|reply
[+] [-] pomber|7 years ago|reply
[+] [-] ljm|7 years ago|reply
A programming language has an opinion on how you build software with it, so it’s appreciated that it also has an opinion on how you should write it so that it remains consistent and easy to follow. No debate about where to put braces or semicolons or whatever else doesn’t matter when putting something in front of your users.
It feels like dumbing down in a way, which is sad, but I think this is more for the benefit of collaboration than individualism or artistic intent. In that case you either disable the tool or refuse to use it.
In every other case, you’ve automated away almost every nitpick from a code review.
[+] [-] sametmax|7 years ago|reply
[+] [-] platinumrad|7 years ago|reply
[+] [-] biztos|7 years ago|reply
Coming from that background I was initially put off by the lack of options with gofmt, but once I realized the whole world of go coders would be using the same formatting I immediately fell in love with it.
[0]: https://metacpan.org/pod/distribution/Perl-Tidy/bin/perltidy
[+] [-] iainmerrick|7 years ago|reply
The earliest implementation I know of was COMAL, a very clean and tidy version of BASIC, I think dating from around 1980.
A lot of 80s micro BASICs did some level of auto-formatting purely as a side-effect of the source code being stored in tokenized form to save memory.
[+] [-] Too|7 years ago|reply
[+] [-] cup-of-tea|7 years ago|reply
[+] [-] danpalmer|7 years ago|reply
Double quotes for strings that need to be human readable, single quotes otherwise.
This makes it so obvious when something is going to be sent to the user, we find it really useful. That said, I think Black’s appeal is it’s uncompromising nature, so I wouldn’t ask it to change. Adding the option to turn off quote formatting would probably go against its vision. Also, it could be argued that we should use the internationalisation functions to denote strings sent to the user, but hey we don’t do i18n yet.
For now, this, and one or two places that it fails to have an opinion (number of lines after imports) are keeping us from using it.
[+] [-] ambivalence|7 years ago|reply
As for number of lines after imports, how is a lack of enforcement there stopping you from using the tool? Black enforces one line but is fine if you put two (on module level). In general, if you give up on the tool due to a missing rule, you end up having to manually enforce tens of other rules that you'd otherwise be free from.
[+] [-] waleedka|7 years ago|reply
[+] [-] Too|7 years ago|reply
Then you also have the ambiguity of what is considered human readable, is an xml document human readable? Http headers? File paths? Urls? Is a programmer considered human?
[+] [-] nicpottier|7 years ago|reply
[+] [-] bpicolo|7 years ago|reply
[+] [-] alexhill|7 years ago|reply
[+] [-] vjeux|7 years ago|reply
The most successful strategy was to add a flag in the file (@format in the header) to tell that a file is automatically formatted. The immediate benefit is that we enable format on save for developers on those files when they use Nuclide (>90% of penetration for JavaScript and Hack).
The other advantage is that when we release a new version of the formatter, we can re-run it on all those files so that people don't have lint warnings on code they already formatted in the past.
With that setup, there's a strong incentive for individual engineers to run the formatter on their team codebase in one PR and then everyone benefits from now on.
[1] https://secure.phabricator.com/
[+] [-] ianamartin|7 years ago|reply
I don't agree with every detail--double quotes as default is going to be hard for me to adjust to--but the things I don't agree with aren't as important to me as being able to set it and forget it and stop debating it every so often.
This is the gofmt the python world needs. As far as I'm concerned this is the new standard.
Well done.
[+] [-] kungtotte|7 years ago|reply
Either it gets caught in code review and you have to waste time with nitpicking, or worse it makes it through to the repo and now you have to make a commit to fix what amounts to a typo.
Autoformatting with a unified, consistent tool means that you remove all those problems.
[+] [-] acdha|7 years ago|reply
That's the key part for me, too: Black offers the freedom of not needing to waste time talking about things which really don't matter. No more wasting time on code review where the real issues are obscured by sloppy whitespace, idiosyncratic formatting preferences, etc.
I also had a preference for single quotes but … every file in every project I work on is consistent as soon as I hit save and I certainly don't care enough not to let that outweigh a minor aesthetic point.
[+] [-] curtis|7 years ago|reply
I may be in a minority, but I do not want to cede control over minutiae of hand-formatting. Am I the only person that feels this way?
[+] [-] davidfstr|7 years ago|reply
At the risk of being redundant, I also raise an eyebrow at the choice to prefer double quotes for strings. My company standardized on single quotes, mainly to be consistent with repr and also encourage the use of double quotes in messages displayed to the user.
Everything else seems in order. I might increase the line width to 90 just to use an easier value to remember when configuring editors and other tools ;)
[+] [-] epr|7 years ago|reply
[+] [-] aldanor|7 years ago|reply
[+] [-] 49bc|7 years ago|reply
Exactly why every language, from here until the end of time, should have a “go fmt” equivalent.
[+] [-] quietbritishjim|7 years ago|reply
[+] [-] jsmeaton|7 years ago|reply
Then there were requests to add command line arguments specifically so that tools could integrate with black that were added almost immediately.
Congrats on gaining so much traction so quickly, and thanks for listening to users (when it makes sense).
[0] https://github.com/ambv/black/issues/67
[+] [-] erikig|7 years ago|reply
[+] [-] zaius|7 years ago|reply
[+] [-] ambivalence|7 years ago|reply
General guidelines:
1. One commit with only the automatic formatting. Afterwards you'll be able to skip over it easily with `git hyper-blame` or `git blame $BLACK_REV^ -- $FILE`.
2. Avoid leaving open pull requests. If you do, after landing the blackening commit, blacken all pull requests, too. They shouldn't conflict then.
3. Set up enforcement with pre-commit or CI (you can run `black --check` on Travis or similar).
4. Don't forget the repo badge ;-)
[+] [-] ra7|7 years ago|reply
[+] [-] ambivalence|7 years ago|reply
[+] [-] joobus|7 years ago|reply
Figured it out:
`autocmd BufWritePre *.py Black`
[+] [-] crooked-v|7 years ago|reply
[+] [-] philosopherlawr|7 years ago|reply
[+] [-] unknown|7 years ago|reply
[deleted]
[+] [-] hrez|7 years ago|reply