Skip to content

Two blank lines after an import should be reduced to one#4489

Merged
JelleZijlstra merged 12 commits intopsf:mainfrom
kastkeepitjumpinlikekangaroos:gh-2020
Dec 4, 2024
Merged

Two blank lines after an import should be reduced to one#4489
JelleZijlstra merged 12 commits intopsf:mainfrom
kastkeepitjumpinlikekangaroos:gh-2020

Conversation

@kastkeepitjumpinlikekangaroos
Copy link
Contributor

Description

Hey! Trying to contribute for the first time to the project so let me know if I'm missing anything :)

I've implemented changes to address this issue #2020 where there's some inconsistency around how many lines are added after an import. I've added 2 test cases showing that if there is more than 1 blank line between the import and the next line that it is now being reduced to one. One test case was failing because it had in its expected outout 2 lines between the import and following statement, so I think modifying the test case now that it should always be one makes sense.

Checklist - did you ...

  • Add an entry in CHANGES.md if necessary?
  • Add / update tests if necessary?
  • Add new / update outdated documentation?

@kastkeepitjumpinlikekangaroos
Copy link
Contributor Author

I got an email about this job failure but looks like all the checks are passing on the PR https://github.com/psf/black/actions/runs/11377698063/job/31652281800 is this something that needs to be addressed?

@JelleZijlstra
Copy link
Collaborator

Interesting, I suspect some change to how GitHub handles artifacts. Not sure why it doesn't show up here.

@kastkeepitjumpinlikekangaroos
Copy link
Contributor Author

kastkeepitjumpinlikekangaroos commented Oct 25, 2024

I got an email about this job failure but looks like all the checks are passing on the PR https://github.com/psf/black/actions/runs/11377698063/job/31652281800 is this something that needs to be addressed?

I got this same error again on the rerun of the workflows https://github.com/psf/black/actions/runs/11483099904/job/31957735676 and seems to be because there's no artifact in this workflow https://github.com/psf/black/actions/runs/11412528080 with the file name .pr-comment.json. If I'm understanding correctly it looks like this is because these tasks which call comment-body (which produces .pr-comment.json https://github.com/psf/black/blob/main/scripts/diff_shades_gha_helper.py#L167) only executes when the matrix mode is preview-changes and the above diff-shades workflow has a matrix mode of analysis

https://github.com/psf/black/blob/main/.github/workflows/diff_shades.yml#L130:

      - name: Generate summary file (PR only)
        if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
        run: >
          python helper.py comment-body
          ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
          ${{ matrix.baseline-sha }} ${{ matrix.target-sha }}
          ${{ github.event.pull_request.number }}

      - name: Upload summary file (PR only)
        if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
        uses: actions/upload-artifact@v3
        with:
          name: .pr-comment.json
          path: .pr-comment.json

@kastkeepitjumpinlikekangaroos
Copy link
Contributor Author

hey @JelleZijlstra ! :) just bumping this PR - do the changes look good or are there other modifications you'd like to see?

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks reasonable

One nit: could you move the logic down next to

black/src/black/lines.py

Lines 674 to 680 in c98fc0c

if (
self.previous_line.is_import
and not current_line.is_import
and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
and depth == self.previous_line.depth
):
return (before or 1), 0
and also add a test case for when imports are within a function?

@kastkeepitjumpinlikekangaroos
Copy link
Contributor Author

Thanks, this looks reasonable

One nit: could you move the logic down next to

black/src/black/lines.py

Lines 674 to 680 in c98fc0c

if (
self.previous_line.is_import
and not current_line.is_import
and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
and depth == self.previous_line.depth
):
return (before or 1), 0

and also add a test case for when imports are within a function?

@hauntsaninja for sure, let me know if where I moved the logic is what you were thinking!

also moved all the case cases to a single file, added a test case for imports inside a function, and expanded some existing test cases

Copy link
Collaborator

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, just some wordsmithing

@JelleZijlstra JelleZijlstra merged commit e54f86b into psf:main Dec 4, 2024
luketainton pushed a commit to luketainton/repos_PwnedPW that referenced this pull request Feb 10, 2025
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | dependency-groups | major | `<25.0.0,>=24.10.0` -> `<25.2.0,>=25.1.0` |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v25.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2510)

[Compare Source](psf/black@24.10.0...25.1.0)

##### Highlights

