-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add --unstable flag #4096
Add --unstable flag #4096
Changes from 39 commits
18e711f
d753703
129349c
51bb901
c71b5e2
cc3780f
bb31678
337a85d
37f8ed0
be46470
7712a74
6238e38
47221c9
3fd83e0
6e8871b
10f6449
c27daf6
dc2d104
b073cbd
034fd94
acb8c7c
27c8a34
0302e8d
6794240
9886590
7f7eb72
280ec86
975e7f1
073ee3f
8758f3c
a9ca9a4
47449ff
a646358
c4f42c6
5d2d735
7836fb9
5eaba4a
718ce47
27bcbc5
5411e74
cb9bc00
9bfeae2
9389390
07eccbe
81ab9cc
926bbde
1755897
3a7310f
a1b4dca
47ea1d2
e21787f
09c1fb5
9cc105b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -449,6 +449,12 @@ file that are not enforced yet but might be in a future version of the formatter | |
_Black_ will normalize line endings (`\n` or `\r\n`) based on the first line ending of | ||
the file. | ||
|
||
### Form feed characters | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved from "future style", this change is in the 2024 stable style |
||
|
||
_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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,117 +1,38 @@ | ||
# The (future of the) Black code style | ||
|
||
```{warning} | ||
Changes to this document often aren't tied and don't relate to releases of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This warning isn't really true any more now that we explicitly list preview features. |
||
_Black_. It's recommended that you read the latest version available. | ||
``` | ||
|
||
## Using backslashes for with statements | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved this to the end as it's a speculative feature that we haven't even implemented. The real-world preview style is more important. |
||
|
||
[Backslashes are bad and should be never be used](labels/why-no-backslashes) however | ||
there is one exception: `with` statements using multiple context managers. Before Python | ||
3.9 Python's grammar does not allow organizing parentheses around the series of context | ||
managers. | ||
|
||
We don't want formatting like: | ||
|
||
```py3 | ||
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4: | ||
... # nothing to split on - line too long | ||
``` | ||
|
||
So _Black_ will, when we implement this, format it like this: | ||
|
||
```py3 | ||
with \ | ||
make_context_manager1() as cm1, \ | ||
make_context_manager2() as cm2, \ | ||
make_context_manager3() as cm3, \ | ||
make_context_manager4() as cm4 \ | ||
: | ||
... # backslashes and an ugly stranded colon | ||
``` | ||
|
||
Although when the target version is Python 3.9 or higher, _Black_ uses parentheses | ||
instead in `--preview` mode (see below) since they're allowed in Python 3.9 and higher. | ||
|
||
An alternative to consider if the backslashes in the above formatting are undesirable is | ||
to use {external:py:obj}`contextlib.ExitStack` to combine context managers in the | ||
following way: | ||
|
||
```python | ||
with contextlib.ExitStack() as exit_stack: | ||
cm1 = exit_stack.enter_context(make_context_manager1()) | ||
cm2 = exit_stack.enter_context(make_context_manager2()) | ||
cm3 = exit_stack.enter_context(make_context_manager3()) | ||
cm4 = exit_stack.enter_context(make_context_manager4()) | ||
... | ||
``` | ||
|
||
(labels/preview-style)= | ||
|
||
## 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! | ||
|
||
### 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. User-made splits are respected when they do not exceed the line length | ||
limit. 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). | ||
|
||
### Improved line breaks | ||
|
||
For assignment expressions, _Black_ now prefers to split and wrap the right side of the | ||
assignment instead of left side. For example: | ||
|
||
```python | ||
some_dict[ | ||
"with_a_long_key" | ||
] = some_looooooooong_module.some_looooooooooooooong_function_name( | ||
first_argument, second_argument, third_argument | ||
) | ||
``` | ||
|
||
will be changed to: | ||
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. | ||
|
||
```python | ||
some_dict["with_a_long_key"] = ( | ||
some_looooooooong_module.some_looooooooooooooong_function_name( | ||
first_argument, second_argument, third_argument | ||
) | ||
) | ||
``` | ||
Currently, the following features are included in the preview style: | ||
|
||
### Improved parentheses management | ||
- `hex_codes_in_unicode_sequences`: normalize casing of Unicode escape characters in | ||
strings | ||
- `unify_docstring_detection`: fix inconsistencies in whether certain strings are | ||
detected as docstrings | ||
- `hug_parens_with_braces_and_square_brackets`: more compact formatting of nested | ||
brackets ([see below](labels/hug-parens)) | ||
|
||
For dict literals with long values, they are now wrapped in parentheses. Unnecessary | ||
parentheses are now removed. For example: | ||
The unstable style additionally includes the following features: | ||
|
||
```python | ||
my_dict = { | ||
"a key in my dict": a_very_long_variable | ||
* and_a_very_long_function_call() | ||
/ 100000.0, | ||
"another key": (short_value), | ||
} | ||
``` | ||
- `string_processing`: split long string literals and related changes | ||
([see below](labels/string-processing)) | ||
- `wrap_long_dict_values_in_parens`: add parentheses to long values in dictionaries | ||
([see below](labels/wrap-long-dict-values)) | ||
- `multiline_string_handling`: more compact formatting of expressions involving | ||
multiline strings ([see below](labels/multiline-string-handling)) | ||
|
||
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/hug-parens)= | ||
|
||
### Improved multiline dictionary and list indentation for sole function parameter | ||
|
||
|
@@ -185,6 +106,46 @@ foo( | |
) | ||
``` | ||
|
||
(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. User-made splits are respected when they do not exceed the line length | ||
limit. 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). | ||
|
||
(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/multiline-string-handling)= | ||
|
||
### Improved multiline string handling | ||
|
||
_Black_ is smarter when formatting multiline strings, especially in function arguments, | ||
|
@@ -297,13 +258,51 @@ s = ( # Top comment | |
) | ||
``` | ||
|
||
======= | ||
## Potential future changes | ||
|
||
This section lists changes that we may want to make in the future, but that aren't | ||
implemented yet. | ||
|
||
### Using backslashes for with statements | ||
|
||
[Backslashes are bad and should be never be used](labels/why-no-backslashes) however | ||
there is one exception: `with` statements using multiple context managers. Before Python | ||
3.9 Python's grammar does not allow organizing parentheses around the series of context | ||
managers. | ||
|
||
We don't want formatting like: | ||
|
||
```py3 | ||
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4: | ||
... # nothing to split on - line too long | ||
``` | ||
|
||
So _Black_ will, when we implement this, format it like this: | ||
|
||
```py3 | ||
with \ | ||
make_context_manager1() as cm1, \ | ||
make_context_manager2() as cm2, \ | ||
make_context_manager3() as cm3, \ | ||
make_context_manager4() as cm4 \ | ||
: | ||
... # backslashes and an ugly stranded colon | ||
``` | ||
|
||
Although when the target version is Python 3.9 or higher, _Black_ uses parentheses | ||
instead in `--preview` mode (see below) since they're allowed in Python 3.9 and higher. | ||
|
||
### Form feed characters | ||
An alternative to consider if the backslashes in the above formatting are undesirable is | ||
to use {external:py:obj}`contextlib.ExitStack` to combine context managers in the | ||
following way: | ||
|
||
_Black_ will now 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 will be placed on the second line. | ||
```python | ||
with contextlib.ExitStack() as exit_stack: | ||
cm1 = exit_stack.enter_context(make_context_manager1()) | ||
cm2 = exit_stack.enter_context(make_context_manager2()) | ||
cm3 = exit_stack.enter_context(make_context_manager3()) | ||
cm4 = exit_stack.enter_context(make_context_manager4()) | ||
... | ||
``` | ||
|
||
_Black_ already retained form feed literals inside a comment or inside a string. This | ||
remains the case. | ||
(labels/preview-style)= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a quick link / blurb here for preview style codebases that want hug_parens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kept the hugging feature (
hug_parens_with_braces_and_square_brackets
) in preview. Or maybe you're referring tomultiline_string_handling
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also possibly
hug_parens_with_braces_and_square_brackets
should go into unstable; I haven't thought much about it beyond not putting it in 2024 stable. We have 11 months left to do that though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I was wrong on the specifics. Just thought more of a mention in changelog could be nice for whatever unstable features users may want
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll add something.