chore: import upstream snapshot with attribution
fuzz / fuzz (3.11) (push) Failing after 1s
fuzz / fuzz (3.12) (push) Failing after 1s
build and publish / sdist + pure wheel (push) Failing after 0s
diff-shades / analysis / base / ${{ matrix.mode }} (push) Has been skipped
docs / docs (ubuntu-latest) (push) Failing after 2s
fuzz / fuzz (3.10) (push) Failing after 1s
fuzz / fuzz (3.14) (push) Failing after 0s
lint and format / lint (push) Failing after 1s
diff-shades / configure (push) Failing after 1s
docker / build (linux/amd64) (push) Has been skipped
diff-shades / analysis / target / ${{ matrix.mode }} (push) Has been skipped
fuzz / fuzz (3.13) (push) Failing after 0s
build and publish / generate wheels matrix (push) Failing after 0s
test release tool / test-release-tool (ubuntu-latest, 3.13) (push) Failing after 1s
build and publish / mypyc wheels ${{ matrix.only }} (push) Has been skipped
test / test (ubuntu-latest, 3.10) (push) Failing after 0s
test / test (ubuntu-latest, 3.11) (push) Failing after 1s
test / test (ubuntu-latest, 3.13) (push) Failing after 0s
test / test (ubuntu-latest, pypy3.11-v7.3.22) (push) Failing after 1s
test / test (ubuntu-latest, 3.15) (push) Failing after 1s
test release tool / test-release-tool (ubuntu-latest, 3.15) (push) Failing after 0s
zizmor / zizmor (push) Failing after 0s
test release tool / test-release-tool (ubuntu-latest, 3.12) (push) Failing after 4s
test release tool / test-release-tool (ubuntu-latest, 3.14) (push) Failing after 3s
test / uvloop (ubuntu-latest) (push) Failing after 1s
test / test (ubuntu-latest, 3.14) (push) Failing after 1s
test / test (ubuntu-latest, 3.12.10) (push) Failing after 5s
docker / build (linux/arm64) (push) Has been cancelled
docker / push (push) Has been cancelled
docs / docs (windows-latest) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.14) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.15) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.12) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.13) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.14) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.15) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.12) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.11) (push) Has been cancelled
test / test (macOS-latest, 3.12.10) (push) Has been cancelled
test / test (macOS-latest, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.14) (push) Has been cancelled
test / test (macOS-latest, 3.15) (push) Has been cancelled
test / test (macOS-latest, pypy3.11-v7.3.22) (push) Has been cancelled
test / test (windows-11-arm, 3.11) (push) Has been cancelled
test / test (windows-11-arm, 3.12.10) (push) Has been cancelled
test / test (windows-11-arm, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.10) (push) Has been cancelled
test / coveralls-finish (push) Has been cancelled
test / uvloop (macOS-latest) (push) Has been cancelled
test / uvloop (windows-11-arm) (push) Has been cancelled
test / uvloop (windows-latest) (push) Has been cancelled
test / test (windows-11-arm, 3.14) (push) Has been cancelled
test / test (windows-11-arm, 3.15) (push) Has been cancelled
test / test (windows-latest, 3.10) (push) Has been cancelled
test / test (windows-latest, 3.11) (push) Has been cancelled
test / test (windows-latest, 3.12.10) (push) Has been cancelled
test / test (windows-latest, 3.13) (push) Has been cancelled
test / test (windows-latest, 3.14) (push) Has been cancelled
test / test (windows-latest, 3.15) (push) Has been cancelled
test / test (windows-latest, pypy3.11-v7.3.22) (push) Has been cancelled
diff-shades / compare / ${{ matrix.mode }} (push) Has been cancelled
fuzz / create-issue (push) Has been cancelled
build and publish / publish-mypyc (push) Has been cancelled
build and publish / publish-hatch (push) Has been cancelled
fuzz / fuzz (3.11) (push) Failing after 1s
fuzz / fuzz (3.12) (push) Failing after 1s
build and publish / sdist + pure wheel (push) Failing after 0s
diff-shades / analysis / base / ${{ matrix.mode }} (push) Has been skipped
docs / docs (ubuntu-latest) (push) Failing after 2s
fuzz / fuzz (3.10) (push) Failing after 1s
fuzz / fuzz (3.14) (push) Failing after 0s
lint and format / lint (push) Failing after 1s
diff-shades / configure (push) Failing after 1s
docker / build (linux/amd64) (push) Has been skipped
diff-shades / analysis / target / ${{ matrix.mode }} (push) Has been skipped
fuzz / fuzz (3.13) (push) Failing after 0s
build and publish / generate wheels matrix (push) Failing after 0s
test release tool / test-release-tool (ubuntu-latest, 3.13) (push) Failing after 1s
build and publish / mypyc wheels ${{ matrix.only }} (push) Has been skipped
test / test (ubuntu-latest, 3.10) (push) Failing after 0s
test / test (ubuntu-latest, 3.11) (push) Failing after 1s
test / test (ubuntu-latest, 3.13) (push) Failing after 0s
test / test (ubuntu-latest, pypy3.11-v7.3.22) (push) Failing after 1s
test / test (ubuntu-latest, 3.15) (push) Failing after 1s
test release tool / test-release-tool (ubuntu-latest, 3.15) (push) Failing after 0s
zizmor / zizmor (push) Failing after 0s
test release tool / test-release-tool (ubuntu-latest, 3.12) (push) Failing after 4s
test release tool / test-release-tool (ubuntu-latest, 3.14) (push) Failing after 3s
test / uvloop (ubuntu-latest) (push) Failing after 1s
test / test (ubuntu-latest, 3.14) (push) Failing after 1s
test / test (ubuntu-latest, 3.12.10) (push) Failing after 5s
docker / build (linux/arm64) (push) Has been cancelled
docker / push (push) Has been cancelled
docs / docs (windows-latest) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.14) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.15) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.12) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.13) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.14) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.15) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.12) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.11) (push) Has been cancelled
test / test (macOS-latest, 3.12.10) (push) Has been cancelled
test / test (macOS-latest, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.14) (push) Has been cancelled
test / test (macOS-latest, 3.15) (push) Has been cancelled
test / test (macOS-latest, pypy3.11-v7.3.22) (push) Has been cancelled
test / test (windows-11-arm, 3.11) (push) Has been cancelled
test / test (windows-11-arm, 3.12.10) (push) Has been cancelled
test / test (windows-11-arm, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.10) (push) Has been cancelled
test / coveralls-finish (push) Has been cancelled
test / uvloop (macOS-latest) (push) Has been cancelled
test / uvloop (windows-11-arm) (push) Has been cancelled
test / uvloop (windows-latest) (push) Has been cancelled
test / test (windows-11-arm, 3.14) (push) Has been cancelled
test / test (windows-11-arm, 3.15) (push) Has been cancelled
test / test (windows-latest, 3.10) (push) Has been cancelled
test / test (windows-latest, 3.11) (push) Has been cancelled
test / test (windows-latest, 3.12.10) (push) Has been cancelled
test / test (windows-latest, 3.13) (push) Has been cancelled
test / test (windows-latest, 3.14) (push) Has been cancelled
test / test (windows-latest, 3.15) (push) Has been cancelled
test / test (windows-latest, pypy3.11-v7.3.22) (push) Has been cancelled
diff-shades / compare / ${{ matrix.mode }} (push) Has been cancelled
fuzz / create-issue (push) Has been cancelled
build and publish / publish-mypyc (push) Has been cancelled
build and publish / publish-hatch (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,505 @@
|
||||
# The _Black_ code style
|
||||
|
||||
## Code style
|
||||
|
||||
_Black_ aims for consistency, generality, readability and reducing git diffs. Similar
|
||||
language constructs are formatted with similar rules. Style configuration options are
|
||||
deliberately limited and rarely added. Previous formatting is taken into account as
|
||||
little as possible, with rare exceptions like the magic trailing comma. The coding style
|
||||
used by _Black_ follows PEP 8 in spirit and enforces a consistent subset of its
|
||||
formatting recommendations. It does not implement every style rule covered by PEP 8.
|
||||
|
||||
This document describes the current formatting style. If you're interested in trying out
|
||||
where the style is heading, see [future style](./future_style.md) and try running
|
||||
`black --preview`.
|
||||
|
||||
### How _Black_ wraps lines
|
||||
|
||||
_Black_ ignores previous formatting and applies uniform horizontal and vertical
|
||||
whitespace to your code. The rules for horizontal whitespace can be summarized as: do
|
||||
whatever makes `pycodestyle` happy.
|
||||
|
||||
As for vertical whitespace, _Black_ tries to render one full expression or simple
|
||||
statement per line. If this fits the allotted line length, great.
|
||||
|
||||
```python
|
||||
# in:
|
||||
|
||||
j = [1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
|
||||
# out:
|
||||
|
||||
j = [1, 2, 3]
|
||||
```
|
||||
|
||||
If not, _Black_ will look at the contents of the first outer matching brackets and put
|
||||
that in a separate indented line.
|
||||
|
||||
```python
|
||||
# in:
|
||||
|
||||
ImportantClass.important_method(exc, limit, lookup_lines, capture_locals, extra_argument)
|
||||
|
||||
# out:
|
||||
|
||||
ImportantClass.important_method(
|
||||
exc, limit, lookup_lines, capture_locals, extra_argument
|
||||
)
|
||||
```
|
||||
|
||||
If that still doesn't fit the bill, it will decompose the internal expression further
|
||||
using the same rule, indenting matching brackets every time. If the contents of the
|
||||
matching brackets pair are comma-separated (like an argument list, or a dict literal,
|
||||
and so on) then _Black_ will first try to keep them on the same line with the matching
|
||||
brackets. If that doesn't work, it will put all of them in separate lines.
|
||||
|
||||
```python
|
||||
# in:
|
||||
|
||||
def very_important_function(template: str, *variables, file: os.PathLike, engine: str, header: bool = True, debug: bool = False):
|
||||
"""Applies `variables` to the `template` and writes to `file`."""
|
||||
with open(file, 'w') as f:
|
||||
...
|
||||
|
||||
# out:
|
||||
|
||||
def very_important_function(
|
||||
template: str,
|
||||
*variables,
|
||||
file: os.PathLike,
|
||||
engine: str,
|
||||
header: bool = True,
|
||||
debug: bool = False,
|
||||
):
|
||||
"""Applies `variables` to the `template` and writes to `file`."""
|
||||
with open(file, "w") as f:
|
||||
...
|
||||
```
|
||||
|
||||
If a data structure literal (tuple, list, set, dict) or a line of "from" imports cannot
|
||||
fit in the allotted length, it's always split into one element per line. This minimizes
|
||||
diffs as well as enables readers of code to find which commit introduced a particular
|
||||
entry. This also makes _Black_ compatible with
|
||||
[isort](../guides/using_black_with_other_tools.md#isort) with the ready-made `black`
|
||||
profile or manual configuration.
|
||||
|
||||
You might have noticed that closing brackets are always dedented and that a trailing
|
||||
comma is always added. Such formatting produces smaller diffs; when you add or remove an
|
||||
element, it's always just one line. Also, having the closing bracket dedented provides a
|
||||
clear delimiter between two distinct sections of the code that otherwise share the same
|
||||
indentation level (like the arguments list and the docstring in the example above).
|
||||
|
||||
(labels/why-no-backslashes)=
|
||||
|
||||
_Black_ prefers parentheses over backslashes, and will remove backslashes if found.
|
||||
|
||||
```python
|
||||
# in:
|
||||
|
||||
if some_short_rule1 \
|
||||
and some_short_rule2:
|
||||
...
|
||||
|
||||
# out:
|
||||
|
||||
if some_short_rule1 and some_short_rule2:
|
||||
...
|
||||
|
||||
|
||||
# in:
|
||||
|
||||
if some_long_rule1 \
|
||||
and some_long_rule2:
|
||||
...
|
||||
|
||||
# out:
|
||||
|
||||
if (
|
||||
some_long_rule1
|
||||
and some_long_rule2
|
||||
):
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
Backslashes and multiline strings are one of the two places in the Python grammar that
|
||||
break significant indentation. You never need backslashes, they are used to force the
|
||||
grammar to accept breaks that would otherwise be parse errors. That makes them confusing
|
||||
to look at and brittle to modify. This is why _Black_ always gets rid of them.
|
||||
|
||||
If you're reaching for backslashes, that's a clear signal that you can do better if you
|
||||
slightly refactor your code. I hope some of the examples above show you that there are
|
||||
many ways in which you can do it.
|
||||
|
||||
(labels/line-length)=
|
||||
|
||||
### Line length
|
||||
|
||||
You probably noticed the peculiar default line length. _Black_ defaults to 88 characters
|
||||
per line, which happens to be 10% over 80. This number was found to produce
|
||||
significantly shorter files than sticking with 80 (the most popular), or even 79 (used
|
||||
by the standard library). In general,
|
||||
[90-ish seems like the wise choice](https://youtu.be/wf-BqAjZb8M?t=260).
|
||||
|
||||
If you're paid by the lines of code you write, you can pass `--line-length` with a lower
|
||||
number. _Black_ will try to respect that. However, sometimes it won't be able to without
|
||||
breaking other rules. In those rare cases, auto-formatted code will exceed your allotted
|
||||
limit.
|
||||
|
||||
You can also increase it, but remember that people with sight disabilities find it
|
||||
harder to work with line lengths exceeding 100 characters. It also adversely affects
|
||||
side-by-side diff review on typical screen resolutions. Long lines also make it harder
|
||||
to present code neatly in documentation or talk slides.
|
||||
|
||||
#### Flake8 and other linters
|
||||
|
||||
See [Using _Black_ with other tools](../guides/using_black_with_other_tools.md) about
|
||||
linter compatibility.
|
||||
|
||||
### Empty lines
|
||||
|
||||
_Black_ avoids spurious vertical whitespace. This is in the spirit of PEP 8 which says
|
||||
that in-function vertical whitespace should only be used sparingly.
|
||||
|
||||
_Black_ will allow single empty lines inside functions, and single and double empty
|
||||
lines on module level left by the original editors, except when they're within
|
||||
parenthesized expressions. Since such expressions are always reformatted to fit minimal
|
||||
space, this whitespace is lost.
|
||||
|
||||
```python
|
||||
# in:
|
||||
|
||||
def function(
|
||||
some_argument: int,
|
||||
|
||||
other_argument: int = 5,
|
||||
) -> EmptyLineInParenWillBeDeleted:
|
||||
|
||||
|
||||
|
||||
print("One empty line above me will be kept!")
|
||||
|
||||
def this_is_okay_too():
|
||||
print("No empty line here")
|
||||
# out:
|
||||
|
||||
def function(
|
||||
some_argument: int,
|
||||
other_argument: int = 5,
|
||||
) -> EmptyLineInParenWillBeDeleted:
|
||||
|
||||
print("One empty line above me will be kept!")
|
||||
|
||||
|
||||
def this_is_okay_too():
|
||||
print("No empty line here")
|
||||
```
|
||||
|
||||
It will also insert proper spacing before and after function definitions. It's one line
|
||||
before and after inner functions and two lines before and after module-level functions
|
||||
and classes. _Black_ will not put empty lines between function/class definitions and
|
||||
standalone comments that immediately precede the given function/class.
|
||||
|
||||
_Black_ will enforce single empty lines between a class-level docstring and the first
|
||||
following field or method. This conforms to
|
||||
[PEP 257](https://peps.python.org/pep-0257/#multi-line-docstrings).
|
||||
|
||||
_Black_ won't insert empty lines after function docstrings unless that empty line is
|
||||
required due to an inner function starting immediately after.
|
||||
|
||||
### Comments
|
||||
|
||||
_Black_ does not format comment contents, but it enforces two spaces between code and a
|
||||
comment on the same line, and a space before the comment text begins. Some types of
|
||||
comments that require specific spacing rules are respected: shebangs (`#! comment`), doc
|
||||
comments (`#: comment`), section comments with long runs of hashes, and Spyder cells.
|
||||
Non-breaking spaces after hashes are also preserved. Comments may sometimes be moved
|
||||
because of formatting changes, which can break tools that assign special meaning to
|
||||
them. See [AST before and after formatting](#ast-before-and-after-formatting) for more
|
||||
discussion.
|
||||
|
||||
### Trailing commas
|
||||
|
||||
_Black_ will add trailing commas to expressions that are split by comma where each
|
||||
element is on its own line. This includes function signatures.
|
||||
|
||||
One exception to adding trailing commas is function signatures containing `*`, `*args`,
|
||||
or `**kwargs`. In this case a trailing comma is only safe to use on Python 3.6. _Black_
|
||||
will detect if your file is already 3.6+ only and use trailing commas in this situation.
|
||||
If you wonder how it knows, it looks for f-strings and existing use of trailing commas
|
||||
in function signatures that have stars in them. In other words, if you'd like a trailing
|
||||
comma in this situation and _Black_ didn't recognize it was safe to do so, put it there
|
||||
manually and _Black_ will keep it.
|
||||
|
||||
A pre-existing trailing comma informs _Black_ to always explode contents of the current
|
||||
bracket pair into one item per line. Read more about this in the
|
||||
[Pragmatism](#pragmatism) section below.
|
||||
|
||||
(labels/strings)=
|
||||
|
||||
### Strings
|
||||
|
||||
_Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`). It
|
||||
will replace the latter with the former as long as it does not result in more backslash
|
||||
escapes than before.
|
||||
|
||||
_Black_ also standardizes string prefixes. Prefix characters are made lowercase with the
|
||||
exception of [capital "R" prefixes](#rstrings-and-rstrings), unicode literal markers
|
||||
(`u`) are removed because they are meaningless in Python 3, and in the case of multiple
|
||||
characters "r" is put first as in spoken language: "raw f-string".
|
||||
|
||||
Another area where Python allows multiple ways to format a string is escape sequences.
|
||||
For example, `"\uabcd"` and `"\uABCD"` evaluate to the same string. _Black_ normalizes
|
||||
such escape sequences to lowercase, but uses uppercase for `\N` named character escapes,
|
||||
such as `"\N{MEETEI MAYEK LETTER HUK}"`.
|
||||
|
||||
The main reason to standardize on a single form of quotes is aesthetics. Having one kind
|
||||
of quotes everywhere reduces reader distraction. It will also enable a future version of
|
||||
_Black_ to merge consecutive string literals that ended up on the same line (see
|
||||
[#26](https://github.com/psf/black/issues/26) for details).
|
||||
|
||||
Why settle on double quotes? They anticipate apostrophes in English text. They match the
|
||||
docstring standard described in
|
||||
[PEP 257](https://peps.python.org/pep-0257/#what-is-a-docstring). An empty string in
|
||||
double quotes (`""`) is impossible to confuse with a one double-quote regardless of
|
||||
fonts and syntax highlighting used. On top of this, double quotes for strings are
|
||||
consistent with C which Python interacts a lot with.
|
||||
|
||||
On certain keyboard layouts like US English, typing single quotes is a bit easier than
|
||||
double quotes. The latter requires use of the Shift key. My recommendation here is to
|
||||
keep using whatever is faster to type and let _Black_ handle the transformation.
|
||||
|
||||
If you are adopting _Black_ in a large project with pre-existing string conventions
|
||||
(like the popular
|
||||
["single quotes for data, double quotes for human-readable strings"](https://stackoverflow.com/a/56190)),
|
||||
you can pass `--skip-string-normalization` on the command line. This is meant as an
|
||||
adoption helper, avoid using this for new projects.
|
||||
|
||||
_Black_ also processes docstrings. Firstly the indentation of docstrings is corrected
|
||||
for both quotations and the text within, although relative indentation in the text is
|
||||
preserved. Superfluous trailing whitespace on each line and unnecessary new lines at the
|
||||
end of the docstring are removed. All leading tabs are converted to spaces, but tabs
|
||||
inside text are preserved. Whitespace leading and trailing one-line docstrings is
|
||||
removed.
|
||||
|
||||
### Numeric literals
|
||||
|
||||
_Black_ standardizes most numeric literals to use lowercase letters for the syntactic
|
||||
parts and uppercase letters for the digits themselves: `0xAB` instead of `0XAB` and
|
||||
`1e10` instead of `1E10`.
|
||||
|
||||
### Line breaks & binary operators
|
||||
|
||||
_Black_ will break a line before a binary operator when splitting a block of code over
|
||||
multiple lines. This is so that _Black_ is compliant with the recent changes in the
|
||||
[PEP 8](https://peps.python.org/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
|
||||
style guide, which emphasizes that this approach improves readability.
|
||||
|
||||
Almost all operators will be surrounded by single spaces, the only exceptions are unary
|
||||
operators (`+`, `-`, and `~`), and power operators when both operands are simple. For
|
||||
powers, an operand is considered simple if it's only a NAME, numeric CONSTANT, or
|
||||
attribute access (chained attribute access is allowed), with or without a preceding
|
||||
unary operator.
|
||||
|
||||
```python
|
||||
# For example, these won't be surrounded by whitespace
|
||||
a = x**y
|
||||
b = config.base**5.2
|
||||
c = config.base**runtime.config.exponent
|
||||
d = 2**5
|
||||
e = 2**~5
|
||||
|
||||
# ... but these will be surrounded by whitespace
|
||||
f = 2 ** get_exponent()
|
||||
g = get_x() ** get_y()
|
||||
h = config['base'] ** 2
|
||||
```
|
||||
|
||||
### Slices
|
||||
|
||||
PEP 8
|
||||
[recommends](https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements)
|
||||
to treat `:` in slices as a binary operator with the lowest priority, and to leave an
|
||||
equal amount of space on either side, except if a parameter is omitted (e.g.
|
||||
`ham[1 + 1 :]`). It recommends no spaces around `:` operators for "simple expressions"
|
||||
(`ham[lower:upper]`), and extra space for "complex expressions"
|
||||
(`ham[lower : upper + offset]`). _Black_ treats anything more than variable names as
|
||||
"complex" (`ham[lower : upper + 1]`). It also states that for extended slices, both `:`
|
||||
operators have to have the same amount of spacing, except if a parameter is omitted
|
||||
(`ham[1 + 1 ::]`). _Black_ enforces these rules consistently.
|
||||
|
||||
This behaviour may raise `E203 whitespace before ':'` warnings in style guide
|
||||
enforcement tools like Flake8. Since `E203` is not PEP 8 compliant, you should tell
|
||||
Flake8 to ignore these warnings.
|
||||
|
||||
### Parentheses
|
||||
|
||||
Some parentheses are optional in the Python grammar. Any expression can be wrapped in a
|
||||
pair of parentheses to form an atom. There are a few interesting cases:
|
||||
|
||||
- `if (...):`
|
||||
- `while (...):`
|
||||
- `for (...) in (...):`
|
||||
- `assert (...), (...)`
|
||||
- `from X import (...)`
|
||||
- assignments like:
|
||||
- `target = (...)`
|
||||
- `target: type = (...)`
|
||||
- `some, *un, packing = (...)`
|
||||
- `augmented += (...)`
|
||||
|
||||
In those cases, parentheses are removed when the entire statement fits in one line, or
|
||||
if the inner expression doesn't have any delimiters to further split on. If there is
|
||||
only a single delimiter and the expression starts or ends with a bracket, the
|
||||
parentheses can also be successfully omitted since the existing bracket pair will
|
||||
organize the expression neatly anyway. Otherwise, the parentheses are added.
|
||||
|
||||
Please note that _Black_ does not add or remove any additional nested parentheses that
|
||||
you might want to have for clarity or further code organization. For example those
|
||||
parentheses are not going to be removed:
|
||||
|
||||
```python
|
||||
return not (this or that)
|
||||
decision = (maybe.this() and values > 0) or (maybe.that() and values < 0)
|
||||
```
|
||||
|
||||
### Call chains
|
||||
|
||||
Some popular APIs, like ORMs, use call chaining. This API style is known as a
|
||||
[fluent interface](https://en.wikipedia.org/wiki/Fluent_interface). _Black_ formats
|
||||
those by treating dots that follow a call or an indexing operation like a very low
|
||||
priority delimiter. It's easier to show the behavior than to explain it. Look at the
|
||||
example:
|
||||
|
||||
```python
|
||||
def example(session):
|
||||
result = (
|
||||
session.query(models.Customer.id)
|
||||
.filter(
|
||||
models.Customer.account_id == account_id,
|
||||
models.Customer.email == email_address,
|
||||
)
|
||||
.order_by(models.Customer.id.asc())
|
||||
.all()
|
||||
)
|
||||
```
|
||||
|
||||
### Typing stub files
|
||||
|
||||
PEP 484 describes the syntax for type hints in Python. One of the use cases for typing
|
||||
is providing type annotations for modules which cannot contain them directly (they might
|
||||
be written in C, or they might be third-party, or their implementation may be overly
|
||||
dynamic, and so on).
|
||||
|
||||
To solve this,
|
||||
[stub files with the `.pyi` file extension](https://peps.python.org/pep-0484/#stub-files)
|
||||
can be used to describe typing information for an external module. Those stub files omit
|
||||
the implementation of classes and functions they describe, instead they only contain the
|
||||
structure of the file (listing globals, functions, and classes with their members). The
|
||||
recommended code style for those files is more terse than PEP 8:
|
||||
|
||||
- prefer `...` on the same line as the class/function signature;
|
||||
- avoid vertical whitespace between consecutive module-level functions, names, or
|
||||
methods and fields within a single class;
|
||||
- use a single blank line between top-level class definitions, or none if the classes
|
||||
are very small.
|
||||
|
||||
_Black_ enforces the above rules. There are additional guidelines for formatting `.pyi`
|
||||
file that are not enforced yet but might be in a future version of the formatter:
|
||||
|
||||
- prefer `...` over `pass`;
|
||||
- avoid using string literals in type annotations, stub files support forward references
|
||||
natively (like Python 3.7 code with `from __future__ import annotations`);
|
||||
- use variable annotations instead of type comments, even for stubs that target older
|
||||
versions of Python.
|
||||
|
||||
### Line endings
|
||||
|
||||
_Black_ will normalize line endings (`\n` or `\r\n`) based on the first line ending of
|
||||
the file.
|
||||
|
||||
### Form feed characters
|
||||
|
||||
_Black_ will retain form feed characters on otherwise empty lines at the module level.
|
||||
Only one form feed is retained for a group of consecutive empty lines. Where there are
|
||||
two empty lines in a row, the form feed is placed on the second line.
|
||||
|
||||
## Pragmatism
|
||||
|
||||
Early versions of _Black_ used to be absolutist in some respects. They took after its
|
||||
initial author. This was fine at the time as it made the implementation simpler and
|
||||
there were not many users anyway. Not many edge cases were reported. As a mature tool,
|
||||
_Black_ does make some exceptions to rules it otherwise holds. This section documents
|
||||
what those exceptions are and why this is the case.
|
||||
|
||||
(labels/magic-trailing-comma)=
|
||||
|
||||
### The magic trailing comma
|
||||
|
||||
_Black_ in general does not take existing formatting into account.
|
||||
|
||||
However, there are cases where you put a short collection or function call in your code
|
||||
but you anticipate it will grow in the future.
|
||||
|
||||
For example:
|
||||
|
||||
```python
|
||||
TRANSLATIONS = {
|
||||
"en_us": "English (US)",
|
||||
"pl_pl": "polski",
|
||||
}
|
||||
```
|
||||
|
||||
Early versions of _Black_ used to ruthlessly collapse those into one line (it fits!).
|
||||
Now, you can communicate that you don't want that by putting a trailing comma in the
|
||||
collection yourself. When you do, _Black_ will know to always explode your collection
|
||||
into one item per line.
|
||||
|
||||
How do you make it stop? Just delete that trailing comma and _Black_ will collapse your
|
||||
collection into one line if it fits.
|
||||
|
||||
If you must, you can recover the behaviour of early versions of _Black_ with the option
|
||||
`--skip-magic-trailing-comma` / `-C`.
|
||||
|
||||
### r"strings" and R"strings"
|
||||
|
||||
_Black_ normalizes string quotes as well as string prefixes, making them lowercase. One
|
||||
exception to this rule is r-strings. It turns out that the very popular
|
||||
[MagicPython](https://github.com/MagicStack/MagicPython/) syntax highlighter, used by
|
||||
default by (among others) GitHub and Visual Studio Code, differentiates between
|
||||
r-strings and R-strings. The former are syntax highlighted as regular expressions while
|
||||
the latter are treated as true raw strings with no special semantics.
|
||||
|
||||
(labels/ast-changes)=
|
||||
|
||||
### AST before and after formatting
|
||||
|
||||
When run with `--safe` (the default), _Black_ checks that the code before and after is
|
||||
semantically equivalent. This check is done by comparing the AST of the source with the
|
||||
AST of the target. There are three limited cases in which the AST does differ:
|
||||
|
||||
1. _Black_ cleans up leading and trailing whitespace of docstrings, re-indenting them if
|
||||
needed. It's been one of the most popular user-reported features for the formatter to
|
||||
fix whitespace issues with docstrings. While the result is technically an AST
|
||||
difference, due to the various possibilities of forming docstrings, all real-world
|
||||
uses of docstrings that we're aware of sanitize indentation and leading/trailing
|
||||
whitespace anyway.
|
||||
|
||||
1. _Black_ manages optional parentheses for some statements. In the case of the `del`
|
||||
statement, presence of wrapping parentheses or lack thereof changes the resulting AST
|
||||
but is semantically equivalent in the interpreter.
|
||||
|
||||
1. _Black_ might move comments around, which includes type comments. Those are part of
|
||||
the AST as of Python 3.8. While the tool implements a number of special cases for
|
||||
those comments, there is no guarantee they will remain where they were in the source.
|
||||
Note that this doesn't change runtime behavior of the source code.
|
||||
|
||||
To put things in perspective, the code equivalence check is a feature of _Black_ which
|
||||
other formatters don't implement at all. It is of crucial importance to us to ensure
|
||||
code behaves the way it did before it got reformatted. We treat this as a feature and
|
||||
there are no plans to relax this in the future. The exceptions enumerated above stem
|
||||
from either user feedback or implementation details of the tool. In each case we made
|
||||
due diligence to ensure that the AST divergence is of no practical consequence.
|
||||
@@ -0,0 +1,500 @@
|
||||
# The (future of the) Black code style
|
||||
|
||||
## Preview style
|
||||
|
||||
(labels/preview-style)=
|
||||
|
||||
Experimental, potentially disruptive style changes are gathered under the `--preview`
|
||||
CLI flag. At the end of each year, these changes may be adopted into the default style,
|
||||
as described in [The Black Code Style](index.md). Because the functionality is
|
||||
experimental, feedback and issue reports are highly encouraged!
|
||||
|
||||
(labels/preview-features)=
|
||||
|
||||
Currently, the following features are included in the preview style:
|
||||
|
||||
- `wrap_comprehension_in`: Wrap the `in` clause of list and dictionary comprehensions
|
||||
across lines if it would otherwise exceed the maximum line length.
|
||||
([see below](labels/wrap-comprehension-in))
|
||||
- `simplify_power_operator_hugging`: Use a simpler implementation of the power operator
|
||||
"hugging" logic (removing whitespace around `**` in simple expressions), which applies
|
||||
also in the rare case the exponentiation is split into separate lines.
|
||||
([see below](labels/simplify-power-operator))
|
||||
- `wrap_long_dict_values_in_parens`: Add parentheses around long values in dictionaries.
|
||||
([see below](labels/wrap-long-dict-values))
|
||||
- `fix_if_guard_explosion_in_case_statement`: fixed exploding of the if guard in case
|
||||
patterns which have trailing commas in them, even if the guard expression fits in one
|
||||
line
|
||||
- `pyi_overload_group_blank_lines`: In `.pyi` stub files, improve heuristics around when
|
||||
blank lines should appear before, after and within decorated function groups.
|
||||
([see below](labels/pyi-overload-group))
|
||||
- `pyi_blank_line_before_decorated_class`: In `.pyi` stub files, enforce a blank line
|
||||
before a decorated class definition when it follows a function definition.
|
||||
([see below](labels/pyi-blank-line-before-decorated-class))
|
||||
- `fix_unnecessary_parens_in_indexed_assignment`: Remove unnecessary parentheses around
|
||||
the right-hand side of indexed assignments (e.g. `x[key] = expr`) when the subscripted
|
||||
target is too long to fit on one line and the expression fits on the tail line.
|
||||
([see below](labels/fix-unnecessary-parens-indexed-assignment))
|
||||
- `pyi_blank_line_after_function_docstring`: In `.pyi` stub files, enforce a blank line
|
||||
after a function or method body that consists of a docstring.
|
||||
([see below](labels/pyi-blank-line-after-function-docstring))
|
||||
- `hug_comparator`: Don't break a comparator (`not in`, `==`, `is`, ...) away from its
|
||||
left operand when the right operand is a bracketed expression that has to break
|
||||
anyway; let the bracket explode instead. ([see below](labels/hug-comparator))
|
||||
- `parenthesize_tuple_in_yield`: Add parentheses around tuple expressions in `yield`
|
||||
statements.
|
||||
|
||||
(labels/wrap-comprehension-in)=
|
||||
|
||||
### Wrapping long comprehension `in` clauses
|
||||
|
||||
When a list or dictionary comprehension has a long `in` clause that would exceed the
|
||||
maximum line length, Black will wrap it across multiple lines for better readability.
|
||||
This helps keep comprehensions readable when the iterable expression is complex or
|
||||
lengthy.
|
||||
|
||||
For example:
|
||||
|
||||
```python
|
||||
# Before
|
||||
result = [
|
||||
very_very_very_very_very_long_item
|
||||
for very_very_very_very_very_long_item in some_very_very_very_very_very_very_long_function_name
|
||||
]
|
||||
```
|
||||
|
||||
will be formatted to:
|
||||
|
||||
```python
|
||||
# After
|
||||
result = [
|
||||
very_very_very_very_very_long_item
|
||||
for very_very_very_very_very_long_item in (
|
||||
some_very_very_very_very_very_very_long_function_name
|
||||
)
|
||||
]
|
||||
```
|
||||
|
||||
This also applies to dictionary comprehensions:
|
||||
|
||||
```python
|
||||
# Before
|
||||
mapping = {
|
||||
very_long_key: very_very_very_long_item
|
||||
for very_long_key, very_very_very_long_item in very_very_very_very_long_function_name
|
||||
}
|
||||
```
|
||||
|
||||
will be formatted to:
|
||||
|
||||
```python
|
||||
# After
|
||||
mapping = {
|
||||
very_long_key: very_very_very_long_item
|
||||
for very_long_key, very_very_very_long_item in (
|
||||
very_very_very_very_long_function_name
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
(labels/simplify-power-operator)=
|
||||
|
||||
### Simplified power operator whitespace handling
|
||||
|
||||
Black's power operator "hugging" logic removes whitespace around `**` in simple
|
||||
expressions (e.g., `x**2` instead of `x ** 2`). This feature uses a simpler, more
|
||||
consistent implementation that also applies when exponentiation is split across lines.
|
||||
|
||||
For example:
|
||||
|
||||
```python
|
||||
# Simple expressions - whitespace is removed
|
||||
result = x**2 + y**3
|
||||
value = base**exponent
|
||||
```
|
||||
|
||||
When the exponentiation is split across lines (rare), the simplified logic ensures
|
||||
consistent formatting:
|
||||
|
||||
```python
|
||||
# Complex expression split across lines
|
||||
result = (
|
||||
some_very_long_base_expression
|
||||
**some_very_long_exponent_expression
|
||||
**some_very_long_third_expression
|
||||
)
|
||||
```
|
||||
|
||||
This feature primarily improves the internal consistency of Black's formatting logic
|
||||
rather than making dramatic visual changes to most code.
|
||||
|
||||
(labels/wrap-long-dict-values)=
|
||||
|
||||
### Improved parentheses management in dicts
|
||||
|
||||
For dict literals with long values, they are now wrapped in parentheses. Unnecessary
|
||||
parentheses are now removed. For example:
|
||||
|
||||
```python
|
||||
my_dict = {
|
||||
"a key in my dict": a_very_long_variable
|
||||
* and_a_very_long_function_call()
|
||||
/ 100000.0,
|
||||
"another key": (short_value),
|
||||
}
|
||||
```
|
||||
|
||||
will be changed to:
|
||||
|
||||
```python
|
||||
my_dict = {
|
||||
"a key in my dict": (
|
||||
a_very_long_variable * and_a_very_long_function_call() / 100000.0
|
||||
),
|
||||
"another key": short_value,
|
||||
}
|
||||
```
|
||||
|
||||
(labels/pyi-overload-group)=
|
||||
|
||||
### Improved overload groups in stub files
|
||||
|
||||
In `.pyi` stub files, Black now has improved heuristics regarding when blank lines
|
||||
should appear before, after or within groups of decorated functions that share the same
|
||||
name (such as `@overload` groups). Two rules are applied when a decorated function is
|
||||
determined to be part of a series of >=2 decorated functions with the same name:
|
||||
|
||||
1. **Before the decorated function**: a blank line is always inserted, unless the
|
||||
preceding statement is a same-name decorated function (i.e. part of an `@overload`
|
||||
group) or the function is the first statement in its block.
|
||||
2. **After the decorated function**: a blank line is always inserted, unless the
|
||||
following statement is a same-name decorated function.
|
||||
|
||||
These rules apply regardless of what the adjacent statement is — whether it's another
|
||||
function definition, a variable annotation, or any other statement.
|
||||
|
||||
Previously, Black could insert unwanted blank lines _within_ an overload group when one
|
||||
of the overloads had a docstring, and did not consistently enforce blank lines at the
|
||||
boundaries of overload groups:
|
||||
|
||||
```python
|
||||
# Before
|
||||
|
||||
@overload
|
||||
def foo(x: int) -> int:
|
||||
"""Docs."""
|
||||
|
||||
@overload # unwanted blank line within group
|
||||
def foo(x: str) -> str: ...
|
||||
def bar(x): ... # no blank line after group
|
||||
```
|
||||
|
||||
With this feature enabled, the group is kept together and clearly separated from
|
||||
surrounding code:
|
||||
|
||||
```python
|
||||
# After (with --preview)
|
||||
|
||||
@overload
|
||||
def foo(x: int) -> int:
|
||||
"""Docs."""
|
||||
@overload
|
||||
def foo(x: str) -> str: ...
|
||||
|
||||
def bar(x): ...
|
||||
```
|
||||
|
||||
(labels/pyi-blank-line-before-decorated-class)=
|
||||
|
||||
### Blank line before decorated classes in stub files
|
||||
|
||||
In `.pyi` stub files, Black already enforces blank lines around class definitions in
|
||||
many situations. However, when a class has a decorator, Black previously failed to
|
||||
enforce this, instead _removing_ the blank line between a function and the decorator:
|
||||
|
||||
```diff
|
||||
# Before
|
||||
|
||||
def foo(): ...
|
||||
-
|
||||
@decorator
|
||||
class Bar: ...
|
||||
|
||||
def baz(): ...
|
||||
@decorator
|
||||
class Spam: ...
|
||||
```
|
||||
|
||||
With this feature enabled, a blank line is enforced, consistent with how undecorated
|
||||
classes are handled:
|
||||
|
||||
```diff
|
||||
# After (with --preview)
|
||||
|
||||
def foo(): ...
|
||||
|
||||
@decorator
|
||||
class Bar: ...
|
||||
|
||||
def baz(): ...
|
||||
+
|
||||
@decorator
|
||||
class Spam: ...
|
||||
```
|
||||
|
||||
(labels/fix-unnecessary-parens-indexed-assignment)=
|
||||
|
||||
### Unnecessary parentheses in indexed assignments
|
||||
|
||||
When an assignment target ends with a subscript (e.g. `x[key] = expr`) and is too long
|
||||
to fit on one line, Black has to split at the subscript's brackets. Previously it would
|
||||
additionally wrap the right-hand side expression in parentheses, even when the
|
||||
expression fits on the closing line. With this feature enabled, Black omits those
|
||||
unnecessary parentheses.
|
||||
|
||||
For example:
|
||||
|
||||
```python
|
||||
# Before
|
||||
dictionary_of_arrays["long_key_name_for_the_example"][
|
||||
very_long_index_name, index_zero
|
||||
] = (10 - 5)
|
||||
```
|
||||
|
||||
will be formatted to:
|
||||
|
||||
```python
|
||||
# After (with --preview)
|
||||
dictionary_of_arrays["long_key_name_for_the_example"][
|
||||
very_long_index_name, index_zero
|
||||
] = 10 - 5
|
||||
```
|
||||
|
||||
Assignments whose target fits on one line are not affected: wrapping the right-hand side
|
||||
in parentheses remains the preferred style there.
|
||||
|
||||
(labels/pyi-blank-line-after-function-docstring)=
|
||||
|
||||
### Blank line after function docstrings in stub files
|
||||
|
||||
In `.pyi` stub files, functions and methods sometimes use a docstring as their whole
|
||||
body. Black already separated these definitions from a following function definition,
|
||||
but did not consistently do the same before a following comment, conditional block,
|
||||
variable annotation, or other statement:
|
||||
|
||||
```python
|
||||
# Before
|
||||
|
||||
class Example:
|
||||
def method(self) -> None:
|
||||
"""Documentation."""
|
||||
# comment for the next member
|
||||
attr: int
|
||||
```
|
||||
|
||||
With this feature enabled, the docstring-only function body is consistently separated
|
||||
from the next comment or statement:
|
||||
|
||||
```python
|
||||
# After (with --preview)
|
||||
|
||||
class Example:
|
||||
def method(self) -> None:
|
||||
"""Documentation."""
|
||||
|
||||
# comment for the next member
|
||||
attr: int
|
||||
```
|
||||
|
||||
Black still keeps same-name decorated functions, such as `@overload` groups and property
|
||||
setters, together without inserting blank lines between them.
|
||||
|
||||
(labels/hug-comparator)=
|
||||
|
||||
### Keep comparators next to their left operand
|
||||
|
||||
When a comparator (`not in`, `==`, `is`, ...) sits inside another bracketed construct
|
||||
and its right operand is a bracketed expression that has to break (either via a magic
|
||||
trailing comma or because the line is too long), Black used to split the line right
|
||||
before the comparator. The left operand ended up alone on its own line, visually
|
||||
disconnected from the operator and the operand that explains it:
|
||||
|
||||
```python
|
||||
# Before
|
||||
|
||||
x = [
|
||||
t
|
||||
for t in y
|
||||
if t
|
||||
not in {
|
||||
LongNameOne,
|
||||
LongNameTwo,
|
||||
LongNameThree,
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
With this feature enabled, Black skips that comparator split and lets the right-hand
|
||||
bracket explode instead, which it would have done anyway:
|
||||
|
||||
```python
|
||||
# After (with --preview)
|
||||
|
||||
x = [
|
||||
t
|
||||
for t in y
|
||||
if t not in {
|
||||
LongNameOne,
|
||||
LongNameTwo,
|
||||
LongNameThree,
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
The fix is not limited to comprehensions. The same shape appears inside `if`/`elif`
|
||||
chains, `assert` statements, and parenthesized expressions, and gets the same treatment:
|
||||
|
||||
```python
|
||||
# Before
|
||||
|
||||
if (
|
||||
is_scalar(value)
|
||||
and self.dtype
|
||||
in (np.dtype("float64"), np.dtype("float32"), np.dtype("object"))
|
||||
and (limit is not None or inplace)
|
||||
):
|
||||
...
|
||||
|
||||
assert (
|
||||
bool
|
||||
is _AnnotationExtractor(attr.fields(C).x.converter.__call__).get_return_type()
|
||||
)
|
||||
```
|
||||
|
||||
```python
|
||||
# After (with --preview)
|
||||
|
||||
if (
|
||||
is_scalar(value)
|
||||
and self.dtype in (
|
||||
np.dtype("float64"),
|
||||
np.dtype("float32"),
|
||||
np.dtype("object"),
|
||||
)
|
||||
and (limit is not None or inplace)
|
||||
):
|
||||
...
|
||||
|
||||
assert (
|
||||
bool is _AnnotationExtractor(
|
||||
attr.fields(C).x.converter.__call__
|
||||
).get_return_type()
|
||||
)
|
||||
```
|
||||
|
||||
## Unstable style
|
||||
|
||||
(labels/unstable-style)=
|
||||
|
||||
In the past, the preview style included some features with known bugs, so that we were
|
||||
unable to move these features to the stable style. Therefore, such features are now
|
||||
moved to the `--unstable` style. All features in the `--preview` style are expected to
|
||||
make it to next year's stable style; features in the `--unstable` style will be
|
||||
stabilized only if issues with them are fixed. If bugs are discovered in a `--preview`
|
||||
feature, it is demoted to the `--unstable` style. To avoid thrash when a feature is
|
||||
demoted from the `--preview` to the `--unstable` style, users can use the
|
||||
`--enable-unstable-feature` flag to enable specific unstable features.
|
||||
|
||||
(labels/unstable-features)=
|
||||
|
||||
The unstable style additionally includes the following features:
|
||||
|
||||
- `hug_parens_with_braces_and_square_brackets`: More compact formatting of nested
|
||||
brackets. ([see below](labels/hug-parens))
|
||||
- `string_processing`: Split long string literals and related changes.
|
||||
([see below](labels/string-processing))
|
||||
|
||||
(labels/hug-parens)=
|
||||
|
||||
### Improved multiline dictionary and list indentation for sole function parameter
|
||||
|
||||
For better readability and less verticality, _Black_ now pairs parentheses ("(", ")")
|
||||
with braces ("{", "}") and square brackets ("[", "]") on the same line. For example:
|
||||
|
||||
```python
|
||||
foo(
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
)
|
||||
|
||||
nested_array = [
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
will be changed to:
|
||||
|
||||
```python
|
||||
foo([
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
])
|
||||
|
||||
nested_array = [[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]]
|
||||
```
|
||||
|
||||
This also applies to list and dictionary unpacking:
|
||||
|
||||
```python
|
||||
foo(
|
||||
*[
|
||||
a_long_function_name(a_long_variable_name)
|
||||
for a_long_variable_name in some_generator
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
will become:
|
||||
|
||||
```python
|
||||
foo(*[
|
||||
a_long_function_name(a_long_variable_name)
|
||||
for a_long_variable_name in some_generator
|
||||
])
|
||||
```
|
||||
|
||||
You can use a magic trailing comma to avoid this compacting behavior; by default,
|
||||
_Black_ will not reformat the following code:
|
||||
|
||||
```python
|
||||
foo(
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
(labels/string-processing)=
|
||||
|
||||
### Improved string processing
|
||||
|
||||
_Black_ will split long string literals and merge short ones. Parentheses are used where
|
||||
appropriate. When split, parts of f-strings that don't need formatting are converted to
|
||||
plain strings. f-strings will not be merged if they contain internal quotes and it would
|
||||
change their quotation mark style. Line continuation backslashes are converted into
|
||||
parenthesized strings. Unnecessary parentheses are stripped. The stability and status of
|
||||
this feature is tracked in [this issue](https://github.com/psf/black/issues/2188).
|
||||
@@ -0,0 +1,54 @@
|
||||
# The Black Code Style
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
hidden:
|
||||
---
|
||||
|
||||
Current style <current_style>
|
||||
Future style <future_style>
|
||||
```
|
||||
|
||||
_Black_ is a PEP 8 compliant opinionated formatter with its own style.
|
||||
|
||||
While keeping the style unchanged throughout releases has always been a goal, the
|
||||
_Black_ code style isn't set in stone. It evolves to accommodate for new features in the
|
||||
Python language and, occasionally, in response to user feedback. Large-scale style
|
||||
preferences presented in {doc}`current_style` are very unlikely to change, but minor
|
||||
style aspects and details might change according to the stability policy presented
|
||||
below. Ongoing style considerations are tracked on GitHub with the
|
||||
[style](https://github.com/psf/black/labels/T%3A%20style) issue label.
|
||||
|
||||
(labels/stability-policy)=
|
||||
|
||||
## Stability Policy
|
||||
|
||||
The following policy applies for the _Black_ code style, in non pre-release versions of
|
||||
_Black_:
|
||||
|
||||
- If code has been formatted with _Black_, it will remain unchanged when formatted with
|
||||
the same options using any other release in the same calendar year.
|
||||
|
||||
This means projects can safely use `black ~= 26.0` without worrying about formatting
|
||||
changes disrupting their project in 2026. We may still fix bugs where _Black_ crashes
|
||||
on some code, and make other improvements that do not affect formatting.
|
||||
|
||||
In rare cases, we may make changes affecting code that has not been previously
|
||||
formatted with _Black_. For example, we have had bugs where we accidentally removed
|
||||
some comments. Such bugs can be fixed without breaking the stability policy.
|
||||
|
||||
- The first release in a new calendar year _may_ contain formatting changes, although
|
||||
these will be minimised as much as possible. This is to allow for improved formatting
|
||||
enabled by newer Python language syntax as well as due to improvements in the
|
||||
formatting logic.
|
||||
|
||||
- The `--preview` and `--unstable` flags are exempt from this policy. There are no
|
||||
guarantees around the stability of the output with these flags passed into _Black_.
|
||||
They are intended for allowing experimentation with proposed changes to the _Black_
|
||||
code style. The `--preview` style at the end of a year should closely match the stable
|
||||
style for the next year, but we may always make changes.
|
||||
|
||||
Documentation for both the current and future styles can be found:
|
||||
|
||||
- {doc}`current_style`
|
||||
- {doc}`future_style`
|
||||
Reference in New Issue
Block a user