GeezerVison is showing github.com — Prepare release 26.10.0 by JelleZijlstra · Pull Request #5478 · psf/black
Conversation
JelleZijlstra
commented
Oct 3, 2026
•
edited by github-actions
Bot
Loading
Uh oh!
There was an error while loading. Please reload this page.
Please follow the process in the docs to cut a release.
Changelog Diff
diff --git a/CHANGES.md b/CHANGES.md
index b710349a..1ae1b599 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,196 @@
# Change Log
+## Version 26.10.0
+
+### Stable style
+
+- `--line-ranges` no longer inserts an empty line after a docstring when the range
+ covers only the docstring itself (#5312)
+- Fix `# fmt: skip` on a bracketed ternary turning the surrounding tuple into a call
+ (#5464)
+- Fix crash when `# fmt: skip` is placed on a one-line function or class with PEP 695
+ type parameters (#5429)
+- Fix an inline comment after the closing bracket of optional parentheses being moved
+ inside the parentheses when the parenthesized expression contains own-line comments
+ (#5395)
+- Fix unparseable output when `# fmt: skip` is placed on a bracket of an `if`, `while`,
+ `for`, or `with` header (#5401, #5405)
+- Fix crash when formatting parenthesized expressions with multiple inline comments and
+ `# fmt: skip` (#5414)
+- Fix parsing Jupyter notebook assignment magics when non-ASCII characters appear
+ earlier on the line (#5381)
+- Preserve blank lines that come immediately before a `# fmt: on` comment (#5300)
+- Keep the parentheses around the target of an annotated assignment (e.g.
+ `(x): int = 5`), which prevent CPython from including the name in `__annotations__`
+ (#5321)
+- Stop treating a t-string in docstring position as a docstring (e.g. `t" spam "` as
+ the first statement of a module, class or function) (#5287)
+- Fix unparseable output for a t-string whose replacement field contains a quote (e.g.
+ `t'\'{a["b"]}\''`) (#5265)
+- Fix unparseable output for a triple-quoted string whose body ends in an
+ already-escaped double quote (e.g. `'''\'''\"'''`) (#5262)
+- Fix `--skip-magic-trailing-comma` dropping the trailing comma from a split
+ single-element tuple used as a lambda parameter default (#5246)
+- Fix unstable formatting when an inline comment sits on optional parentheses (e.g. a
+ parenthesized assert message) (#5241)
+- Fix `--skip-magic-trailing-comma` dropping the trailing comma of a one-element
+ subscript (`a[x,]`) when the line is long enough to be split and contains a power
+ operator (#5272)
+- Fix crash when a standalone comment sits between tokens of a comprehension or lambda
+ (#5144)
+- Fix inline comments on a bracket inside a comprehension being dropped (#5330)
+- Respect the magic trailing comma in a PEP 695 type parameter list containing a
+ `*TypeVarTuple` or `**ParamSpec` (#5244)
+- Fix crash when a comment-only `# fmt: off`/`# fmt: on` block is followed by a `with`
+ statement after another standalone comment (#5189)
+- Fix a crash when splitting `case case if ...` match patterns at very small line
+ lengths (#5147)
+- Fix multiline docstring indentation when leading tabs are used inside indented
+ docstrings (#5148)
+- Respect `# fmt: skip` on a line that opens a bracket (e.g.
+ `from x import ( # fmt: skip`) when a standalone comment is among the bracket's
+ contents (#5161)
+- Fix an AST safety error when separate `# type: ignore` comments in a parenthesized
+ attribute chain were merged onto one physical line (#5297)
+- Preserve comments and blank lines outside requested ranges when formatting with
+ `--line-ranges` (#5175)
+- Fix crash when `# fmt: skip` is used on one-line `async def`, `async with`, and
+ `async for` statements containing a semicolon (#5311)
+- Stop converting form feeds or other similar characters in docstrings into newlines
+ (#5461)
+- Fix `--skip-source-first-line` turning the skipped line's CRLF ending into `\r\r\n`
+ when reformatting a file with CRLF line endings (#5438)
+
+### Preview style
+
+#### New preview features
+
+- Add missing blank lines after classes whose last method has an ellipsis body (#5439)
+- Split only the brackets holding a magic trailing comma when more trailers follow them
+ (e.g. stop splitting inside the `[2]` of `[1,][2](3)`) (#5448)
+- Keep dictionary keys containing operators together on one line when the value can be
+ wrapped onto a new line instead (#5435)
+- Remove redundant parentheses around individual variables in unpacking targets (e.g.
+ `for (x), (y) in points:` becomes `for x, y in points:`) (#5416)
+- Normalize uppercase `T` prefixes on t-strings to lowercase (#5425)
+- Remove redundant parentheses around generator expressions (#5304, #5369)
+- Preserve two blank lines before a top-level class starting inside a `# fmt: off` block
+ after an import (#5238)
+- Fix unnecessary parentheses around short right-hand expressions in indexed assignments
+ (e.g. `x[key] = expr`) (#5095)
+- Parenthesize tuple expressions in `yield` statements for consistency with function
+ calls and returns (#5170)
+- Stop splitting between a variable and its operator (`not in`, `==`, `is`, ...) when
+ the right-hand side is a bracketed expression, and instead split inside the brackets
+ (#5135)
+- In `.pyi` stub files, enforce a blank line after a function or method that has a
+ docstring-only body when another comment or statement follows it (#5158)
+
+#### Updates to existing preview features
+
+- Fix crash in stub files when `# fmt: skip` is placed on a function in a group of
+ same-name decorated functions (e.g. `@overload`s or a property setter) (#5430)
+- Keep the parentheses around a lambda used as the iterable of a comprehension (e.g.
+ `[x for x in (lambda: 0) if x]`) (#5176, #5200)
+
+#### Updates to existing unstable features
+
+- Do not treat multi-line expressions with merged strings and trailing `# type: ignore`
+ comments as single-line unsplittable expressions (#5466)
+- Fix duplicated inline comment when stripping the parentheses around a string or
+ merging a backslash-continued string on the same line (#5449)
+- Split long stringified return annotations even when the function has parameters
+ (#5427)
+- Don't hug brackets when doing so would join two `# type: ignore` comments onto one
+ line (#5271)
+- Fix a crash when `# type: ignore` is lost during formatting of a long parenthesized
+ string (#5329)
+- Fix only the first part of an implicitly concatenated unmergeable string (e.g.
+ `r"..." r"..."`) being wrapped in parentheses (#5434)
+
+### Configuration
+
+- Add support for `NO_COLOR` environment variable to disable ANSI output (#5129)
+- Remove spurious target version warning when runtime version is included in a
+ `--target-version` flag (#5167)
+- Fix `--force-exclude` not excluding files whose path contains `..` (e.g.
+ `black ../generated/file.py` run from a subdirectory) (#5471)
+- Fall back to the default configuration, with a warning, when the given sources share
+ no common project root (e.g. they are on different drives on Windows) instead of
+ crashing (#5386)
+- Fix loading a stale cached `pyproject.toml` path when `--code` is used from different
+ working directories in the same process (#5152)
+- Add validation for `--line-ranges` values (#5107)
+- Ignore empty cache files instead of raising an `EOFError` (#5192)
+- Reject non-string `include` and `force-exclude` values in `pyproject.toml` (#5193)
+- Validate `BLACK_NUM_WORKERS` values and report invalid values as usage errors instead
+ of crashing (#5211)
+- Ignore permission errors when reading cache (#5258)
+
+### Packaging
+
+- Reduce the size of Linux standalone binaries by stripping debug symbols during the
+ PyInstaller release build (#5223)
+- Black is now released using GitHub
+ [Immutable Releases](https://docs.github.com/code-security/concepts/supply-chain-security/immutable-releases)
+ (#5296)
+
+### Performance
+
+- Fix superlinear runtime growth with the number of input files (#5450)
+- Improve performance on strings containing many consecutive backslashes (#5163)
+- Improve performance on files with many `# fmt: skip`/`# fmt: off`/`# fmt: on` comments
+ (#5169, #5190, #5232)
+- Improve performance on long calls and collections (#5177)
+- Improve performance on multiline strings inside large collections (e.g. a dict literal
+ with triple-quoted strings as values) (#5188)
+- Improve performance on files with many soft keywords (e.g. `match`/`case` blocks)
+ (#5186)
+- Improve performance on long semicolon-separated statements (in the stable style) and
+ large dict literals (in `--preview`) (#5184)
+- Improve performance of `--line-ranges` on files with many sibling blocks (a long
+ `if`/`elif` chain, a `match` with many cases, or many top-level definitions) (#5213)
+- Improve performance on deeply nested bracketed expressions (#5171, #5242)
+- Improve performance on lists and subscripts holding one long expression without
+ operators (e.g. a long run of implicitly concatenated strings inside `[]`) (#5239)
+- Improve performance on deeply chained operations (e.g. a long `a ** b ** c ** ...`
+ chain) (#5235)
+- Improve performance on long `if`/`elif` chains and other compound statements with many
+ clauses (#5322)
+- Improve performance of `string_processing`:
+ - when merging implicitly concatenated f-strings containing long string literals
+ (#5165)
+ - when merging long implicitly concatenated strings (#5173, #5194)
+ - when rewriting large nodes (e.g. `"%s ..." % (a, b, c, ...)`) (#5178, #5199, #5220)
+ - when splitting long string literals (#5183)
+
+### Output
+
+- Report parser failures using editor-friendly `path:line:column` locations (#5237)
+- Fix crash when writing formatted code or diffs to a `sys.stdout` that has no `buffer`
+ attribute (e.g. in Jupyter notebooks) (#5411)
+- Report parse failures on Black's own output as internal errors (#5383)
+
+### _Blackd_
+
+- Return HTTP 400 instead of 500 when the `X-Python-Variant` header is empty or has an
+ empty entry (e.g. a trailing comma) (#5428)
+- Allow optional whitespace around comma-separated versions and `pyi` in the
+ `X-Python-Variant` header (#5441)
+
+### Integrations
+
+- Remove unused `migrate-black` script (#5319)
+- Support PEP 440 version specifiers in `tool.black.required-version` for the GitHub
+ Action (#5399)
+- Add outputs (`is_formatted`, `change_count`, `same_count`, `failure_count`) to GitHub
+ Action runs (#5408)
+
+### Documentation
+
+- Document `vim-python-pep8-indent`, which provides an `indentexpr` for Black-style
+ insert-mode indentation (#5288)
+
## Version 26.5.1
### Stable style
@@ -186,7 +377,7 @@ The following change was not in any previous stable release:
- Regenerated the `_width_table.py` and added tests for the Khmer language (#4253)
-This release alo bumps `pathspec` to v1 and fixes inconsistencies with Git's
+This release also bumps `pathspec` to v1 and fixes inconsistencies with Git's
`.gitignore` logic (#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`:
@@ -197,7 +388,7 @@ exclude/
```
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`:
+all of its children are included in formatting (and in Git), use this `.gitignore`:
```
*/exclude/*
@@ -428,8 +619,8 @@ The following changes were not in any previous release:
### Preview style
-- Fix type annotation spacing between * and more complex type variable tuple (i.e. `def
- fn(*args: *tuple[*Ts, T]) -> None: pass`) (#4440)
+- Fix type annotation spacing between * and more complex type variable tuple (i.e.
+ `def fn(*args: *tuple[*Ts, T]) -> None: pass`) (#4440)
### Caching
This PR is automated
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
cobaltt7
commented
Oct 4, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
In addition to copyediting the changelog, I also included some small follow-ups to #5296, found when using the new system in practice:
- support
(#1234, #1235) in the changelog check script
- add a note to automated PRs, since they're not easily identifiable now that they use a PAT
- add a comment not to manually edit the prepare release PR description
- prevent
release.py from removing nested headings in changelog sections
- show help when running
release.py without arguments
The changelog had gotten rather unwieldly, which was my fault - I'll be paying more attention to the placement and wording of changelog entries in future reviews.
Additionally, since this changelog is still quite long, I added subheadings inside the "Preview style" section to distinguish between new and updated preview features, which is probably the most impactful section of the changelog. I don't think it's necessary to include it every time because many changelogs will be shorter. I also don't think any other section would benefit from subheadings; the only other long section is "Stable style", and it's all just small bugfixes.
Will merge in ~11 hours
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
n-badtke-cg
commented
Oct 5, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
Just curious: is there a specific reason why jumping from 26.5 -> 26.10? :D
Nevermind, answered by myself, version is based on CalVer, sorry ^^ we are in October 2026 -> 26.10
My mind just defaulted to SemVer
|
cobaltt7 reacted with laugh emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Labels
C: maintenance
Related to project maintenance, e.g. CI, testing, policy changes, releases
ci: skip news
Pull requests that don't need a changelog entry.
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|