Work continues as usual with bugfixes and enhancements, but style changes are now introduced under our new `--preview` CLI switch. This allows us to evolve Black's style without too much disruption to users that want consistency. The default style is updated yearly.
Thanks to our maintainers for orchestrating the efforts, especially to our most recent reinforcement Batuhan (@isidentical) who was responsible for our match statement support! A hearty thank you to all of our contributors for pushing Black forward, and to our users for being the reason we do it!
Congratulations. I'm a Python developer of 17+ years and Black is truly a huge blessing in the Python ecosystem.
That said, I'm a little sad to see it's gone stable without adding support for tabs, which would be extremely simple to add at this point (cf. https://github.com/jleclanche/tan/commit/e23c038167528bdacdd...). I have a lot of people using this tab-capable fork, that I did not advertise anywhere.
Łukasz seems to have a personal grudge against tabs which may be why the issue for tab support was closed early on, but there's a plethora of good reasons to support it behind a flag. I don't want to rehash those arguments here on HN but you think you could re-think the approach a bit?
I'd be happy to do a PR if it's not getting rejected right away with "no discussion allowed" like the last one was (before Black was moved to PSF maintainership).
On the contrary, I think it's fundamentally useful to the ecosystem that there be a winner in the tabs-vs-spaces/how-many-spaces debate. Code snippets become portable, developers don't need to adapt when joining a new team, etc. Indeed, https://www.python.org/dev/peps/pep-0008/#indentation has enshrined 4 spaces as the official recommendation. And when the best-in-class formatter enforces this, that's a good thing.
To be sure, I personally would have preferred that 2-spaces win out for compatibility with the Javascript ecosystem (so I am perhaps the furthest from the parent poster on the tabs-spaces spectrum!) but I abandoned my preference in favor of PEP-8 years ago, and doing so has opened far more doors for team productivity than it's closed.
I don't want to wade in or start a debate, but just share my experiences with formatting over the years. Lacking autoformatters in the past, I've worked with coworkers that preferred 2, 3, 4 & even 8 spaces for indentation.
My personal preference is tabs for indentation, spaces for alignment. The reason for this is the customizability that comes with tabs instead of spaces. Any editor worth using for coding has an easily configurable tab stop that you can set to your desired space count. With tabs and proper editor configs, everyone can be happy with how their code looks while remaining absolutely identical with no tools reformatting on checkout or commit (as I've sometimes seen).
For a long time, I was in the 4-space indentation camp. These days, I prefer 2. The reality is, though, I use whatever the codebase I'm working on has as "standard".
Since Black enforces that indents are exactly four spaces, you could configure your editor to render four spaces at the start of a line as two spaces, getting exactly the behaviour you desire from tabs.
An editor plugin for this wouldn't even have to be syntax-aware, except for some rare cases where you are using spaces to nicely align a multiline string.
The proper number of spaces seems to me to be dependent upon the font size. Smaller font, more spaces.
In the olden days, with fixed width fonts on an 80x24 terminal, I think I read somewhere that 3 spaces was optimal (fewest bugs); but that programmers have an aversion to non-multiples of 2. That is why you see 2- or 4-spaces, but not 3. (I think...)
Perhaps my naivete is showing, but I fail to see how an option that allows broader range of use cases suddenly becomes a religious war about spacing.
In the spirit of dev/user freedom, the creator has every right to enforce a standard, regardless of its basis - even if arbitrary - but I find it a little creepy. Then again, the prevailing usage of “opinionated” in dev circles was new to me, as well. What ever happened to design around maximum flexibility AND feature coverage?
Are developers more likely to be “opinionated” in their work if the predominant digital culture of their early career was rewarding of evangelism via self-promotion? Or grew up in an educational era that promoted activism? Are these sorts of issues more common in smaller / person-driven teams vs. corporate behemoths?
e.g., if VS Code were a one-person show vs. a corporate effort, would we risk seeing changelogs like “Insiders 2.20 - lead Architect and Face of the Product removes plug-ins starting with vowels, “because they lacked cohesion and product-centered aesthetics. They looked poopy in list format with most fonts.”
Absurd, to be sure, but what if these decisions don’t step on obvious toes? The average supporter is more likely to tolerate slightly warmer water than hop into another pot, right? And if you stayed in the pot through several degree increases, you’ll feel a sense of Boiling Frog Belonging (TM).
And if you credited the original dictatorial decision for this emergent sense of community, you’d be very much correct.
While I completely agree with all your other reasoning. It should be pointed out that PEP 8 is not intended to be a styling guide for user code, it's intended to be a styling guide for the standard library: https://www.python.org/dev/peps/pep-0008/#introduction
It's nice the broader Python community generally agrees with PEP 8 but it's always a little weird to see it referenced as an authority on styling user code when it is not it's intention and does not claim to be.
One thing I liked about Python was that PEP8 existed and was some sort of fairly aged standard for formatting. I’m not sure why people feel under deviation to suit their personal preferences is more valuable than consistency.
Consistency is not in and of itself valuable. What is valuable is when it makes things clearer, or otherwise easier. Tabs vs spaces has absolutely no effect on my comprehension of the code. Being able to use spaces for alignment would actually help in some cases but oh well, that's not allowed in python. The way black splits [] expressions is actually harmful when it's used in a chain with method calls as is not uncommon in pandas.
to anyone with even the slightest levels of OCD,(like say 95%? of software developers) consistency for the sake of consistency has a lot of value. The reason I like Black is not because of the authors opinions, but because it is consistent (due to the absence of configuration/user preferences).
Environments that prefer tabs just use Tan, or otherwise, those environments just didn't use Black at all.
It's not useful to the ecosystem because those projects not actually using Black and unable to make the switch end up in a worse scenario (hence the fork which at least fixes this). Nobody wins, here; at best, you're unaffected.
Again I invite you to look at Prettier which has had as much of an impact (if not more) on the JS ecosystem as Black did on Python, but does support tab indent (and is opinionated regardless).
The Prettier team has gone on to say they regret giving people several of the configuration options they did though and have a page dedicated to their option philosophy. https://prettier.io/docs/en/option-philosophy.html
Yes, you'll find no mention of regretting adding tab support to prettier on that page.
Key quote: --arrow-parens, --jsx-single-quote, --bracket-same-line and --no-bracket-spacing are not the type of options we’re happy to have.
That's because these are entirely stylistic choices. Tab support is a mechanical one. Worth mentioning as well that Prettier supports multiple languages and tab/spaces is a global option, whereas all of these are very language-specific.
I think one of the great benefits of Black is that it is opinionated. Giving folks the option to select the type of indentation blunts the benefits. If you have a huge code base which mixes tabs and spaces it’s going to be hard to diff and merge code (or even reuse code snippets).
The point of black is that you run it on the same codebase with the same parameters.
Prettier works the exact same way and does have --use-tabs as a parameter. Nobody died. No codebase ended up with mixed tabs and spaces from it. Codebases either do --use-tabs or don't.
Like I said, there are a lot of reasons to allow for this. For one thing, tabs are an accessibility feature, but also it's impossible to use Black in an environment that prefers tabs.
Whereas there's no such thing as "an environment that prefers exactly two spaces after every comma inside tuples", thus you don't need an option for this.
>Yet the more options Prettier has, the further from the above goal it gets. The debates over styles just turn into debates over which Prettier options to use. Formatting wars break out with renewed vigour: “Which option values are better? Why? Did we make the right choices?”
>And it’s not the only cost options have. To learn more about their downsides, see the issue about resisting adding configuration, which has more s than any option request issue.
>So why are there any options at all?
>A few were added during Prettier’s infancy to make it take off at all.
>A couple were added after “great demand.”
>Some were added for compatibility reasons.
Reading this doc it feels like the Prettier team is saying options like tabs/spaces were only added early on to get initial adoption, if it were up to them now there would be far less options to configure at all.
The options in question are some of the more.. fancy ones, and the "history" in question is things such as cross-compatibility with ESLint. Certainly not "tab support". (And I've contributed to Prettier a great deal, FWIW)
There. Now the Python world has a single standard while you are free to use tabs in your checkout. See, you can make all the people happy all the time. :-)
At the risk of repeating myself, I forked Black into Tan and just added --use-tabs. The alternative was "don't use Black". Others are in my situation as well and use Tan, somehow finding it despite it not being advertised anywhere. Hell I had people bugging me to update it a few weeks back.
There's extremely clear demand, I didn't just add a random flag to control how much space should be around parentheses. Switching an existing codebase using tabs to spaces is not always feasible.
That said, TIL about a lot of what's in your link, but it looks like a completely inappropriate solution, I think you can agree.
I shared that link in good faith, not aware of your specific use case. I still think it's for the better that black does not allow tabs, and that your fork is a good solution for shops that need tabs for an existing code base.
Black encourages the Python ecosystem to settle on spaces. There should be some friction involved (more than a switch) to use tabs, otherwise we're likely to see new code using tabs too.
Sorry, I re-read my comment and noticed it sounds way more aggressive than I intended it to be! I love the little hack actually, but it looks like it's really just a hack ;)
And I’m a little sad to see it’s gone stable without adding support for single quotes...
Wait I’m not. As much as I dislike double quotes, if they add an option every time someone is a little sad, we’re just going back to square one. I don’t want to debate styles anymore, ever, and I’m willing to give up my own aesthetics for that.
Congrats to the black team on this release, and thank you scrollaway for your fork. We are in a similar position where we are (for various reasons) stuck on using tabs for an existing project. Luckily it seems like there might be some movement on this front where the maintainer team is at least more receptive to reopening this conversation:
But if you're going to use a tool like Black in the first place, you're already committed to not preserving different formatting styles in existing code. You want to enforce one consistent style everywhere in the code base. And PEP 8 says that means no tabs.
> a personal grudge against tabs
I don't see why there would have to be any personal grudge given the above.
Some teams strongly prefer a longer line length. For code maintained exclusively or primarily by a team that can reach agreement on this issue, it is okay to increase the nominal line length from 80 to 100 characters (effectively increasing the maximum length to 99 characters), provided that comments and docstrings are still wrapped at 72 characters.
PEP-8 is the de-facto standard for python. Why would a formatter for python support anything (such as tabs) that deviates from that? There might be code that does not adhere to PEP-8, but to me this is not a justification, just some people distancing themselves from the python core community.
Tab codebases are PEP8 compliant. It merely says spaces are "preferred". What it disallows is mixing the two. What it also says is to use tabs if the codebase uses tabs, which I can't do with Black; how about that.
Incidentally, PEP8 takes a much stronger stance on line length, says they should be no more than 79 characters, and Black has enough sense not to respect that by default (and... offer an option, because line length, much like tabs for indent, is an accessibility feature).
Unfortunately Black goes with PEP8, and PEP8 recommends spaces. Guido made this call arbitrarily years ago for absolutely nonsensical reasoning (basically came down to that some people use shitty editors that don't handle tabs reasonably) and the entire Python community has had to suffer since.
I'm hoping there will be minimal or even zero style based commits, excepting those related to new Python features. It wouldn't be very Black-like to force a commit of a potentially enormous size on users of the library every year. Probably something you're already thinking about.
I was apprehensive about taking our legacy codebase Black, but zero regrets. Thanks for your work!
Change log: https://black.readthedocs.io/en/latest/change_log.html
Going forward we'll follow our stability policy (https://black.readthedocs.io/en/latest/the_black_code_style/...).
Work continues as usual with bugfixes and enhancements, but style changes are now introduced under our new `--preview` CLI switch. This allows us to evolve Black's style without too much disruption to users that want consistency. The default style is updated yearly.
Thanks to our maintainers for orchestrating the efforts, especially to our most recent reinforcement Batuhan (@isidentical) who was responsible for our match statement support! A hearty thank you to all of our contributors for pushing Black forward, and to our users for being the reason we do it!