Black – Uncompromising Python code formatter
github.com
github.com
I super dislike black's formatting, and I think it's really rare to actually see it in codebases. It wraps weirdly (sometimes not at all). I'd prefer to use yapf, but last I checked it still crashes on "f-strings".
Here's a small example:
basket.add({
apple.stem
for satchel in satchels
for apple in satchel
})
Black formats this as: basket.add(
{
apple.stem
for satchel in satchels
for apple in satchel
}
)
I've never seen Python code like that.I totally believe using a formatter is good practice. Black is in a challenging position of coming into a community with a lot of existing code and customs, and I get that. But I also think that's an opportunity, rather than having to guess at what is good, there's a wealth of prior art to look at. I wish it had done this, rather than essentially codify the author's style.
black isn't an uglifier/minifier. it's undoubtedly readable.
>predictable
why?
stems = {
apple.stem for satchel in satchels for apple in satchel
}
basket.add(stems)
I concede that without black it wouldn't have made sense to make that refactoring, but since I really want to use an autoformatter, and black is the best autoformatter I have, I'd rather restructure my code slightly so that I can just use black 100% all the time.You always end up adapting to the tool, while adapting the tool to you
Until you oneday reach a perfect harmony with your tool... until you introduce another one, and the equilibrium must once again be found.
Also of note, this is a general principle/behavior (eg you and your furniture..!)
I’m kind of thinking of it as something like baking some exercise into your day by putting a walk into your commute: the little nudge of not fighting the tool on something minor means you don’t skip little things, and over time that adds up more than it seems at first.
My understanding is that by using Black you're saying I choose to not express my opinions about formatting aesthetics and delegate that decision to Black instead.
Which, as a longtime Go dev and now Rust dev, I love formatters that are opinionated. I don't always love what Gofmt or Rustfmt do, but I definitely like consistency that the community has in code style.
So I don't care what Black thinks - I care what, hopefully, everyone uses. Though, I could see a situation where formatting can be altered and the project has a format config. Meaning that while code fmt differs between projects, it would be consistent among all devs working on X projects.
I was initially grumpy about my org adopting black because I preferred single quotes, but the level of standardization is a huge win in my book. I never even think about my code style anymore, I just write it and then run black.
To be clear though, in your example, it would format it as:
basket.add({apple.stem for satchel in satchels for apple in satchel})
It might also format it as basket.add(
{apple.stem for satchel in satchels for apple in satchel}
)
It only formats like your example if the statement is much further indented I believeIn this particular case, that may result in code that breaks with tradition. But I can't see a way to preserve the tradition without creating special or edge cases. For example, we can't follow the first option and get clean formatting with a function like zip. You'll have a train wreck of bad options about where to put the braces and how to place the comprehension's body in relation to the braces that enclose it. Versus, with Black's style, the answer is easy and straightforward, because you just do it the same way you would anywhere else:
zipped = zip(
{
apple.stem
for satchel in satchels
for apple in satchel
},
{
apple.core
for satchel in satchels
for apple in satchel
}
)
IMO, that's good, even if it isn't what we're all used to. Having a bunch of special cases just to match what someone might think is more aesthetically pleasing in specific situations is not a desirable feature in a set of autoformatting rules. zipped = zip({
apple.stem
for satchel in satchels
for apple in satchel
}, {
apple.core
for satchel in satchels
for apple in satchel
}) zipped = {apple.stem: apple.core
for satchel in satchels
for apple in satchel}Not sure what came about of object comprehensions though.
zipped = zip({
apple.stem
for satchel in satchels
for apple in satchel
},
someList
)
or zipped = zip({
apple.stem
for satchel in satchels
for apple in satchel
}, someList)
(Which admittedly looks reasonably tidy, but starts to get gross again if we start looking at 3-ary functions.)You've also got to contend with the first not being a comprehension meaning that the comprehension's indenting can't so easily be kept the same:
zipped = zip(
someList,
{
apple.stem
for satchel in satchels
for apple in satchel
}
)
Which is where I was going with the comment about edge cases. Personally, I don't want formatting rules where you might decide to format the arguments to a function in different ways depending on the specifics of what other arguments the function has. I like simple. Give me one rule for when it all fits on one line, and another rule for when it doesn't. And make sure neither of the rules causes me to have to re-indent things just because a function picked up an additional argument. And make sure that the rules are completely oblivious to the function's arity.Maybe that would fail to put long strings on their own line?
There is a great autoformatter that does not have this issue. Using it guarantees that you'll never have to stick with an outdated version of a language because your autoformatter of choice hasn't been updated for the current one, or even worse, is not maintained anymore.
It's called "cat".
Precisely. I wonder why ML has not been applied here.
Yeah, I keep seeing people singing the praises of black and I'm really dreading the inevitable future where people start acting like this dude's opinion is Correct Official Python Style.
Having a standard is more important than the standard being excellent.
Neither is very important, though. It's just formatting and your code will run the same regardless.
And you can see the phenomenon of over-abbreviation by reading a few debates on twitter and repeatedly seeing, "how can you not understand what I tweeted?!"
https://medium.freecodecamp.org/codebyte-why-are-explicit-se...
> Javascript developers
Oh, of course.
Having said that, I've been introducing a lot more colons, since I use TypeScript.
If you're working with others, though, then it becomes very important. I don't think I'm being entirely hyperbolic when I say that inconsistent or poorly-chosen formatting rules are the death of 1,000 cuts for a team's productivity.
There's a tiny but existent cost that's incurred every time formatting rules that aren't diff-stable result in a noisy code review that takes longer to read, or makes it harder for reviewers to discern the real changes from the formatting junk. There's a tiny but existent cost when excess delta makes it harder to gitblame. There's a tiny but existent cost when people have to stop and think about how to format their code manually. Or when they have to stop and debate formatting. Or when they read someone else's code slightly more slowly because different formatting rules make it harder for them to skim it or rely on pattern recognition instead of careful reading to understand its structure.
All those tiny little costs add up to something that's not so tiny. And it's so easy to make it just disappear, for the low low cost of swallowing one's pride, by simply adopting an opinionated autoformatter.
Don't reformat code you didn't otherwise touch. That's just common sense. Common sense autoformatters lack.
> There's a tiny but existent cost when people have to stop and think about how to format their code manually.
I rarely think about how I format my code. When I do, it's because the code is hard to format in a readable way, in which case an autoformatter will produce garbage.
> Or when they have to stop and debate formatting.
"Doctor, it hurts when I do this."
> Or when they read someone else's code slightly more slowly because different formatting rules make it harder for them to skim it or rely on pattern recognition instead of careful reading to understand its structure.
Neglible. To the contrary, different formatting reminds you that you did not write this code and you should read it more carefully because you can't expect its creator to think the way you do.
I've never been able to wrap my head around people having strong opinions on style issues. I'll defer to whoever cares the most on the team and then just do that. When I look at the problems in code bases, rarely has "slightly inconsistent formatting" been at the top of the list.
Because an autoformatter with 10 simple yes/no options has 1024 different ways those options can interact, and an autoformatter with 20 yes/no options has 1,048,576 different ways that they can interact. It's simply not possible to make sure that you're going to get reliably good results in the face of that kind of combinatorial explosion.
Versus, if there's only one way that it will format things, then the people designing the rules have a single stationary target that they can aim at.
If you don't have as powerful a backend as the full clang paraer/lexer on the other hand, I could quickly see things breaking as you described.
Let me take a shot at why it's important.
We spend years peering at code hunting for tiny, miniscule mistakes. Thus we're training ourselves, quite rigorously, to spot minor deviations.
We're also irrational in the moment: our aesthetic sense is bothered by certain patterns, and our social sense wants to assign blame for this "wrongness" to individuals.
An auto-formatter removes a ton of deviations that don't matter, and desocializes the aesthetics.
This saves code reviewers time and stress and helps them focus on what actually matters in the code.
And it only has to save more time than it takes to run "pipenv run black" to be measurably worth it.
I like it because I can document most maintenance tasks as "pipenv sync && pipenv run X" and they Just Work with exactly the library versions specified for that commit.
But definitely look into poetry if you're packaging a library.
Whenever I have time I want to migrate all my pipenv projects to poetry.
It would be nice if pip could act more as a base tool and pass information back to a wrapper.
I'm no longer using it for Python projects.
(Showing up in an HN thread is a neat little milestone for my blog and me. Thanks for sharing!)
The Python community is victim to pipenv's creator's marketing and shoehorning, that's why.
I feel like in every one of these formatter discussions people are waiting to pounce on anyone who takes issue with the formatting. I'm totally down with formatting: prettier, dart_style, rustfmt, gofmt, uncrustify, I use and love them all both professionally and personally (well, gofmt is bad at wrapping but the language is bad at wrapping in general). But in all these cases, these tools are either configurable or they set a standard for how to format code for $lang. Black does neither, which is fine, but its options then are "pick a common convention" or "pick an uncommon convention". All I'm saying is that I wish it had done the former.
It always strikes me as strange that we spend our own effort and time on systems that mandate code style when my unambiguously correct style and my coworkers obviously incorrect style both end up converted to the same AST for any useful work. Why isn't style an entirely local choice, with a higher-level representation of the code stored canonically?
Better question: What wheel did I point towards and suggest be reinvented?
That said, once upgraded, that would be far, far, far superior to text. Our tooling hit the limits of text a long time ago: consider how terrible diffs are at communicating simple operations like indentation changes, or how basic our refactoring is even in the best case scenarios.
Pretty printing.
I'm completely indifferent to autoformatters turning my coworkers' code from one perfectly readable format into another. The "problem" they solve is a ridiculous thing to worry about. Having a standard is not important, it's petty.
What I do dislike is having to fight the autoformatter because for some reason some teams use different settings. I dislike autoformatters turning code into something that is objectively harder to read -- sometimes it's not a matter of taste. Even when they work, I dislike even a second on something that only satisfies other peoples' pettiness. I also dislike git blame being useless because someone reformatted all the code for no good reason.
That's usually a good clue that you've hit real middle-ground.
I blackify my projects once we hit 3 contributors.
I write some garbage-formatted code, press ctrl-s, and the code is formatted automatically.
Even on a single-dev project, I would take a config and just put it there for the convenience it provides me.
If I ever were to code python again, I would probably also use black.
https://github.com/django/deps/blob/master/accepted/0008-bla...
https://groups.google.com/forum/#!topic/django-developers/7G...
> Several developers report that, in their experience, Black made code formatting worse and decreased readability. Concrete examples shown in the discussion were short lists, which Black reformats when they fit on a single line, and vertically aligned comments, which Black is unable to preserve. This is being addressed [0] in Black and is expected to be resolved before Black becomes stable.
It is immensely valuable to be able to look at any Go code, whether in the toolchain, the standard library, or a random stackoverflow snippet, and not have to think about formatting at all.
That's not the case at all. The Go compiler treats an arbitrary few lint issues as compiler errors (e.g. unused imports), code which is not gofmt-formatted isn't a compiler error.
you can't even comment out your code while debugging. annoying as hell.
- reformat the whole codebase
- build (if needed, e.g a C++ project)
- run all tests
The programming workflow is then:
- edit code
- run the 'check' script
- repeat.
I think code formatting is very important for readability, and I think many (subtle) choices about how to make a piece of code more readable are very subjective. These types of tools are just incapable to make those choices because they have no concept of intention.
And some rules make this painfully obvious even in less subjective cases. Eg: black formats dictionaries into a single line if they fit one line, which makes nested structures unreadable if they combine bigger and smaller sub-dictionaries.
In the end, I don't have problems with other peoples' formatting choices; as long as they are sufficiently consistent within their own style, which they usually are, I can live just fine with them even when they go against how I'd do things.
I do have problems with tools that reduce code readability for consistency's sake and argue that these provide little benefit, and may even be detrimental to code quality.
In the example I mentioned, I may sometimes choose to put a small dictionary initialization into a single line if it's just a detail, or may split it into multiple lines if it's important enough for someone reading the code to pay attention to it before going further.
This simply cannot be decided by an automatic formatter without it knowing the code's purpose which, for now, requires a human brain.
Someone mentioned elsewhere that automatic formatters remove the cognitive load of formatting code, but I argue that load is an intrinsic part of programming, because it is (for the most part) the effort of communicating to the next person that comes along.
I have not used Black, but considering it so I am curious about these occasional situations where you want to override auto-formatting
Here's an example snippet by Peter Norvig that is beautifully formatted:
def neighbors4(point):
"The four neighboring squares."
x, y = point
return ( (x, y-1),
(x-1, y), (x+1, y),
(x, y+1))
def neighbors8(point):
"The eight neighboring squares."
x, y = point
return ((x-1, y-1), (x, y-1), (x+1, y-1),
(x-1, y), (x+1, y),
(x-1, y+1), (x, y+1), (x+1, y+1))I you would be fine with 95% of what it does and just want it to ignore the 5% where you care the most, I think the tool could benefit you.
At least that’s how I feel about autoformatting in general.
munge(gidget,
thing1,thing2,thing3);
cmplt(dtypeA,valueA,
dtypeB,valueB);
(Most cases are more subtle (and thus less amenable to "oh, you just need to build a complete static type checker into the formatter") than this, but I wanted an obvious example.) cmplt(
(type_a, value_a),
(type_b, value_b),
)
That's much more clear about the relationship between each pair of values either way, and would get formatted nicely by Black.0: which doesn't have tuples anyway; you could use structs, but it doesn't really work well in context/practice.
1: I don't use python frecently enough to have ready examples of autoformatter stupidity on hand for it.
A better example is a matrix laid out as a grid, which auto-formatters always destroy
mat3x3(
0, a, -b,
-a, 0, c,
b, -c, 0,
) mat3x3(
rowvec3( 0, a, b),
rowvec3(-a, 0, c),
rowvec3( b,-c, 0),
)
Which is probably better, especially with tuples instead of struct{Scalar[3]}. Doesn't fix mat3x3(( 0, a, b),(-a, 0, c),( b,-c, 0))
, though. def cmplt((type_a, value_a), (type_b, value_b)):
return ...
I was sad when they removed argument unpacking in Python 3. I thought it was a really elegant feature of the language.what do you think the result of
def cmplt((type_a, value_a), (type_b, value_b)):
return locals()
is? Now granted, you shouldn't do that, but what you think it is? a dict with 4 keys, right? {'type_a': ..., 'value_b': ...}.That's wrong. It has those four keys, and two more: '.0' and .1', whose values are the packed tuples.
!?!?!
Prettier for JS has a simple solution to this specific problem, and that is to follow the code's lead. If the first element of the object or array starts on the same line as the opening bracket, keep it as a single line if it fits. Otherwise, if the first element starts on a new line, put every element on a new line (explode the collection), even if they would all fit on a single line.
Black should consider doing this instead of the open PR to explode collections if there is a trailing comma[0], which feels... wrong.
Edit: Previous discussion: https://news.ycombinator.com/item?id=17155048
I prefer Black, which has minimal configuration. There's no debate to be had over details that don't matter much in the grand scheme of things. Yeah, maybe it doesn't always look _just_ how I'd like, but I get used it.
And while Black may not be 100% compatible with flake8 out of the box, they are aware of flake8 and document places where it may not be flake8-compatible.
foo = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ]
Black formats it to something more like: foo = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30
]
That's, in my not-so-humble opinion, absolutely atrocious. Compare with how Emacs formats if it I press M-q (with python-mode and EditorConfig): foo = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ]
More readable (again, IMO) and way more compact.The default line length of 88 also seems weird, but at least that's readily configurable to my preferred 80.
If you add a single item to your preferred style, the entire thing has to be reflowed.
For strings, it will format it like he formatted the array, and adding a word will reflow the entire block of text.
months = ["January", "February", "March", ...]
A human can make a smart decision, an autoformatter can't.A good diff will tell you:
foo = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ]
vs. >> foo = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ]
Better ones will underline the offending characters.Even in a case where I need to add an item in the middle, the diff will - again - only start where I actually added an item, and any human can readily see that the rest of the downstream diffs were from the reflow.
Of course, it'd be even better if diff tools were more aware of the format/language of the code being diff'd, at which point it'd be able to say "new element added to foo" instead of reporting on a bunch of reflowed lines.
I know 2 is kind of subjective but when I look at someone elses code and I see obvious mistakes against pep8 I start judging both the person and the code harshly. Perhaps unfair but for the very simple pep8 rules I see it as someone who is not as well versed in Python and perhaps does not care about their code as much.
Overall I just concede that consistency is better than everyones personal tastes. For a startup I think you can get by with just some custom linting but in a larger org I find it much harder to agree on a consistent format unless you are a Python first org. Much easier just to roll Black into the project and go with it.
Worrying about or judging code based on PEP8 is missing the forest for the trees[0]
For example, in JavaScript, there is always a space before a function's opening curly bracket. This is pretty much a global standard, and it's rare to see code that doesn't follow this rule.
However, I'll occasionally see code on Stack Overflow that randomly excludes these spaces. It honestly makes it so much harder to read, and I'm less willing to put in the effort to help them, because they didn't even go to the effort of properly formatting their code. Inconsistent indentation especially kills me because it makes code impossible to read.
Also, imagine blind people coding. I imagine they have a completely different stance on how code should be formatted.
(edit: black has pre-commit support [1], and it's easier than setting up and maintaining your own hooks IMO)
[1] https://github.com/python/black/blob/master/README.md#versio...
Run that target as part of the test
But I'm not sure if making the code easier -- and thus faster -- to read is necessarily a good thing. If the brain parses and analyzes the code in parallel, making it harder to parse could give the analyzing process more time and thus make the review more thorough.
Of course, nothing stops a reviewer from being thorough either way. But making it the path of least resistance makes it more likely.
This is what I've stuffed in my VS code settings:
"python.formatting.provider": "black",
"editor.formatOnSave": true,I run into this philosophical debate at work. In my mind, I don't care much what the resulting code looks like as long as
- it's somewhere in the reasonable spectrum of readablility
- it's consistent and unambiguous
- it never fails for a syntactically valid source file (if it's doing something for syntactically invalid source files, even better, formatting helps me find the error)
There are other opinions though that emphasize minimizing diffs or extensive customization to fit somebody's favorite style (I'm looking at you, rustfmt). Black seems to be right down my alley.
I like auto-formatting, because it makes PRs less stressful to commit, and makes review comments more focused on stuff that actually matters. How exactly the code gets formatted is not something I care much about, just that it happens consistently, and I don't have to think about it.
We use pre-commit with Black and other formatters, such that it formats the code, warns you stuff changed, prevents the commit, and makes you recommit with the formatting patch included.
more .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.1.0
hooks:
- id: end-of-file-fixer
- id: check-json
- id: check-yaml
- repo: https://github.com/asottile/reorder_python_imports
rev: v1.3.4
hooks:
- id: reorder-python-imports
args: [--application-directories=gaia]
language_version: python3
- repo: https://github.com/ambv/black
rev: stable
hooks:
- id: black
language_version: python3
- repo: local
hooks:
- id: eslint
name: eslint
entry: ./frontend/node_modules/.bin/eslint --fix
language: node
language_version: system
files: \.(js|jsx|ts|tsx)$
- repo: https://github.com/prettier/prettier
rev: "1.15.3"
hooks:
- id: prettier
files: \.(yml|yaml|md|json)$
language_version: systemI'm an auto-formatting true believer, but I hate doing code reviews where the author has run a formatting tool that introduced diffs all over parts of the file that they didn't actually touch. It makes it really hard to review the actual change, and you have to worry about missing something.
With something like ClangFormat's '--lines' flag, you can configure the tool to only modify the lines that the author actually changed. This removes most of the pain that comes with adopting an auto-formatting tool, and your codebase will gradually converge to the fully auto-formatted state over time.
This also makes it easier for to introduce improvements to the formatting tool itself, because the improvements won't immediately force a bunch of diffs on code that was already "blessed" by the tool.
As I mentioned above, formatting only the diffs also removes most of the pain of any changes to the formatting tool itself that aren't diff-stable.
Teach them to commit properly:
1. Run an autoformatter on the file
2. Commit
3. Make desired changes
4. Commit again
The same principle applies to refactoring as well, you want to keep your commits 'atomic' aka containing a single unit of work. Autoformatting and changing the code are two separate units.
Happy Black user over here!
Go's formatter adjusts whitespace within a line and will add or remove blank lines, but it doesn't change line breaks and has no opinion on the maximum length of a line. Other formatters work differently.
But the part that drives me crazy is this...
# in:
ImportantClass.important_method(exc, limit, lookup_lines, capture_locals, extra_argument)
# out:
ImportantClass.important_method(
exc, limit, lookup_lines, capture_locals, extra_argument
)
instead of ImportantClass.important_method(exc, limit, lookup_lines,
capture_locals, extra_argument)
which to my eyes is way more readable and understandable. I understand what in some corner cases (if the call is too long that all arguments require its own line) it may be weird, but in those cases, it is showing that you try to do something strange in the first place (too long of a method name or too many elements in the call)Having used both extensively, my biggest grievances (in order) are that there aren't more editors that with good on-save support, that black is relatively slow (compared to gofmt), and that black isn't more opinionated and less configurable.
black --diff
black --check
The first one shows you what's different (so you have logs in your build job), the second one fails your job if there are any diffs. You could just do the second one if you're a fan of the whole brevity thing.
Here’s a reference:
https://github.com/LibraryOfCongress/coding-standards
The CI check can be pretty simple — for example: https://github.com/LibraryOfCongress/concordia/blob/2f813f18...
Here's an example with Prettier:
https://coolaj86.com/articles/server-side-git-hooks-for-code...
https://github.com/simonw/sqlite-utils/blob/master/tests/tes...
If you use Pandas you should be using method chaining and therefore also black.
It's pretty disturbing that people think this is how a manager behaves. Turns out there are reasons beyond aesthetics that people should apply strict code formatting practices.
In the example cited, notice how insubstantial the complaints are? That’s a dead giveaway for someone who is reacting rather than thinking rationally about the goals and benefits. An important distinction to remember here is that we’re talking about something which is safe, fully automatic, and easily integrated into most editors, so the effort to follow it is a few seconds the first time you set it up.
I’ve generally found three classes of reaction to standardizing formatting, linting, and similar style checks: most people just roll with it, some people work through the initial “this is different!” reaction and realize how much easier consistency makes things (it’s been months since code review wasted time on formatting!), and a much group never get over it. I’ve only seen that a couple of times in a couple of decades and those were people who were net losses overall because this was just a symptom of a larger unwillingness to work well with others. The same guys refused to test their code, committed syntax errors or failed merges, wasted time reporting problems due to incredibly hacked up local build environments, etc. The important thing to remember is that those are a vanishingly small part of the community and I would make policy around them only to the extent of figuring out how to keep them from dragging your project down.
Though I think I prefer autopep8
As I mainly use other languages, with formatters with working region support, I went back to autopep8 so I could leave it format region enabled.
x = y[1]['a'] + z[2]['b']
can be broken like this in Black (if it's over the line length limit): x = y[1][
'a'] + z[2]['b']
But it needs brackets inserted so that it can be formatted something like this: x = (
y[1]['a']
+ z[2]['b']
)
You can argue the formatting I've chosen e.g. whether the binary operator should go on the previous line (the above line is what PEP 8 suggests). But surely it's clear that breaking in the indexing bracket is atrocious.It reminds me of the last time Black came up on a Hacker News. I posted the same objection (but hypothetically) and the actual creator of Black replied with a comment along the lines of "you should check for yourself before making a comment like that". By the time I finally did check, the discussion had died down (like this one now has) and not many people saw the reply. As the creator, he must have known that my objection was correct but he posted a low-effort misleading comment that invalidated it. It doesn't give me a great feeling about the project. I realise you couldn't have known that happened but you can see why I find your reply so annoying.
I think the newline-after-bracket behavior looks like some brain damage based on how it likes lists formatted. The complaint I have on if clauses is that it doesn't break at logical operators, but rather at an open-paren, which just ruins the readability of compound expressions.
$ black --skip-string-normalization my_python_script.py
$ git add --patch my_python_script.py
Then I accept or reject all its suggestions (other than the string "normalization" idea which is not our convention) on a case-by-case basis, then `git commit; git reset HEAD --hard`.Especially when working in teams, I couldn't care less about the style itself. As long as it's consistent, super easy to adhere (`black .`) and fairly readable, I'm happy.
https://black.readthedocs.io/en/stable/editor_integration.ht...
If you're paid by the line of code you write
:-)printable_chars = { 33, 34, 35 [...and another few hundred ]
to printable_chars = { 33, 34, 35 [...and another few hundred lines ]
printable_chars = { 33, 34, 35 [...and another few hundred ]
to printable_chars = {
33,
34,
35
[...and another few hundred lines ]
}1. black is not perfect, but it is pretty great
2. vscode is a much better IDE than Atom
Hi Lukasz!!
something like: # nofmt
https://github.com/python/black/blob/master/plugin/black.vim
But does it have an #ignoreformatter directive?
# fmt: off
unformatted code goes here
# fmt: onIt's a major step backward for the Python community.
this_is_my_very_long_function_name_and_here_come_the_args(self,
foo,
bar,
baz)