This release introduces the new 2025 stable style ([#&#8203;4558](psf/black#4558)), stabilizing
the following changes:

-   Normalize casing of Unicode escape characters in strings to lowercase ([#&#8203;2916](psf/black#2916))
-   Fix inconsistencies in whether certain strings are detected as docstrings ([#&#8203;4095](psf/black#4095))
-   Consistently add trailing commas to typed function parameters ([#&#8203;4164](psf/black#4164))
-   Remove redundant parentheses in if guards for case blocks ([#&#8203;4214](psf/black#4214))
-   Add parentheses to if clauses in case blocks when the line is too long ([#&#8203;4269](psf/black#4269))
-   Whitespace before `# fmt: skip` comments is no longer normalized ([#&#8203;4146](psf/black#4146))
-   Fix line length computation for certain expressions that involve the power operator ([#&#8203;4154](psf/black#4154))
-   Check if there is a newline before the terminating quotes of a docstring ([#&#8203;4185](psf/black#4185))
-   Fix type annotation spacing between `*` and more complex type variable tuple ([#&#8203;4440](psf/black#4440))

The following changes were not in any previous release:

-   Remove parentheses around sole list items ([#&#8203;4312](psf/black#4312))
-   Generic function definitions are now formatted more elegantly: parameters are
    split over multiple lines first instead of type parameter definitions ([#&#8203;4553](psf/black#4553))

##### Stable style

-   Fix formatting cells in IPython notebooks with magic methods and starting or trailing
    empty lines ([#&#8203;4484](psf/black#4484))
-   Fix crash when formatting `with` statements containing tuple generators/unpacking
    ([#&#8203;4538](psf/black#4538))

##### Preview style

-   Fix/remove string merging changing f-string quotes on f-strings with internal quotes
    ([#&#8203;4498](psf/black#4498))
-   Collapse multiple empty lines after an import into one ([#&#8203;4489](psf/black#4489))
-   Prevent `string_processing` and `wrap_long_dict_values_in_parens` from removing
    parentheses around long dictionary values ([#&#8203;4377](psf/black#4377))
-   Move `wrap_long_dict_values_in_parens` from the unstable to preview style ([#&#8203;4561](psf/black#4561))

##### Packaging

-   Store license identifier inside the `License-Expression` metadata field, see
    [PEP 639](https://peps.python.org/pep-0639/). ([#&#8203;4479](psf/black#4479))

##### Performance

-   Speed up the `is_fstring_start` function in Black's tokenizer ([#&#8203;4541](psf/black#4541))

##### Integrations

-   If using stdin with `--stdin-filename` set to a force excluded path, stdin won't be
    formatted. ([#&#8203;4539](psf/black#4539))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJsaW50aW5nIl19-->

Reviewed-on: https://git.tainton.uk/repos/PwnedPW/pulls/283
Reviewed-by: Luke Tainton <luke@tainton.uk>
Co-authored-by: Renovate [BOT] <renovate-bot@git.tainton.uk>
Co-committed-by: Renovate [BOT] <renovate-bot@git.tainton.uk>
@dylwil3 dylwil3 mentioned this pull request Sep 19, 2025
31 tasks
736-c41-2c1-e464fc974 added a commit to Swiss-Armed-Forces/Loom that referenced this pull request Dec 30, 2025
This MR contains the following updates:

| Package | Type | Update | Change | OpenSSF |
|---|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | dev | major | `^24.4.2` → `^25.0.0` | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/psf/black/badge)](https://securityscorecards.dev/viewer/?uri=github.com/psf/black) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v25.12.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#25120)

[Compare Source](psf/black@25.11.0...25.12.0)

##### Highlights

- Black no longer supports running with Python 3.9 ([#&#8203;4842](psf/black#4842))

##### Stable style

- Fix bug where comments preceding `# fmt: off`/`# fmt: on` blocks were incorrectly
  removed, particularly affecting Jupytext's `# %% [markdown]` comments ([#&#8203;4845](psf/black#4845))
- Fix crash when multiple `# fmt: skip` comments are used in a multi-part if-clause, on
  string literals, or on dictionary entries with long lines ([#&#8203;4872](psf/black#4872))
- Fix possible crash when `fmt: ` directives aren't on the top level ([#&#8203;4856](psf/black#4856))

##### Preview style

- Fix `fmt: skip` skipping the line after instead of the line it's on ([#&#8203;4855](psf/black#4855))
- Remove unnecessary parentheses from the left-hand side of assignments while preserving
  magic trailing commas and intentional multiline formatting ([#&#8203;4865](psf/black#4865))
- Fix `fix_fmt_skip_in_one_liners` crashing on `with` statements ([#&#8203;4853](psf/black#4853))
- Fix `fix_fmt_skip_in_one_liners` crashing on annotated parameters ([#&#8203;4854](psf/black#4854))
- Fix new lines being added after imports with `# fmt: skip` on them ([#&#8203;4894](psf/black#4894))

##### Packaging

- Releases now include arm64 Windows binaries and wheels ([#&#8203;4814](psf/black#4814))

##### Integrations

- Add `output-file` input to GitHub Action `psf/black` to write formatter output to a
  file for artifact capture and log cleanliness ([#&#8203;4824](psf/black#4824))

### [`v25.11.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#25110)

[Compare Source](psf/black@25.9.0...25.11.0)

##### Highlights

- Enable base 3.14 support ([#&#8203;4804](psf/black#4804))
- Add support for the new Python 3.14 t-string syntax introduced by PEP 750 ([#&#8203;4805](psf/black#4805))

##### Stable style

- Fix bug where comments between `# fmt: off` and `# fmt: on` were reformatted ([#&#8203;4811](psf/black#4811))
- Comments containing fmt directives now preserve their exact formatting instead of
  being normalized ([#&#8203;4811](psf/black#4811))

##### Preview style

- Move `multiline_string_handling` from `--unstable` to `--preview` ([#&#8203;4760](psf/black#4760))
- Fix bug where module docstrings would be treated as normal strings if preceded by
  comments ([#&#8203;4764](psf/black#4764))
- Fix bug where python 3.12 generics syntax split line happens weirdly ([#&#8203;4777](psf/black#4777))
- Standardize type comments to form `# type: <value>` ([#&#8203;4645](psf/black#4645))
- Fix `fix_fmt_skip_in_one_liners` preview feature to respect `# fmt: skip` for compound
  statements with semicolon-separated bodies ([#&#8203;4800](psf/black#4800))

##### Configuration

- Add `no_cache` option to control caching behavior. ([#&#8203;4803](psf/black#4803))

##### Packaging

- Releases now include arm64 Linux binaries ([#&#8203;4773](psf/black#4773))

##### Output

- Write unchanged content to stdout when excluding formatting from stdin using pipes
  ([#&#8203;4610](psf/black#4610))

##### *Blackd*

- Implemented BlackDClient. This simple python client allows to easily send formatting
  requests to blackd ([#&#8203;4774](psf/black#4774))

##### Integrations

- Enable 3.14 base CI ([#&#8203;4804](psf/black#4804))
- Enhance GitHub Action `psf/black` to support the `required-version` major-version-only
  "stability" format when using pyproject.toml ([#&#8203;4770](psf/black#4770))
- Improve error message for vim plugin users. It now handles independently vim version
- Vim: Warn on unsupported Vim and Python versions independently ([#&#8203;4772](psf/black#4772))
- Vim: Print the import paths when importing black fails ([#&#8203;4675](psf/black#4675))
- Vim: Fix handling of virtualenvs that have a different Python version ([#&#8203;4675](psf/black#4675))

### [`v25.9.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2590)

[Compare Source](psf/black@25.1.0...25.9.0)

##### Highlights

- Remove support for pre-python 3.7 `await/async` as soft keywords/variable names
  ([#&#8203;4676](psf/black#4676))

##### Stable style

- Fix crash while formatting a long `del` statement containing tuples ([#&#8203;4628](psf/black#4628))
- Fix crash while formatting expressions using the walrus operator in complex `with`
  statements ([#&#8203;4630](psf/black#4630))
- Handle `# fmt: skip` followed by a comment at the end of file ([#&#8203;4635](psf/black#4635))
- Fix crash when a tuple appears in the `as` clause of a `with` statement ([#&#8203;4634](psf/black#4634))
- Fix crash when tuple is used as a context manager inside a `with` statement ([#&#8203;4646](psf/black#4646))
- Fix crash when formatting a `\` followed by a `\r` followed by a comment ([#&#8203;4663](psf/black#4663))
- Fix crash on a `\\r\n` ([#&#8203;4673](psf/black#4673))
- Fix crash on `await ...` (where `...` is a literal `Ellipsis`) ([#&#8203;4676](psf/black#4676))
- Fix crash on parenthesized expression inside a type parameter bound ([#&#8203;4684](psf/black#4684))
- Fix crash when using line ranges excluding indented single line decorated items
  ([#&#8203;4670](psf/black#4670))

##### Preview style

- Fix a bug where one-liner functions/conditionals marked with `# fmt: skip` would still
  be formatted ([#&#8203;4552](psf/black#4552))
- Improve `multiline_string_handling` with ternaries and dictionaries ([#&#8203;4657](psf/black#4657))
- Fix a bug where `string_processing` would not split f-strings directly after
  expressions ([#&#8203;4680](psf/black#4680))
- Wrap the `in` clause of comprehensions across lines if necessary ([#&#8203;4699](psf/black#4699))
- Remove parentheses around multiple exception types in `except` and `except*` without
  `as`. ([#&#8203;4720](psf/black#4720))
- Add `\r` style newlines to the potential newlines to normalize file newlines both from
  and to ([#&#8203;4710](psf/black#4710))

##### Parser

- Rewrite tokenizer to improve performance and compliance ([#&#8203;4536](psf/black#4536))
- Fix bug where certain unusual expressions (e.g., lambdas) were not accepted in type
  parameter bounds and defaults. ([#&#8203;4602](psf/black#4602))

##### Performance

- Avoid using an extra process when running with only one worker ([#&#8203;4734](psf/black#4734))

##### Integrations

- Fix the version check in the vim file to reject Python 3.8 ([#&#8203;4567](psf/black#4567))
- Enhance GitHub Action `psf/black` to read Black version from an additional section in
  pyproject.toml: `[project.dependency-groups]` ([#&#8203;4606](psf/black#4606))
- Build gallery docker image with python3-slim and reduce image size ([#&#8203;4686](psf/black#4686))

##### Documentation

- Add FAQ entry for windows emoji not displaying ([#&#8203;4714](psf/black#4714))

### [`v25.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2510)

[Compare Source](psf/black@24.10.0...25.1.0)

##### Highlights

This release introduces the new 2025 stable style ([#&#8203;4558](psf/black#4558)), stabilizing the following
changes:

- Normalize casing of Unicode escape characters in strings to lowercase ([#&#8203;2916](psf/black#2916))
- Fix inconsistencies in whether certain strings are detected as docstrings ([#&#8203;4095](psf/black#4095))
- Consistently add trailing commas to typed function parameters ([#&#8203;4164](psf/black#4164))
- Remove redundant parentheses in if guards for case blocks ([#&#8203;4214](psf/black#4214))
- Add parentheses to if clauses in case blocks when the line is too long ([#&#8203;4269](psf/black#4269))
- Whitespace before `# fmt: skip` comments is no longer normalized ([#&#8203;4146](psf/black#4146))
- Fix line length computation for certain expressions that involve the power operator
  ([#&#8203;4154](psf/black#4154))
- Check if there is a newline before the terminating quotes of a docstring ([#&#8203;4185](psf/black#4185))
- Fix type annotation spacing between `*` and more complex type variable tuple ([#&#8203;4440](psf/black#4440))

The following changes were not in any previous release:

- Remove parentheses around sole list items ([#&#8203;4312](psf/black#4312))
- Generic function definitions are now formatted more elegantly: parameters are split
  over multiple lines first instead of type parameter definitions ([#&#8203;4553](psf/black#4553))

##### Stable style

- Fix formatting cells in IPython notebooks with magic methods and starting or trailing
  empty lines ([#&#8203;4484](psf/black#4484))
- Fix crash when formatting `with` statements containing tuple generators/unpacking
  ([#&#8203;4538](psf/black#4538))

##### Preview style

- Fix/remove string merging changing f-string quotes on f-strings with internal quotes
  ([#&#8203;4498](psf/black#4498))
- Collapse multiple empty lines after an import into one ([#&#8203;4489](psf/black#4489))
- Prevent `string_processing` and `wrap_long_dict_values_in_parens` from removing
  parentheses around long dictionary values ([#&#8203;4377](psf/black#4377))
- Move `wrap_long_dict_values_in_parens` from the unstable to preview style ([#&#8203;4561](psf/black#4561))

##### Packaging

- Store license identifier inside the `License-Expression` metadata field, see
  [PEP 639](https://peps.python.org/pep-0639/). ([#&#8203;4479](psf/black#4479))

##### Performance

- Speed up the `is_fstring_start` function in Black's tokenizer ([#&#8203;4541](psf/black#4541))

##### Integrations

- If using stdin with `--stdin-filename` set to a force excluded path, stdin won't be
  formatted. ([#&#8203;4539](psf/black#4539))

### [`v24.10.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#24100)

[Compare Source](psf/black@24.8.0...24.10.0)

##### Highlights

- Black is now officially tested with Python 3.13 and provides Python 3.13
  mypyc-compiled wheels. ([#&#8203;4436](psf/black#4436)) ([#&#8203;4449](psf/black#4449))
- Black will issue an error when used with Python 3.12.5, due to an upstream memory
  safety issue in Python 3.12.5 that can cause Black's AST safety checks to fail. Please
  use Python 3.12.6 or Python 3.12.4 instead. ([#&#8203;4447](psf/black#4447))
- Black no longer supports running with Python 3.8 ([#&#8203;4452](psf/black#4452))

##### Stable style

- Fix crashes involving comments in parenthesised return types or `X | Y` style unions.
  ([#&#8203;4453](psf/black#4453))
- Fix skipping Jupyter cells with unknown `%%` magic ([#&#8203;4462](psf/black#4462))

##### Preview style

- Fix type annotation spacing between \* and more complex type variable tuple (i.e. `def
  fn(*args: *tuple[*Ts, T]) -> None: pass`) ([#&#8203;4440](psf/black#4440))

##### Caching

- Fix bug where the cache was shared between runs with and without `--unstable` ([#&#8203;4466](psf/black#4466))

##### Packaging

- Upgrade version of mypyc used to 1.12 beta ([#&#8203;4450](psf/black#4450)) ([#&#8203;4449](psf/black#4449))
- `blackd` now requires a newer version of aiohttp. ([#&#8203;4451](psf/black#4451))

##### Output

- Added Python target version information on parse error ([#&#8203;4378](psf/black#4378))
- Add information about Black version to internal error messages ([#&#8203;4457](psf/black#4457))

### [`v24.8.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2480)

[Compare Source](psf/black@24.4.2...24.8.0)

##### Stable style

- Fix crash when `# fmt: off` is used before a closing parenthesis or bracket. ([#&#8203;4363](psf/black#4363))

##### Packaging

- Packaging metadata updated: docs are explictly linked, the issue tracker is now also
  linked. This improves the PyPI listing for Black. ([#&#8203;4345](psf/black#4345))

##### Parser

- Fix regression where Black failed to parse a multiline f-string containing another
  multiline string ([#&#8203;4339](psf/black#4339))
- Fix regression where Black failed to parse an escaped single quote inside an f-string
  ([#&#8203;4401](psf/black#4401))
- Fix bug with Black incorrectly parsing empty lines with a backslash ([#&#8203;4343](psf/black#4343))
- Fix bugs with Black's tokenizer not handling `\{` inside f-strings very well ([#&#8203;4422](psf/black#4422))
- Fix incorrect line numbers in the tokenizer for certain tokens within f-strings
  ([#&#8203;4423](psf/black#4423))

##### Performance

- Improve performance when a large directory is listed in `.gitignore` ([#&#8203;4415](psf/black#4415))

##### *Blackd*

- Fix blackd (and all extras installs) for docker container ([#&#8203;4357](psf/black#4357))

</details>

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4yNy4xIiwidXBkYXRlZEluVmVyIjoiNDIuNjAuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIiwicmVub3ZhdGUiXX0=-->

See merge request swiss-armed-forces/cyber-command/cea/loom!235

Co-authored-by: shrewd-laidback palace <shrewd-laidback-palace-736-c41-2c1-e464fc974@swiss-armed-forces-open-source.ch>
Co-authored-by: Loom MR Pipeline Trigger <group_103951964_bot_9504bb8dead6d4e406ad817a607f24be@noreply.gitlab.com>
736-c41-2c1-e464fc974 added a commit to Swiss-Armed-Forces/Loom that referenced this pull request Dec 30, 2025
chore(deps): update black (major)

This MR contains the following updates:

| Package | Type | Update | Change | OpenSSF |
|---|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | dev | major | `^24.4.2` → `^25.0.0` | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/psf/black/badge)](https://securityscorecards.dev/viewer/?uri=github.com/psf/black) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v25.12.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#25120)

[Compare Source](psf/black@25.11.0...25.12.0)

##### Highlights

- Black no longer supports running with Python 3.9 ([#&#8203;4842](psf/black#4842))

##### Stable style

- Fix bug where comments preceding `# fmt: off`/`# fmt: on` blocks were incorrectly
  removed, particularly affecting Jupytext's `# %% [markdown]` comments ([#&#8203;4845](psf/black#4845))
- Fix crash when multiple `# fmt: skip` comments are used in a multi-part if-clause, on
  string literals, or on dictionary entries with long lines ([#&#8203;4872](psf/black#4872))
- Fix possible crash when `fmt: ` directives aren't on the top level ([#&#8203;4856](psf/black#4856))

##### Preview style

- Fix `fmt: skip` skipping the line after instead of the line it's on ([#&#8203;4855](psf/black#4855))
- Remove unnecessary parentheses from the left-hand side of assignments while preserving
  magic trailing commas and intentional multiline formatting ([#&#8203;4865](psf/black#4865))
- Fix `fix_fmt_skip_in_one_liners` crashing on `with` statements ([#&#8203;4853](psf/black#4853))
- Fix `fix_fmt_skip_in_one_liners` crashing on annotated parameters ([#&#8203;4854](psf/black#4854))
- Fix new lines being added after imports with `# fmt: skip` on them ([#&#8203;4894](psf/black#4894))

##### Packaging

- Releases now include arm64 Windows binaries and wheels ([#&#8203;4814](psf/black#4814))

##### Integrations

- Add `output-file` input to GitHub Action `psf/black` to write formatter output to a
  file for artifact capture and log cleanliness ([#&#8203;4824](psf/black#4824))

### [`v25.11.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#25110)

[Compare Source](psf/black@25.9.0...25.11.0)

##### Highlights

- Enable base 3.14 support ([#&#8203;4804](psf/black#4804))
- Add support for the new Python 3.14 t-string syntax introduced by PEP 750 ([#&#8203;4805](psf/black#4805))

##### Stable style

- Fix bug where comments between `# fmt: off` and `# fmt: on` were reformatted ([#&#8203;4811](psf/black#4811))
- Comments containing fmt directives now preserve their exact formatting instead of
  being normalized ([#&#8203;4811](psf/black#4811))

##### Preview style

- Move `multiline_string_handling` from `--unstable` to `--preview` ([#&#8203;4760](psf/black#4760))
- Fix bug where module docstrings would be treated as normal strings if preceded by
  comments ([#&#8203;4764](psf/black#4764))
- Fix bug where python 3.12 generics syntax split line happens weirdly ([#&#8203;4777](psf/black#4777))
- Standardize type comments to form `# type: <value>` ([#&#8203;4645](psf/black#4645))
- Fix `fix_fmt_skip_in_one_liners` preview feature to respect `# fmt: skip` for compound
  statements with semicolon-separated bodies ([#&#8203;4800](psf/black#4800))

##### Configuration

- Add `no_cache` option to control caching behavior. ([#&#8203;4803](psf/black#4803))

##### Packaging

- Releases now include arm64 Linux binaries ([#&#8203;4773](psf/black#4773))

##### Output

- Write unchanged content to stdout when excluding formatting from stdin using pipes
  ([#&#8203;4610](psf/black#4610))

##### *Blackd*

- Implemented BlackDClient. This simple python client allows to easily send formatting
  requests to blackd ([#&#8203;4774](psf/black#4774))

##### Integrations

- Enable 3.14 base CI ([#&#8203;4804](psf/black#4804))
- Enhance GitHub Action `psf/black` to support the `required-version` major-version-only
  "stability" format when using pyproject.toml ([#&#8203;4770](psf/black#4770))
- Improve error message for vim plugin users. It now handles independently vim version
- Vim: Warn on unsupported Vim and Python versions independently ([#&#8203;4772](psf/black#4772))
- Vim: Print the import paths when importing black fails ([#&#8203;4675](psf/black#4675))
- Vim: Fix handling of virtualenvs that have a different Python version ([#&#8203;4675](psf/black#4675))

### [`v25.9.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2590)

[Compare Source](psf/black@25.1.0...25.9.0)

##### Highlights

- Remove support for pre-python 3.7 `await/async` as soft keywords/variable names
  ([#&#8203;4676](psf/black#4676))

##### Stable style

- Fix crash while formatting a long `del` statement containing tuples ([#&#8203;4628](psf/black#4628))
- Fix crash while formatting expressions using the walrus operator in complex `with`
  statements ([#&#8203;4630](psf/black#4630))
- Handle `# fmt: skip` followed by a comment at the end of file ([#&#8203;4635](psf/black#4635))
- Fix crash when a tuple appears in the `as` clause of a `with` statement ([#&#8203;4634](psf/black#4634))
- Fix crash when tuple is used as a context manager inside a `with` statement ([#&#8203;4646](psf/black#4646))
- Fix crash when formatting a `\` followed by a `\r` followed by a comment ([#&#8203;4663](psf/black#4663))
- Fix crash on a `\\r\n` ([#&#8203;4673](psf/black#4673))
- Fix crash on `await ...` (where `...` is a literal `Ellipsis`) ([#&#8203;4676](psf/black#4676))
- Fix crash on parenthesized expression inside a type parameter bound ([#&#8203;4684](psf/black#4684))
- Fix crash when using line ranges excluding indented single line decorated items
  ([#&#8203;4670](psf/black#4670))

##### Preview style

- Fix a bug where one-liner functions/conditionals marked with `# fmt: skip` would still
  be formatted ([#&#8203;4552](psf/black#4552))
- Improve `multiline_string_handling` with ternaries and dictionaries ([#&#8203;4657](psf/black#4657))
- Fix a bug where `string_processing` would not split f-strings directly after
  expressions ([#&#8203;4680](psf/black#4680))
- Wrap the `in` clause of comprehensions across lines if necessary ([#&#8203;4699](psf/black#4699))
- Remove parentheses around multiple exception types in `except` and `except*` without
  `as`. ([#&#8203;4720](psf/black#4720))
- Add `\r` style newlines to the potential newlines to normalize file newlines both from
  and to ([#&#8203;4710](psf/black#4710))

##### Parser

- Rewrite tokenizer to improve performance and compliance ([#&#8203;4536](psf/black#4536))
- Fix bug where certain unusual expressions (e.g., lambdas) were not accepted in type
  parameter bounds and defaults. ([#&#8203;4602](psf/black#4602))

##### Performance

- Avoid using an extra process when running with only one worker ([#&#8203;4734](psf/black#4734))

##### Integrations

- Fix the version check in the vim file to reject Python 3.8 ([#&#8203;4567](psf/black#4567))
- Enhance GitHub Action `psf/black` to read Black version from an additional section in
  pyproject.toml: `[project.dependency-groups]` ([#&#8203;4606](psf/black#4606))
- Build gallery docker image with python3-slim and reduce image size ([#&#8203;4686](psf/black#4686))

##### Documentation

- Add FAQ entry for windows emoji not displaying ([#&#8203;4714](psf/black#4714))

### [`v25.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2510)

[Compare Source](psf/black@24.10.0...25.1.0)

##### Highlights

This release introduces the new 2025 stable style ([#&#8203;4558](psf/black#4558)), stabilizing the following
changes:

- Normalize casing of Unicode escape characters in strings to lowercase ([#&#8203;2916](psf/black#2916))
- Fix inconsistencies in whether certain strings are detected as docstrings ([#&#8203;4095](psf/black#4095))
- Consistently add trailing commas to typed function parameters ([#&#8203;4164](psf/black#4164))
- Remove redundant parentheses in if guards for case blocks ([#&#8203;4214](psf/black#4214))
- Add parentheses to if clauses in case blocks when the line is too long ([#&#8203;4269](psf/black#4269))
- Whitespace before `# fmt: skip` comments is no longer normalized ([#&#8203;4146](psf/black#4146))
- Fix line length computation for certain expressions that involve the power operator
  ([#&#8203;4154](psf/black#4154))
- Check if there is a newline before the terminating quotes of a docstring ([#&#8203;4185](psf/black#4185))
- Fix type annotation spacing between `*` and more complex type variable tuple ([#&#8203;4440](psf/black#4440))

The following changes were not in any previous release:

- Remove parentheses around sole list items ([#&#8203;4312](psf/black#4312))
- Generic function definitions are now formatted more elegantly: parameters are split
  over multiple lines first instead of type parameter definitions ([#&#8203;4553](psf/black#4553))

##### Stable style

- Fix formatting cells in IPython notebooks with magic methods and starting or trailing
  empty lines ([#&#8203;4484](psf/black#4484))
- Fix crash when formatting `with` statements containing tuple generators/unpacking
  ([#&#8203;4538](psf/black#4538))

##### Preview style

- Fix/remove string merging changing f-string quotes on f-strings with internal quotes
  ([#&#8203;4498](psf/black#4498))
- Collapse multiple empty lines after an import into one ([#&#8203;4489](psf/black#4489))
- Prevent `string_processing` and `wrap_long_dict_values_in_parens` from removing
  parentheses around long dictionary values ([#&#8203;4377](psf/black#4377))
- Move `wrap_long_dict_values_in_parens` from the unstable to preview style ([#&#8203;4561](psf/black#4561))

##### Packaging

- Store license identifier inside the `License-Expression` metadata field, see
  [PEP 639](https://peps.python.org/pep-0639/). ([#&#8203;4479](psf/black#4479))

##### Performance

- Speed up the `is_fstring_start` function in Black's tokenizer ([#&#8203;4541](psf/black#4541))

##### Integrations

- If using stdin with `--stdin-filename` set to a force excluded path, stdin won't be
  formatted. ([#&#8203;4539](psf/black#4539))

### [`v24.10.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#24100)

[Compare Source](psf/black@24.8.0...24.10.0)

##### Highlights

- Black is now officially tested with Python 3.13 and provides Python 3.13
  mypyc-compiled wheels. ([#&#8203;4436](psf/black#4436)) ([#&#8203;4449](psf/black#4449))
- Black will issue an error when used with Python 3.12.5, due to an upstream memory
  safety issue in Python 3.12.5 that can cause Black's AST safety checks to fail. Please
  use Python 3.12.6 or Python 3.12.4 instead. ([#&#8203;4447](psf/black#4447))
- Black no longer supports running with Python 3.8 ([#&#8203;4452](psf/black#4452))

##### Stable style

- Fix crashes involving comments in parenthesised return types or `X | Y` style unions.
  ([#&#8203;4453](psf/black#4453))
- Fix skipping Jupyter cells with unknown `%%` magic ([#&#8203;4462](psf/black#4462))

##### Preview style

- Fix type annotation spacing between \* and more complex type variable tuple (i.e. `def
  fn(*args: *tuple[*Ts, T]) -> None: pass`) ([#&#8203;4440](psf/black#4440))

##### Caching

- Fix bug where the cache was shared between runs with and without `--unstable` ([#&#8203;4466](psf/black#4466))

##### Packaging

- Upgrade version of mypyc used to 1.12 beta ([#&#8203;4450](psf/black#4450)) ([#&#8203;4449](psf/black#4449))
- `blackd` now requires a newer version of aiohttp. ([#&#8203;4451](psf/black#4451))

##### Output

- Added Python target version information on parse error ([#&#8203;4378](psf/black#4378))
- Add information about Black version to internal error messages ([#&#8203;4457](psf/black#4457))

### [`v24.8.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2480)

[Compare Source](psf/black@24.4.2...24.8.0)

##### Stable style

- Fix crash when `# fmt: off` is used before a closing parenthesis or bracket. ([#&#8203;4363](psf/black#4363))

##### Packaging

- Packaging metadata updated: docs are explictly linked, the issue tracker is now also
  linked. This improves the PyPI listing for Black. ([#&#8203;4345](psf/black#4345))

##### Parser

- Fix regression where Black failed to parse a multiline f-string containing another
  multiline string ([#&#8203;4339](psf/black#4339))
- Fix regression where Black failed to parse an escaped single quote inside an f-string
  ([#&#8203;4401](psf/black#4401))
- Fix bug with Black incorrectly parsing empty lines with a backslash ([#&#8203;4343](psf/black#4343))
- Fix bugs with Black's tokenizer not handling `\{` inside f-strings very well ([#&#8203;4422](psf/black#4422))
- Fix incorrect line numbers in the tokenizer for certain tokens within f-strings
  ([#&#8203;4423](psf/black#4423))

##### Performance

- Improve performance when a large directory is listed in `.gitignore` ([#&#8203;4415](psf/black#4415))

##### *Blackd*

- Fix blackd (and all extras installs) for docker container ([#&#8203;4357](psf/black#4357))

</details>

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4yNy4xIiwidXBkYXRlZEluVmVyIjoiNDIuNjAuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIiwicmVub3ZhdGUiXX0=-->

See merge request swiss-armed-forces/cyber-command/cea/loom!235

Co-authored-by: Loom MR Pipeline Trigger <group_103951964_bot_9504bb8dead6d4e406ad817a607f24be@noreply.gitlab.com>
Co-authored-by: open-source Pipeline <group_90701827_bot_ed04ae348bc5f40af9966fb8b6867e99@noreply.gitlab.com>
luketainton pushed a commit to luketainton/repos_pypilot that referenced this pull request Jan 18, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | `<25.12.1,>=25.12.0` → `<26.1.1,>=26.1.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/black/26.1.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/black/25.12.0/26.1.0?slim=true) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v26.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2610)

[Compare Source](psf/black@25.12.0...26.1.0)

##### Highlights

Introduces the 2026 stable style ([#&#8203;4892](psf/black#4892)), stabilizing the following changes:

- `always_one_newline_after_import`: Always force one blank line after import
  statements, except when the line after the import is a comment or an import statement
  ([#&#8203;4489](psf/black#4489))
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behavior on one-liner declarations,
  such as `def foo(): return "mock" # fmt: skip`, where previously the declaration would
  have been incorrectly collapsed ([#&#8203;4800](psf/black#4800))
- `fix_module_docstring_detection`: Fix module docstrings being treated as normal
  strings if preceded by comments ([#&#8203;4764](psf/black#4764))
- `fix_type_expansion_split`: Fix type expansions split in generic functions ([#&#8203;4777](psf/black#4777))
- `multiline_string_handling`: Make expressions involving multiline strings more compact
  ([#&#8203;1879](psf/black#1879))
- `normalize_cr_newlines`: Add `\r` style newlines to the potential newlines to
  normalize file newlines both from and to ([#&#8203;4710](psf/black#4710))
- `remove_parens_around_except_types`: Remove parentheses around multiple exception
  types in `except` and `except*` without `as` ([#&#8203;4720](psf/black#4720))
- `remove_parens_from_assignment_lhs`: Remove unnecessary parentheses from the left-hand
  side of assignments while preserving magic trailing commas and intentional multiline
  formatting ([#&#8203;4865](psf/black#4865))
- `standardize_type_comments`: Format type comments which have zero or more spaces
  between `#` and `type:` or between `type:` and value to `# type: (value)` ([#&#8203;4645](psf/black#4645))

The following change was not in any previous stable release:

- Regenerated the `_width_table.py` and added tests for the Khmer language ([#&#8203;4253](psf/black#4253))

This release alo bumps `pathspec` to v1 and fixes inconsistencies with Git's
`.gitignore` logic ([#&#8203;4958](psf/black#4958)). Now, files will be ignored if a pattern matches them, even
if the parent directory is directly unignored. For example, Black would previously
format `exclude/not_this/foo.py` with this `.gitignore`:

```
exclude/
!exclude/not_this/
```

Now, `exclude/not_this/foo.py` will remain ignored. To ensure `exclude/not_this/` and
all of it's children are included in formatting (and in Git), use this `.gitignore`:

```
*/exclude/*
!*/exclude/not_this/
```

This new behavior matches Git. The leading `*/` are only necessary if you wish to ignore
matching subdirectories (like the previous behavior did), and not just matching root
directories.

##### Output

- Explicitly shutdown the multiprocessing manager when run in diff mode too ([#&#8203;4952](psf/black#4952))

##### Integrations

- Upgraded PyPI upload workflow to use Trusted Publishing ([#&#8203;4611](psf/black#4611))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi44NC4yIiwidXBkYXRlZEluVmVyIjoiNDIuODQuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsidHlwZS9kZXBlbmRlbmNpZXMiXX0=-->

Reviewed-on: https://git.tainton.uk/repos/pypilot/pulls/408
Co-authored-by: renovate[bot] <renovate-bot@git.tainton.uk>
Co-committed-by: renovate[bot] <renovate-bot@git.tainton.uk>
luketainton pushed a commit to luketainton/luke_instant-msg-api that referenced this pull request Jan 18, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | `<25.12.1,>=25.12.0` → `<26.1.1,>=26.1.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/black/26.1.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/black/25.12.0/26.1.0?slim=true) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v26.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2610)

[Compare Source](psf/black@25.12.0...26.1.0)

##### Highlights

Introduces the 2026 stable style ([#&#8203;4892](psf/black#4892)), stabilizing the following changes:

- `always_one_newline_after_import`: Always force one blank line after import
  statements, except when the line after the import is a comment or an import statement
  ([#&#8203;4489](psf/black#4489))
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behavior on one-liner declarations,
  such as `def foo(): return "mock" # fmt: skip`, where previously the declaration would
  have been incorrectly collapsed ([#&#8203;4800](psf/black#4800))
- `fix_module_docstring_detection`: Fix module docstrings being treated as normal
  strings if preceded by comments ([#&#8203;4764](psf/black#4764))
- `fix_type_expansion_split`: Fix type expansions split in generic functions ([#&#8203;4777](psf/black#4777))
- `multiline_string_handling`: Make expressions involving multiline strings more compact
  ([#&#8203;1879](psf/black#1879))
- `normalize_cr_newlines`: Add `\r` style newlines to the potential newlines to
  normalize file newlines both from and to ([#&#8203;4710](psf/black#4710))
- `remove_parens_around_except_types`: Remove parentheses around multiple exception
  types in `except` and `except*` without `as` ([#&#8203;4720](psf/black#4720))
- `remove_parens_from_assignment_lhs`: Remove unnecessary parentheses from the left-hand
  side of assignments while preserving magic trailing commas and intentional multiline
  formatting ([#&#8203;4865](psf/black#4865))
- `standardize_type_comments`: Format type comments which have zero or more spaces
  between `#` and `type:` or between `type:` and value to `# type: (value)` ([#&#8203;4645](psf/black#4645))

The following change was not in any previous stable release:

- Regenerated the `_width_table.py` and added tests for the Khmer language ([#&#8203;4253](psf/black#4253))

This release alo bumps `pathspec` to v1 and fixes inconsistencies with Git's
`.gitignore` logic ([#&#8203;4958](psf/black#4958)). Now, files will be ignored if a pattern matches them, even
if the parent directory is directly unignored. For example, Black would previously
format `exclude/not_this/foo.py` with this `.gitignore`:

```
exclude/
!exclude/not_this/
```

Now, `exclude/not_this/foo.py` will remain ignored. To ensure `exclude/not_this/` and
all of it's children are included in formatting (and in Git), use this `.gitignore`:

```
*/exclude/*
!*/exclude/not_this/
```

This new behavior matches Git. The leading `*/` are only necessary if you wish to ignore
matching subdirectories (like the previous behavior did), and not just matching root
directories.

##### Output

- Explicitly shutdown the multiprocessing manager when run in diff mode too ([#&#8203;4952](psf/black#4952))

##### Integrations

- Upgraded PyPI upload workflow to use Trusted Publishing ([#&#8203;4611](psf/black#4611))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi44NC4yIiwidXBkYXRlZEluVmVyIjoiNDIuODQuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsidHlwZS9kZXBlbmRlbmNpZXMiXX0=-->

Reviewed-on: https://git.tainton.uk/luke/instant-msg-api/pulls/236
Co-authored-by: renovate[bot] <renovate-bot@git.tainton.uk>
Co-committed-by: renovate[bot] <renovate-bot@git.tainton.uk>
luketainton pushed a commit to luketainton/repos_PwnedPW that referenced this pull request Jan 18, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | `<25.12.1,>=25.12.0` → `<26.1.1,>=26.1.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/black/26.1.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/black/25.12.0/26.1.0?slim=true) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v26.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2610)

[Compare Source](psf/black@25.12.0...26.1.0)

##### Highlights

Introduces the 2026 stable style ([#&#8203;4892](psf/black#4892)), stabilizing the following changes:

- `always_one_newline_after_import`: Always force one blank line after import
  statements, except when the line after the import is a comment or an import statement
  ([#&#8203;4489](psf/black#4489))
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behavior on one-liner declarations,
  such as `def foo(): return "mock" # fmt: skip`, where previously the declaration would
  have been incorrectly collapsed ([#&#8203;4800](psf/black#4800))
- `fix_module_docstring_detection`: Fix module docstrings being treated as normal
  strings if preceded by comments ([#&#8203;4764](psf/black#4764))
- `fix_type_expansion_split`: Fix type expansions split in generic functions ([#&#8203;4777](psf/black#4777))
- `multiline_string_handling`: Make expressions involving multiline strings more compact
  ([#&#8203;1879](psf/black#1879))
- `normalize_cr_newlines`: Add `\r` style newlines to the potential newlines to
  normalize file newlines both from and to ([#&#8203;4710](psf/black#4710))
- `remove_parens_around_except_types`: Remove parentheses around multiple exception
  types in `except` and `except*` without `as` ([#&#8203;4720](psf/black#4720))
- `remove_parens_from_assignment_lhs`: Remove unnecessary parentheses from the left-hand
  side of assignments while preserving magic trailing commas and intentional multiline
  formatting ([#&#8203;4865](psf/black#4865))
- `standardize_type_comments`: Format type comments which have zero or more spaces
  between `#` and `type:` or between `type:` and value to `# type: (value)` ([#&#8203;4645](psf/black#4645))

The following change was not in any previous stable release:

- Regenerated the `_width_table.py` and added tests for the Khmer language ([#&#8203;4253](psf/black#4253))

This release alo bumps `pathspec` to v1 and fixes inconsistencies with Git's
`.gitignore` logic ([#&#8203;4958](psf/black#4958)). Now, files will be ignored if a pattern matches them, even
if the parent directory is directly unignored. For example, Black would previously
format `exclude/not_this/foo.py` with this `.gitignore`:

```
exclude/
!exclude/not_this/
```

Now, `exclude/not_this/foo.py` will remain ignored. To ensure `exclude/not_this/` and
all of it's children are included in formatting (and in Git), use this `.gitignore`:

```
*/exclude/*
!*/exclude/not_this/
```

This new behavior matches Git. The leading `*/` are only necessary if you wish to ignore
matching subdirectories (like the previous behavior did), and not just matching root
directories.

##### Output

- Explicitly shutdown the multiprocessing manager when run in diff mode too ([#&#8203;4952](psf/black#4952))

##### Integrations

- Upgraded PyPI upload workflow to use Trusted Publishing ([#&#8203;4611](psf/black#4611))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi44NC4yIiwidXBkYXRlZEluVmVyIjoiNDIuODQuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsibGludGluZyJdfQ==-->

Reviewed-on: https://git.tainton.uk/repos/PwnedPW/pulls/319
Co-authored-by: renovate[bot] <renovate-bot@git.tainton.uk>
Co-committed-by: renovate[bot] <renovate-bot@git.tainton.uk>
@CristinaBotez-Ipsos
Copy link

Well this sucks! Ever since I started working in Python (so around 2013) the recommendation was to use 2 blank lines after imports.

anoopcs9 added a commit to anoopcs9/samba-container that referenced this pull request Jan 19, 2026
A new black release[1] with 'always_one_newline_after_import'[2] rule is
causing failure with the build-image script.

[1] https://github.com/psf/black/releases/tag/26.1.0
[2] psf/black#4489

Signed-off-by: Anoop C S <anoopcs@samba.org>
@steve-mavens
Copy link

steve-mavens commented Jan 19, 2026

@CristinaBotez-Ipsos : it's not as bad as it sounds, because this rule won't violate the higher-priority rule from PEP8, "Surround top-level function and class definitions with two blank lines.". This is a change if you had assignments after your imports, with two blank lines between the imports and the assignments (which means that if you were using isort, you would already have been setting --lines-after-imports=2 to avoid the default behaviour of that tool).

@CristinaBotez-Ipsos
Copy link

@steve-mavens: Still feels wrong and inconsistent to have some files that have 1 line of code after imports and others that have 2 lines of code just because functions or classes are defined after imports. Besides this, since one blank line is used to separate the groups of imports, it would be more readable to separate the imports from the rest of the code with 2 blank lines.

mergify bot pushed a commit to samba-in-kubernetes/samba-container that referenced this pull request Jan 19, 2026
A new black release[1] with 'always_one_newline_after_import'[2] rule is
causing failure with the build-image script.

[1] https://github.com/psf/black/releases/tag/26.1.0
[2] psf/black#4489

Signed-off-by: Anoop C S <anoopcs@samba.org>
@steve-mavens
Copy link

steve-mavens commented Jan 19, 2026

@CristinaBotez-Ipsos: sure. One of the minor ways in which black violates PEP8 is that PEP8 explicitly advises prioritising readability over consistency. Whereas black both by nature of an automated tool and by ideology, prioritises consistency over readability. Its axiom in effect is that "familiar but a little bit bad" in the long term across many projects is more readable than "idiosyncratic but marginally better". I still use it, but every January I review that decision when I see the diffs ;-) In this case I personally don't see the diff you get, because I'm already using isort and I ate that change years ago. So, black's position is that it (not you or I) should decide whether the import section deserves 2 blank lines after them in the same way that functions do. Decision apparently is no, it doesn't.

This is all preamble to saying: if you check the original bug report, the intolerable situation was that black just left it alone as either 1 or 2 at the author's preference, instead of expressing an opinion one way or the other. By its nature once that situation is detected, black must either change your code or change mine, because it must not tolerate that inconsistency between your code and mine. I exaggerate because there are exceptions, but this is the principle.

@cobaltt7
Copy link
Collaborator

cobaltt7 commented Jan 19, 2026

Thanks for your feedback here! I don't think we ever had a proper discussion on whether 1 or 2 lines after the last import was better, and we just went with one of the options. From the arguments made here, I do personally think 2 lines is better.

However, moving forward, I'm not sure what the best course of action would be. Since this has already been released, we can't change it to 2 lines until next January. Plus, while I do think 2 lines are better, this change is small and has minimal effect on readability, while affecting a wide range of code and projects, so I don't know that making any further change would be worth it. Theoretically, our stability policy would allow us to remove the normalization all together in a patch release (back to how v25 was) for the sake of anyone who hasn't yet updated, then change it to normalize to two lines next year, but still that's the same noise two years in a row for everyone who already changed, which is a bit less than half of GitHub repos (open prs closed prs).

It's also worth noting that this feature has been in the preview style since 25.1.0 and was moved to preview in 26.1a1, and we never received any feedback on it before now, which would've allowed us to change it to 2 lines before reaching stable. Again, according to Black's stability policy, the behavior of Black with most settings will never change except in the first release of the year. Since these formatting changes can be anticipated even if you don't follow the issue tracker, we strongly recommend trying out the --preview style sometime around November or December, as well as the beta version we often release around that time, and giving this feedback when it can still have an impact.

@CristinaBotez-Ipsos
Copy link

Thank you for your response. Curiously, even though I did not pin the version of this dependency, the new version only got picked up today in both our local environments and the CI/CD. I must admit I was not aware of the way changes are rolled out and the --preview option. I'll know better next time.
If I may ask a possibly stupid question for those more familiar with Black: does always_one_newline_after_import behave like a flag that can be set to true or false?

@cobaltt7
Copy link
Collaborator

When this feature was added, it was added under the --preview flag. always_one_newline_after_import behaves more as a label for which code corresponds to which preview style, so it's easy for us to pick and chose come time to move things to stable. Black doesn't allow enabling specific preview styles one by one.
The --preview flag exists for users to opt-in to testing Black's proposed styles. Although --preview can be expected to be mostly bug-free, it does change with every Black version, probably causing you to reformat your code every release.
Now that this feature has been stabilized, always_one_newline_after_import no longer exists. Its functionality was moved into stable and it's not possible to disable it, similarly to how you can only enable or disable the preview style as a whole and not specific styles.

@webartifex
Copy link

webartifex commented Jan 20, 2026

I am a big fan of black from the first days onward.

Unfortunately, we'll have to drop black now in favor of just ruff (we had both in CI) because of this new rule.

Personally, I would support a style where there is always 2 empty lines after the import section. But that is just taste.

The main problem now with v26.1 is that it applies 1 empty line if the code following the import section is not a class or function def, in which case we get 2 empty lines.

Both ruff and isort offer the option to choose the number of lines and then apply this consistently, which IMO is the more thorough decision.

Anyways, we'll add black back into our project once this is:

  • 1 line always (but that would contradict PEP8, so not a real option long-term),
  • 2 lines always (that would be in the spirit of black to take style decisions away from teams), or
  • give an option to configure this as done by ruff and isort

I feel a bit bad that I did not run black with the --preview flag all year in 2025; otherwise, I would have brought it up.

I also hope this does not lead to some sort of "religious" war :)

Thanks to the black dev team anyways!

@steve-mavens
Copy link

steve-mavens commented Jan 20, 2026

"Both ruff and isort offer the option to choose the number of lines and then apply this consistently" - there's a conflict there. black consistently surrounds functions and classes (including any comments and decorators attached to them) with 2 blank lines. You're talking about putting a fixed number of lines after imports, which if set to 1 would violate the rule on surrounding functions and classes. I'm not sure this is explicit, but black's model in effect is that there's padding in various places, and padding can overlap but can't be reduced. So I think of the options you list, the only one that wouldn't be a huge disturbance to black's peace of mind, is "2 always". That is, set the padding after imports to 2 instead of the new-in-2026 value of 1. cobaltt7 discusses that above.

@steve-mavens
Copy link

steve-mavens commented Jan 20, 2026

@webartifex: another thing that could happen is ruff format updates to match 2026 black style, including this change. It would then be in conflict with certain options you can set for styling imports, but then it's nothing new in ruff that some options and rules can conflict, and it's up to you to pick.

@webartifex
Copy link

webartifex commented Jan 20, 2026

@steve-mavens I am not that familiar with the internals in black, just a happy user.

I tried to make it work for our code base by adapting isort and ruff but could'nt make it.

"another thing that could happen is ruff format updates to match 2026 black style"

I would also vote for this!

parikshithb added a commit to parikshithb/ramen that referenced this pull request Jan 21, 2026
Run `make black-reformat` to comply with black 26.1.0 which enforces
one blank line after imports.

See:
- https://black.readthedocs.io/en/stable/change_log.html#id1
- psf/black#4489

Signed-off-by: Parikshith <parikshithb@gmail.com>
nirs pushed a commit to RamenDR/ramen that referenced this pull request Jan 21, 2026
Run `make black-reformat` to comply with black 26.1.0 which enforces
one blank line after imports.

See:
- https://black.readthedocs.io/en/stable/change_log.html#id1
- psf/black#4489

Signed-off-by: Parikshith <parikshithb@gmail.com>
736-c41-2c1-e464fc974 pushed a commit to Swiss-Armed-Forces/Loom that referenced this pull request Feb 2, 2026
This MR contains the following updates:

| Package | Type | Update | Change | OpenSSF |
|---|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | dev | major | `^25.0.0` → `^26.0.0` | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/psf/black/badge)](https://securityscorecards.dev/viewer/?uri=github.com/psf/black) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v26.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2610)

[Compare Source](psf/black@25.12.0...26.1.0)

##### Highlights

Introduces the 2026 stable style ([#&#8203;4892](psf/black#4892)), stabilizing the following changes:

- `always_one_newline_after_import`: Always force one blank line after import
  statements, except when the line after the import is a comment or an import statement
  ([#&#8203;4489](psf/black#4489))
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behavior on one-liner declarations,
  such as `def foo(): return "mock" # fmt: skip`, where previously the declaration would
  have been incorrectly collapsed ([#&#8203;4800](psf/black#4800))
- `fix_module_docstring_detection`: Fix module docstrings being treated as normal
  strings if preceded by comments ([#&#8203;4764](psf/black#4764))
- `fix_type_expansion_split`: Fix type expansions split in generic functions ([#&#8203;4777](psf/black#4777))
- `multiline_string_handling`: Make expressions involving multiline strings more compact
  ([#&#8203;1879](psf/black#1879))
- `normalize_cr_newlines`: Add `\r` style newlines to the potential newlines to
  normalize file newlines both from and to ([#&#8203;4710](psf/black#4710))
- `remove_parens_around_except_types`: Remove parentheses around multiple exception
  types in `except` and `except*` without `as` ([#&#8203;4720](psf/black#4720))
- `remove_parens_from_assignment_lhs`: Remove unnecessary parentheses from the left-hand
  side of assignments while preserving magic trailing commas and intentional multiline
  formatting ([#&#8203;4865](psf/black#4865))
- `standardize_type_comments`: Format type comments which have zero or more spaces
  between `#` and `type:` or between `type:` and value to `# type: (value)` ([#&#8203;4645](psf/black#4645))

The following change was not in any previous stable release:

- Regenerated the `_width_table.py` and added tests for the Khmer language ([#&#8203;4253](psf/black#4253))

This release alo bumps `pathspec` to v1 and fixes inconsistencies with Git's
`.gitignore` logic ([#&#8203;4958](psf/black#4958)). Now, files will be ignored if a pattern matches them, even
if the parent directory is directly unignored. For example, Black would previously
format `exclude/not_this/foo.py` with this `.gitignore`:

```
exclude/
!exclude/not_this/
```

Now, `exclude/not_this/foo.py` will remain ignored. To ensure `exclude/not_this/` and
all of it's children are included in formatting (and in Git), use this `.gitignore`:

```
*/exclude/*
!*/exclude/not_this/
```

This new behavior matches Git. The leading `*/` are only necessary if you wish to ignore
matching subdirectories (like the previous behavior did), and not just matching root
directories.

##### Output

- Explicitly shutdown the multiprocessing manager when run in diff mode too ([#&#8203;4952](psf/black#4952))

##### Integrations

- Upgraded PyPI upload workflow to use Trusted Publishing ([#&#8203;4611](psf/black#4611))

</details>

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4wLjciLCJ1cGRhdGVkSW5WZXIiOiI0My4yLjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyIsInJlbm92YXRlIl19-->

See merge request swiss-armed-forces/cyber-command/cea/loom!275

Co-authored-by: Loom MR Pipeline Trigger <group_103951964_bot_9504bb8dead6d4e406ad817a607f24be@noreply.gitlab.com>
736-c41-2c1-e464fc974 added a commit to Swiss-Armed-Forces/Loom that referenced this pull request Feb 2, 2026
chore(deps): update black (major)

This MR contains the following updates:

| Package | Type | Update | Change | OpenSSF |
|---|---|---|---|---|
| [black](https://github.com/psf/black) ([changelog](https://github.com/psf/black/blob/main/CHANGES.md)) | dev | major | `^25.0.0` → `^26.0.0` | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/psf/black/badge)](https://securityscorecards.dev/viewer/?uri=github.com/psf/black) |

---

### Release Notes

<details>
<summary>psf/black (black)</summary>

### [`v26.1.0`](https://github.com/psf/black/blob/HEAD/CHANGES.md#2610)

[Compare Source](psf/black@25.12.0...26.1.0)

##### Highlights

Introduces the 2026 stable style ([#&#8203;4892](psf/black#4892)), stabilizing the following changes:

- `always_one_newline_after_import`: Always force one blank line after import
  statements, except when the line after the import is a comment or an import statement
  ([#&#8203;4489](psf/black#4489))
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behavior on one-liner declarations,
  such as `def foo(): return "mock" # fmt: skip`, where previously the declaration would
  have been incorrectly collapsed ([#&#8203;4800](psf/black#4800))
- `fix_module_docstring_detection`: Fix module docstrings being treated as normal
  strings if preceded by comments ([#&#8203;4764](psf/black#4764))
- `fix_type_expansion_split`: Fix type expansions split in generic functions ([#&#8203;4777](psf/black#4777))
- `multiline_string_handling`: Make expressions involving multiline strings more compact
  ([#&#8203;1879](psf/black#1879))
- `normalize_cr_newlines`: Add `\r` style newlines to the potential newlines to
  normalize file newlines both from and to ([#&#8203;4710](psf/black#4710))
- `remove_parens_around_except_types`: Remove parentheses around multiple exception
  types in `except` and `except*` without `as` ([#&#8203;4720](psf/black#4720))
- `remove_parens_from_assignment_lhs`: Remove unnecessary parentheses from the left-hand
  side of assignments while preserving magic trailing commas and intentional multiline
  formatting ([#&#8203;4865](psf/black#4865))
- `standardize_type_comments`: Format type comments which have zero or more spaces
  between `#` and `type:` or between `type:` and value to `# type: (value)` ([#&#8203;4645](psf/black#4645))

The following change was not in any previous stable release:

- Regenerated the `_width_table.py` and added tests for the Khmer language ([#&#8203;4253](psf/black#4253))

This release alo bumps `pathspec` to v1 and fixes inconsistencies with Git's
`.gitignore` logic ([#&#8203;4958](psf/black#4958)). Now, files will be ignored if a pattern matches them, even
if the parent directory is directly unignored. For example, Black would previously
format `exclude/not_this/foo.py` with this `.gitignore`:

```
exclude/
!exclude/not_this/
```

Now, `exclude/not_this/foo.py` will remain ignored. To ensure `exclude/not_this/` and
all of it's children are included in formatting (and in Git), use this `.gitignore`:

```
*/exclude/*
!*/exclude/not_this/
```

This new behavior matches Git. The leading `*/` are only necessary if you wish to ignore
matching subdirectories (like the previous behavior did), and not just matching root
directories.

##### Output

- Explicitly shutdown the multiprocessing manager when run in diff mode too ([#&#8203;4952](psf/black#4952))

##### Integrations

- Upgraded PyPI upload workflow to use Trusted Publishing ([#&#8203;4611](psf/black#4611))

</details>

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4wLjciLCJ1cGRhdGVkSW5WZXIiOiI0My4yLjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyIsInJlbm92YXRlIl19-->

See merge request swiss-armed-forces/cyber-command/cea/loom!275

Co-authored-by: Loom MR Pipeline Trigger <group_103951964_bot_9504bb8dead6d4e406ad817a607f24be@noreply.gitlab.com>
Co-authored-by: open-source Pipeline <group_90701827_bot_ed04ae348bc5f40af9966fb8b6867e99@noreply.gitlab.com>
@AdmiralNemo
Copy link

we strongly recommend trying out the --preview style sometime around November or December

...

I feel a bit bad that I did not run black with the --preview flag all year in 2025; otherwise, I would have brought it up.

To me and my team, the point of black is that we can stop worrying about formatting. Everyone just runs black before committing, and it takes away an entire class of discussion points in code reviews. We were completely taken by surprise when CI checks started failing because of code that didn't even change. It seems a bit disingenuous to request that we now have to spend time every year, during one of the busiest times for software engineering professionals, to pay attention to something we specifically adopted so we could stop paying attention to it. I do not feel bad, I feel betrayed.

@steve-mavens
Copy link

steve-mavens commented Feb 3, 2026

@AdmiralNemo : Unfortunately, the point of black = * is not to stop worrying about formatting, it's to let black rewrite your code once a year. You are opting in to a process that tinkers around with what it considers to be optimal Python style. This is not the first time it has happened, so you must have just got lucky last year that none of the changes modified your code. As a practical workaround, if you pin a specific version of black then that should be good for about 4-5 years (longer if you continue using obsolete Python versions). Then you can move the dependency at your leisure.

@cobaltt7
Copy link
Collaborator

cobaltt7 commented Feb 3, 2026

Black's stability policy has always meant that we will introduce new styles in January. As with any open-source project, Black's style will continue to evolve and change. If you wish to avoid sudden changes in your CI runs, then pin Black and review updates periodically using a tool such as Dependabot or Renovate.
Your issue sounds like it has a wider scope than just always_one_newline_after_import, and is a misunderstanding of the promises Black makes. Someday, Black is probably going to make a formatting change that requires you to reformat your code, whether it is this one or a different one. We have the stability policy to minimize the frequency of these changes, not to eliminate them altogether. If you're unable to apply the new changes right away, then don't update Black right away.

@Wulfson
Copy link

Wulfson commented Feb 10, 2026

It's annoying, but I accept that it should remain stable for this year. The question is, can we get it fixed for next year? The perceived inconsistency of "sometimes it's 1, sometimes it's 2" is really bad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants