Skip to content
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

Merged
merged 53 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
18e711f
Allow empty lines at beginning of blocks (again)
JelleZijlstra Nov 21, 2023
d753703
reformat
JelleZijlstra Nov 21, 2023
129349c
update comments
JelleZijlstra Nov 21, 2023
51bb901
Many uncontroverisal preview changes
JelleZijlstra Nov 21, 2023
c71b5e2
more relatively noncontroversial features
JelleZijlstra Nov 21, 2023
cc3780f
Update some tests
JelleZijlstra Nov 21, 2023
bb31678
Enable two more
JelleZijlstra Nov 21, 2023
337a85d
Merge branch 'main' into 241a1really
JelleZijlstra Dec 10, 2023
37f8ed0
Remove obsolete features
JelleZijlstra Dec 10, 2023
be46470
Fix up merge
JelleZijlstra Dec 10, 2023
7712a74
Add --unstable flag
JelleZijlstra Dec 10, 2023
6238e38
self
JelleZijlstra Dec 10, 2023
47221c9
fine
JelleZijlstra Dec 10, 2023
3fd83e0
Merge branch 'main' into 241a1really
JelleZijlstra Dec 11, 2023
6e8871b
Fix the worst issues
JelleZijlstra Dec 11, 2023
10f6449
fix some tests
JelleZijlstra Dec 11, 2023
c27daf6
Update tests
JelleZijlstra Dec 11, 2023
dc2d104
Fix another dummy impl case
JelleZijlstra Dec 11, 2023
b073cbd
fix some more
JelleZijlstra Dec 11, 2023
034fd94
Merge branch 'main' into 241a1really
JelleZijlstra Dec 11, 2023
acb8c7c
unused imports
JelleZijlstra Dec 11, 2023
27c8a34
Fix feature detection for parenthesized CMs
JelleZijlstra Dec 12, 2023
0302e8d
changelog
JelleZijlstra Dec 12, 2023
6794240
Merge branch 'main' into 241a1really
JelleZijlstra Dec 12, 2023
9886590
Merge remote-tracking branch 'upstream/main' into black24
JelleZijlstra Jan 4, 2024
7f7eb72
Fix up
JelleZijlstra Jan 4, 2024
280ec86
Merge branch 'main' into black24
JelleZijlstra Jan 24, 2024
975e7f1
wrap_long_dict_values_in_parens and multiline_string_handling back to…
JelleZijlstra Jan 24, 2024
073ee3f
bad merge
JelleZijlstra Jan 24, 2024
8758f3c
fix tests
JelleZijlstra Jan 24, 2024
a9ca9a4
fix more tests
JelleZijlstra Jan 24, 2024
47449ff
Remove --preview from some tests
JelleZijlstra Jan 24, 2024
a646358
changelog
JelleZijlstra Jan 24, 2024
c4f42c6
Merge branch 'main' into unstable
JelleZijlstra Jan 24, 2024
5d2d735
Merge branch 'black24' into unstable
JelleZijlstra Jan 24, 2024
7836fb9
docs, blackd
JelleZijlstra Jan 24, 2024
5eaba4a
Format ourselves unstably
JelleZijlstra Jan 24, 2024
718ce47
fix test
JelleZijlstra Jan 24, 2024
27bcbc5
Merge branch 'main' into unstable
JelleZijlstra Jan 25, 2024
5411e74
Merge branch 'main' into unstable
JelleZijlstra Jan 25, 2024
cb9bc00
one more
JelleZijlstra Jan 25, 2024
9bfeae2
Add separate flags for --unstable features
JelleZijlstra Jan 25, 2024
9389390
Clean up obsolete preview tests
JelleZijlstra Jan 25, 2024
07eccbe
docs, blackd
JelleZijlstra Jan 25, 2024
81ab9cc
some tests
JelleZijlstra Jan 25, 2024
926bbde
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 25, 2024
1755897
ugh 3.8
JelleZijlstra Jan 25, 2024
3a7310f
note replacement
JelleZijlstra Jan 25, 2024
a1b4dca
lint
JelleZijlstra Jan 25, 2024
47ea1d2
Remove broken and disabled test
JelleZijlstra Jan 25, 2024
e21787f
lint the lint
JelleZijlstra Jan 25, 2024
09c1fb5
Allow --enable-unstable-feature for preview features
JelleZijlstra Jan 26, 2024
9cc105b
Expand changelog
JelleZijlstra Jan 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 45 additions & 4 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,63 @@

<!-- Include any especially major or disruptive changes here -->

This release introduces the new 2024 stable style (#4106), stabilizing the following
changes:

- Add parentheses around `if`-`else` expressions (#2278)
- Dummy class and function implementations consisting only of `...` are formatted more
compactly (#3796)
- If an assignment statement is too long, we now prefer splitting on the right-hand side
(#3368)
- Hex codes in Unicode escape sequences are now standardized to lowercase (#2916)
- Allow empty first lines at the beginning of most blocks (#3967, #4061)
- Add parentheses around long type annotations (#3899)
- Standardize on a single newline after module docstrings (#3932)
- Fix incorrect magic trailing comma handling in return types (#3916)
- Remove blank lines before class docstrings (#3692)
- Wrap multiple context managers in parentheses if combined in a single `with` statement
(#3489)
- Fix bug in line length calculations for power operations (#3942)
- Add trailing commas to collection literals even if there's a comment after the last
entry (#3393)
- When using `--skip-magic-trailing-comma` or `-C`, trailing commas are stripped from
subscript expressions with more than 1 element (#3209)
- Add extra blank lines in stubs in a few cases (#3564, #3862)
- Accept raw strings as docstrings (#3947)
- Split long lines in case blocks (#4024)
- Stop removing spaces from walrus operators within subscripts (#3823)
- Fix incorrect formatting of certain async statements (#3609)
- Allow combining `# fmt: skip` with other comments (#3959)

There are already a few improvements in the `--preview` style, which are slated for the
2025 stable style. Try them out and
[share your feedback](https://github.com/psf/black/issues). In the past, the preview
style has included some features that we were not able to stabilize. This year, we're
adding a separate `--unstable` style for features with known problems. Now, the
`--preview` style only includes features that we actually expect to make it into next
year's stable style.

### Stable style

<!-- Changes that affect Black's stable style -->

### Preview style

<!-- Changes that affect Black's preview style -->
Several bug fixes were made in features that are moved to the stable style in this
release:

- Fix comment handling when parenthesising conditional expressions (#4134)
- Format module docstrings the same as class and function docstrings (#4095)
- Fix bug where spaces were not added around parenthesized walruses in subscripts,
unlike other binary operators (#4109)
- Remove empty lines before docstrings in async functions (#4132)
- Address a missing case in the change to allow empty lines at the beginning of all
blocks, except immediately before a docstring (#4130)
- For stubs, fix logic to enforce empty line after nested classes with bodies (#4141)

### Preview style

<!-- Changes that affect Black's preview style -->

- Add `--unstable` style (#4096)
Copy link
Collaborator

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?

Copy link
Collaborator Author

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 to multiline_string_handling?

Copy link
Collaborator Author

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.

Copy link
Collaborator

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

Copy link
Collaborator Author

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.

- Format module docstrings the same as class and function docstrings (#4095)
- Fix crash when using a walrus in a dictionary (#4155)
- Fix unnecessary parentheses when wrapping long dicts (#4135)

Expand Down
7 changes: 4 additions & 3 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ other tools, such as `# noqa`, may be moved by _Black_. See below for more detai
Stable. _Black_ aims to enforce one style and one style only, with some room for
pragmatism. See [The Black Code Style](the_black_code_style/index.md) for more details.

Starting in 2022, the formatting output will be stable for the releases made in the same
year (other than unintentional bugs). It is possible to opt-in to the latest formatting
styles, using the `--preview` flag.
Starting in 2022, the formatting output is stable for the releases made in the same year
(other than unintentional bugs). At the beginning of every year, the first release will
make changes to the stable style. It is possible to opt in to the latest formatting
styles using the `--preview` flag.

## Why is my file not formatted?

Expand Down
6 changes: 6 additions & 0 deletions docs/the_black_code_style/current_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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
Expand Down
213 changes: 106 additions & 107 deletions docs/the_black_code_style/future_style.md
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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)=
8 changes: 5 additions & 3 deletions docs/the_black_code_style/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ _Black_:
enabled by newer Python language syntax as well as due to improvements in the
formatting logic.

- The `--preview` flag is exempt from this policy. There are no guarantees around the
stability of the output with that flag passed into _Black_. This flag is intended for
allowing experimentation with the proposed changes to the _Black_ code style.
- 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:

Expand Down
3 changes: 3 additions & 0 deletions docs/usage_and_configuration/black_as_a_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ The headers controlling how source code is formatted are:
- `X-Preview`: corresponds to the `--preview` command line flag. If present and its
value is not an empty string, experimental and potentially disruptive style changes
will be used.
- `X-Unstable`: corresponds to the `--unstable` command line flag. If present and its
value is not an empty string, experimental style changes that are known to be buggy
will be used.
- `X-Fast-Or-Safe`: if set to `fast`, `blackd` will act as _Black_ does when passed the
`--fast` command line flag.
- `X-Python-Variant`: if set to `pyi`, `blackd` will act as _Black_ does when passed the
Expand Down
15 changes: 12 additions & 3 deletions docs/usage_and_configuration/the_basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,18 @@ magic trailing comma is ignored.

#### `--preview`

Enable potentially disruptive style changes that may be added to Black's main
functionality in the next major release. Read more about
[our preview style](labels/preview-style).
Enable potentially disruptive style changes that we expect to add to Black's main
functionality in the next major release. Use this if you want a taste of what next
year's style will look like.

Read more about [our preview style](labels/preview-style).

#### `--unstable`

Enable all style changes in `--preview`, plus additional changes that we would like to
make eventually, but that have known issues that need to be fixed before they can move
back to the `--preview` style. Use this if you want to experiment with these changes and
help fix issues with them.

(labels/exit-code)=

Expand Down