Black

Developer Tools

The uncompromising Python code formatter.

Latest 26.5.1 · by Python Software FoundationWebsitepsf/black

Release activity

Release activity — 9 releases across 8 days in the last year. Each cell is one day; darker means more releases that day. Older weeks are hidden at this screen width.
MayJunJulAug
SundayNo releases on Apr 26, 2026No releases on May 3, 2026No releases on May 10, 2026No releases on May 17, 2026No releases on May 24, 2026No releases on May 31, 2026No releases on Jun 7, 2026No releases on Jun 14, 2026No releases on Jun 21, 2026No releases on Jun 28, 2026No releases on Jul 5, 2026No releases on Jul 12, 2026No releases on Jul 19, 2026No releases on Jul 26, 2026No releases on Aug 2, 2026No releases on Aug 9, 2026
MondayNo releases on Apr 27, 2026No releases on May 4, 2026No releases on May 11, 20261 release on May 18, 2026No releases on May 25, 2026No releases on Jun 1, 2026No releases on Jun 8, 2026No releases on Jun 15, 2026No releases on Jun 22, 2026No releases on Jun 29, 2026No releases on Jul 6, 2026No releases on Jul 13, 2026No releases on Jul 20, 2026No releases on Jul 27, 2026No releases on Aug 3, 2026No releases on Aug 10, 2026
TuesdayNo releases on Apr 28, 2026No releases on May 5, 2026No releases on May 12, 2026No releases on May 19, 2026No releases on May 26, 2026No releases on Jun 2, 2026No releases on Jun 9, 2026No releases on Jun 16, 2026No releases on Jun 23, 2026No releases on Jun 30, 2026No releases on Jul 7, 2026No releases on Jul 14, 2026No releases on Jul 21, 2026No releases on Jul 28, 2026No releases on Aug 4, 2026
WednesdayNo releases on Apr 29, 2026No releases on May 6, 2026No releases on May 13, 2026No releases on May 20, 2026No releases on May 27, 2026No releases on Jun 3, 2026No releases on Jun 10, 2026No releases on Jun 17, 2026No releases on Jun 24, 2026No releases on Jul 1, 2026No releases on Jul 8, 2026No releases on Jul 15, 2026No releases on Jul 22, 2026No releases on Jul 29, 2026No releases on Aug 5, 2026
ThursdayNo releases on Apr 30, 2026No releases on May 7, 2026No releases on May 14, 2026No releases on May 21, 2026No releases on May 28, 2026No releases on Jun 4, 2026No releases on Jun 11, 2026No releases on Jun 18, 2026No releases on Jun 25, 2026No releases on Jul 2, 2026No releases on Jul 9, 2026No releases on Jul 16, 2026No releases on Jul 23, 2026No releases on Jul 30, 2026No releases on Aug 6, 2026
FridayNo releases on May 1, 2026No releases on May 8, 2026No releases on May 15, 2026No releases on May 22, 2026No releases on May 29, 2026No releases on Jun 5, 2026No releases on Jun 12, 2026No releases on Jun 19, 2026No releases on Jun 26, 2026No releases on Jul 3, 2026No releases on Jul 10, 2026No releases on Jul 17, 2026No releases on Jul 24, 2026No releases on Jul 31, 2026No releases on Aug 7, 2026
SaturdayNo releases on May 2, 2026No releases on May 9, 20261 release on May 16, 2026No releases on May 23, 2026No releases on May 30, 2026No releases on Jun 6, 2026No releases on Jun 13, 2026No releases on Jun 20, 2026No releases on Jun 27, 2026No releases on Jul 4, 2026No releases on Jul 11, 2026No releases on Jul 18, 2026No releases on Jul 25, 2026No releases on Aug 1, 2026No releases on Aug 8, 2026

9 releases in the last year, busiest day 2

Changelog

26.5.1

Added 1
  • Add Neovim integration guide covering conform.nvim, ALE, and simple command approaches
Fixed 3
  • Fix unstable formatting of annotated assignments whose subscript annotation contains an inline comment
  • Preserve inline comments (including # type: ignore) immediately before a # fmt: skip line, avoiding AST equivalence failures
  • Correct the version in the published executables
Stable style
  • Fix unstable formatting of annotated assignments whose subscript annotation contains an inline comment (e.g. x: list[ # pyright: ignore[...]) (#5130)
  • Preserve inline comments (including # type: ignore) immediately before a # fmt: skip line, avoiding AST equivalence failures (#5139)
Packaging
  • Correct the version in the published executables (#5137)
Documentation
  • Add Neovim integration guide covering conform.nvim, ALE, and simple command approaches (#5124)
View originalPermalink
How 26.5.1 went

26.5.0

Added 3
  • Support for unpacking in comprehensions (PEP 798) and lazy imports (PEP 810), new syntactic features in Python 3.15
  • Python 3.15 support
  • Add `SourceASTParseError` to distinguish source parse failures from internal safety errors
Changed 3
  • Improve heuristics around blank lines before, within and after groups of same-name decorated functions (such as `@overload` groups) in `.pyi` stub files
  • Improve parse error readability by showing multi-line output with an error pointer
  • Return HTTP 400 (Bad Request) for source parse failures instead of HTTP 500 in Blackd, keeping HTTP 500 only for genuine internal safety errors
Fixed 5
  • Fix `# fmt: skip` being ignored in nested `if` expressions with parenthesized `in` clauses
  • Fix crash when an f-string follows a `# fmt: off` comment inside brackets
  • Preserve multiline compound statement headers when `# fmt: skip` is placed on the colon line
  • Fix blank lines being removed between a function and a decorated class in `.pyi` stub files
  • Prevent string merger from creating unsplittable long lines when a pragma comment (e.g. `# type: ignore`) follows the closing bracket
Highlights
  • Add support for unpacking in comprehensions (PEP 798) and for lazy imports (PEP 810), both new syntactic features in Python 3.15 (#5048)
  • Python 3.15 is now supported. Compiled wheels are not yet provided for Python 3.15, so performance may be slower than on existing Python versions. Wheels will be provided once Python 3.15 is later in its release cycle. (#5127)
Stable style
  • Fix # fmt: skip being ignored in nested if expressions with parenthesized in clauses (#4903)
  • Add syntactic support for Python 3.15 (#5048)
  • Fix crash when an f-string follows a # fmt: off comment inside brackets (#5097)
  • Preserve multiline compound statement headers when # fmt: skip is placed on the colon line (#5117)
Preview style
  • Improve heuristics around whether blank lines should appear before, within and after groups of same-name decorated functions (such as @overload groups) in .pyi stub files (#5021)
  • Fix blank lines being removed between a function and a decorated class in .pyi stub files (#5092)
  • Prevent string merger from creating unsplittable long lines when a pragma comment (e.g. # type: ignore) follows the closing bracket (#5096)
Packaging
  • Run CI on 3.15 (#5127)
Output
  • Improve parse error readability by showing multi-line output with an error pointer. (#5068)
  • Add SourceASTParseError to distinguish source parse failures from internal safety errors, improving error reporting when Black's lenient parser accepts input that ast.parse() rejects (#5080)
Blackd
  • Return HTTP 400 (Bad Request) for source parse failures instead of HTTP 500, keeping HTTP 500 only for genuine internal safety errors (#5080)
Integrations
  • Added documentation for doctest formatting tools and updated the integrations index to match (#4916)
Documentation
  • Use "Version X.Y.Z" headings in changelog for stable permalink anchors on ReadTheDocs (#5063)
  • Note in the editor integrations that the SublimeText sublack plugin is archived and unmaintained (#5082)
View originalPermalink
How 26.5.0 went

26.3.1

Changed 2
  • Always hash cache filename components derived from --python-cell-magics so custom magic names cannot affect cache paths
  • Disable browser-originated requests by default in Blackd, add configurable origin allowlisting and request body limits, and bound executor submissions to improve backpressure
Fixed 1
  • Prevent Jupyter notebook magic masking collisions from corrupting cells by using exact-length placeholders for short magics and aborting if a placeholder can no longer be unmasked safely
Stable style
  • Prevent Jupyter notebook magic masking collisions from corrupting cells by using exact-length placeholders for short magics and aborting if a placeholder can no longer be unmasked safely (#5038)
Configuration
  • Always hash cache filename components derived from --python-cell-magics so custom magic names cannot affect cache paths (#5038)
Blackd
  • Disable browser-originated requests by default, add configurable origin allowlisting and request body limits, and bound executor submissions to improve backpressure (#5039)
View originalPermalink
How 26.3.1 went

26.3.0

Added 2
  • Introduce winloop for Windows as an alternative to uvloop
  • Introduce winloop to be used when Windows is in use which enables blackd to run faster on Windows when winloop is installed
Changed 3
  • Simplify implementation of the power operator "hugging" logic
  • Rename maybe_install_uvloop function to maybe_use_uvloop to simplify loop installation and creation of either a uvloop/winloop evenloop or default eventloop
  • Emit a clear warning when the target Python version is newer than the running Python version, since AST safety checks cannot parse newer syntax, and replace the misleading "INTERNAL ERROR" message with an actionable error explaining the version mismatch
Fixed 6
  • Don't double-decode input, causing non-UTF-8 files to be corrupted
  • Fix crash on standalone comment in lambda default arguments
  • Preserve parentheses when # type: ignore comments would be merged with other comments on the same line, preventing AST equivalence failures
  • Fix bug where if guards in case blocks were incorrectly split when the pattern had a trailing comma
  • Fix string_processing crashing on unassigned long string literals with trailing commas
  • Fix shutdown errors in PyInstaller builds on macOS by disabling multiprocessing in frozen environments
Removed 2
  • Remove deprecated function uvloop.install() in favor of uvloop.new_event_loop()
  • Remove unused gallery script
Security 1
  • Harden parsing of black requirements in the GitHub Action when use_pyproject is enabled so that only version specifiers are accepted and direct references such as black @ https://... are rejected
Stable style
  • Don't double-decode input, causing non-UTF-8 files to be corrupted (#4964)
  • Fix crash on standalone comment in lambda default arguments (#4993)
  • Preserve parentheses when # type: ignore comments would be merged with other comments on the same line, preventing AST equivalence failures (#4888)
Preview style
  • Fix bug where if guards in case blocks were incorrectly split when the pattern had a trailing comma (#4884)
  • Fix string_processing crashing on unassigned long string literals with trailing commas (one-item tuples) (#4929)
  • Simplify implementation of the power operator "hugging" logic (#4918)
Packaging
  • Fix shutdown errors in PyInstaller builds on macOS by disabling multiprocessing in frozen environments (#4930)
Performance
  • Introduce winloop for windows as an alternative to uvloop (#4996)
  • Remove deprecated function uvloop.install() in favor of uvloop.new_event_loop() (#4996)
  • Rename maybe_install_uvloop function to maybe_use_uvloop to simplify loop installation and creation of either a uvloop/winloop evenloop or default eventloop (#4996)
Output
  • Emit a clear warning when the target Python version is newer than the running Python version, since AST safety checks cannot parse newer syntax. Also replace the misleading "INTERNAL ERROR" message with an actionable error explaining the version mismatch (#4983)
Blackd
  • Introduce winloop to be used when windows in use which enables blackd to run faster on windows when winloop is installed. (#4996)
Integrations
  • Remove unused gallery script (#5030)
  • Harden parsing of black requirements in the GitHub Action when use_pyproject is enabled so that only version specifiers are accepted and direct references such as black @ https://... are rejected. Users should upgrade to the latest version of the action as soon as possible. This update is received automatically when using psf/black@stable, and is independent of the version of Black installed by the action. (#5031)
Documentation
  • Expand preview style documentation with detailed examples for wrap_comprehension_in, simplify_power_operator_hugging, and wrap_long_dict_values_in_parens features (#4987)
  • Add detailed documentation for formatting Jupyter Notebooks (#5009)
View originalPermalink
How 26.3.0 went

26.1.0

Added 6
  • Introduce the 2026 stable style with always_one_newline_after_import to force one blank line after import statements except when followed by a comment or import
  • Add multiline_string_handling to make expressions involving multiline strings more compact
  • Add normalize_cr_newlines to normalize file newlines with \r style newlines
  • Add remove_parens_around_except_types to remove parentheses around multiple exception types in except and except* without as
  • Add remove_parens_from_assignment_lhs to remove unnecessary parentheses from the left-hand side of assignments while preserving magic trailing commas
  • Add standardize_type_comments to format type comments to # type: (value) style
Changed 2
  • Regenerate the _width_table.py with added tests for the Khmer language
  • Bump pathspec to v1 and fix inconsistencies with Git's .gitignore logic to match Git behavior for ignored patterns
Fixed 4
  • Fix fmt: skip behavior on one-liner declarations to prevent incorrect collapsing
  • Fix module docstrings being treated as normal strings if preceded by comments
  • Fix type expansions split in generic functions
  • Explicitly shutdown the multiprocessing manager when run in diff mode
Highlights

Introduces the 2026 stable style (#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 (#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 (#4800)
  • fix_module_docstring_detection: Fix module docstrings being treated as normal strings if preceded by comments (#4764)
  • fix_type_expansion_split: Fix type expansions split in generic functions (#4777)
  • multiline_string_handling: Make expressions involving multiline strings more compact (#1879)
  • normalize_cr_newlines: Add \r style newlines to the potential newlines to normalize file newlines both from and to (#4710)
  • remove_parens_around_except_types: Remove parentheses around multiple exception types in except and except* without as (#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 (#4865)
  • standardize_type_comments: Format type comments which have zero or more spaces between # and type: or between type: and value to # type: (value) (#4645)

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 .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:

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 (#4952)
Integrations
  • Upgraded PyPI upload workflow to use Trusted Publishing (#4611)
View originalPermalink
How 26.1.0 went

26.1a1

Pre-release
Added 6
  • always_one_newline_after_import option to always force one blank line after import statements, except when the line after the import is a comment or an import statement
  • multiline_string_handling option to make expressions involving multiline strings more compact
  • normalize_cr_newlines option to add \r style newlines to the potential newlines to normalize file newlines both from and to
  • remove_parens_around_except_types option to remove parentheses around multiple exception types in except and except* without as
  • remove_parens_from_assignment_lhs option to remove unnecessary parentheses from the left-hand side of assignments while preserving magic trailing commas and intentional multiline formatting
  • standardize_type_comments option to format type comments which have zero or more spaces between # and type: or between type: and value to # type: (value)
Changed 1
  • Regenerated the _width_table.py and added tests for the Khmer language
Fixed 3
  • fix_fmt_skip_in_one_liners to correct # fmt: skip behavior on one-liner declarations such as def foo(): return "mock" # fmt: skip where the declaration would have been incorrectly collapsed
  • fix_module_docstring_detection to prevent module docstrings from being treated as normal strings if preceded by comments
  • fix_type_expansion_split to correct type expansions split in generic functions

This is a preview of the Black stable style for 2026 (#4892). Please test it and share your feedback!

The following formatting changes are included:

  • 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 (#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 (#4800)
  • fix_module_docstring_detection: Fix module docstrings being treated as normal strings if preceded by comments (#4764)
  • fix_type_expansion_split: Fix type expansions split in generic functions (#4777)
  • multiline_string_handling: Make expressions involving multiline strings more compact (#1879)
  • normalize_cr_newlines: Add \r style newlines to the potential newlines to normalize file newlines both from and to (#4710)
  • remove_parens_around_except_types: Remove parentheses around multiple exception types in except and except* without as. See PEP 758 for details (#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 (#4865)
  • standardize_type_comments: Format type comments which have zero or more spaces between # and type: or between type: and value to # type: (value) (#4645)
  • Regenerated the _width_table.py and added tests for the Khmer language (#4253)
View originalPermalink
How 26.1a1 went

25.12.0

Added 2
  • Releases now include arm64 Windows binaries and wheels
  • Add output-file input to GitHub Action psf/black to write formatter output to a file for artifact capture and log cleanliness
Changed 1
  • Remove unnecessary parentheses from the left-hand side of assignments while preserving magic trailing commas and intentional multiline formatting
Fixed 7
  • Fix bug where comments preceding # fmt: off/# fmt: on blocks were incorrectly removed, particularly affecting Jupytext's # %% [markdown] comments
  • 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
  • Fix possible crash when fmt: directives aren't on the top level
  • Fix # fmt: skip skipping the line after instead of the line it's on
  • Fix fix_fmt_skip_in_one_liners crashing on with statements
  • Fix fix_fmt_skip_in_one_liners crashing on annotated parameters
  • Fix new lines being added after imports with # fmt: skip on them
Removed 1
  • Black no longer supports running with Python 3.9

Please test out the draft 2026 style in version 26.1a1! This style will be finalized in the January release (26.1.0). Most of the changes in --preview will be in the 2026 stable style, but not all. Please share your feedback!

This release (25.12.0) will still produce the 2025 style.

Highlights
  • Black no longer supports running with Python 3.9 (#4842)
Stable style
  • Fix bug where comments preceding # fmt: off/# fmt: on blocks were incorrectly removed, particularly affecting Jupytext's # %% [markdown] comments (#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 (#4872)
  • Fix possible crash when fmt: directives aren't on the top level (#4856)
Preview style
  • Fix fmt: skip skipping the line after instead of the line it's on (#4855)
  • Remove unnecessary parentheses from the left-hand side of assignments while preserving magic trailing commas and intentional multiline formatting (#4865)
  • Fix fix_fmt_skip_in_one_liners crashing on with statements (#4853)
  • Fix fix_fmt_skip_in_one_liners crashing on annotated parameters (#4854)
  • Fix new lines being added after imports with # fmt: skip on them (#4894)
Packaging
  • Releases now include arm64 Windows binaries and wheels (#4814)
Integrations
  • Add output-file input to GitHub Action psf/black to write formatter output to a file for artifact capture and log cleanliness (#4824)
View originalPermalink
How 25.12.0 went

25.11.0

Added 5
  • Enable base 3.14 support
  • Add support for the new Python 3.14 t-string syntax introduced by PEP 750
  • Add no_cache option to control caching behavior
  • Releases now include arm64 Linux binaries
  • Implement BlackDClient, a simple python client to send formatting requests to blackd
Changed 7
  • Comments containing fmt directives now preserve their exact formatting instead of being normalized
  • Move multiline_string_handling from --unstable to --preview
  • Standardize type comments to form # type: <value>
  • Write unchanged content to stdout when excluding formatting from stdin using pipes
  • Enhance GitHub Action psf/black to support the required-version major-version-only stability format when using pyproject.toml
  • Improve error message for vim plugin users and warn on unsupported Vim and Python versions independently
  • Vim: Print the import paths when importing black fails
Fixed 5
  • Fix bug where comments between # fmt: off and # fmt: on were reformatted
  • Fix bug where module docstrings would be treated as normal strings if preceded by comments
  • Fix bug where python 3.12 generics syntax split line happens weirdly
  • Fix fix_fmt_skip_in_one_liners preview feature to respect # fmt: skip for compound statements with semicolon-separated bodies
  • Vim: Fix handling of virtualenvs that have a different Python version
Highlights
  • Enable base 3.14 support (#4804)
  • Add support for the new Python 3.14 t-string syntax introduced by PEP 750 (#4805)
Stable style
  • Fix bug where comments between # fmt: off and # fmt: on were reformatted (#4811)
  • Comments containing fmt directives now preserve their exact formatting instead of being normalized (#4811)
Preview style
  • Move multiline_string_handling from --unstable to --preview (#4760)
  • Fix bug where module docstrings would be treated as normal strings if preceded by comments (#4764)
  • Fix bug where python 3.12 generics syntax split line happens weirdly (#4777)
  • Standardize type comments to form # type: <value> (#4645)
  • Fix fix_fmt_skip_in_one_liners preview feature to respect # fmt: skip for compound statements with semicolon-separated bodies (#4800)
Configuration
  • Add no_cache option to control caching behavior. (#4803)
Packaging
  • Releases now include arm64 Linux binaries (#4773)
Output
  • Write unchanged content to stdout when excluding formatting from stdin using pipes (#4610)
Blackd
  • Implemented BlackDClient. This simple python client allows to easily send formatting requests to blackd (#4774)
Integrations
  • Enable 3.14 base CI (#4804)
  • Enhance GitHub Action psf/black to support the required-version major-version-only "stability" format when using pyproject.toml (#4770)
  • Improve error message for vim plugin users. It now handles independently vim version
  • Vim: Warn on unsupported Vim and Python versions independently (#4772)
  • Vim: Print the import paths when importing black fails (#4675)
  • Vim: Fix handling of virtualenvs that have a different Python version (#4675)
View originalPermalink
How 25.11.0 went

25.9.0

Changed 6
  • Improve multiline_string_handling with ternaries and dictionaries
  • Wrap the in clause of comprehensions across lines if necessary
  • Remove parentheses around multiple exception types in except and except* without as
  • Add \r style newlines to the potential newlines to normalize file newlines both from and to
  • Rewrite tokenizer to improve performance and compliance
  • Avoid using an extra process when running with only one worker
Fixed 13
  • Fix crash while formatting a long del statement containing tuples
  • Fix crash while formatting expressions using the walrus operator in complex with statements
  • Handle # fmt: skip followed by a comment at the end of file
  • Fix crash when a tuple appears in the as clause of a with statement
  • Fix crash when tuple is used as a context manager inside a with statement
  • Fix crash when formatting a \ followed by a \r followed by a comment
Removed 1
  • Remove support for pre-python 3.7 await/async as soft keywords/variable names
Highlights
  • Remove support for pre-python 3.7 await/async as soft keywords/variable names (#4676)
Stable style
  • Fix crash while formatting a long del statement containing tuples (#4628)
  • Fix crash while formatting expressions using the walrus operator in complex with statements (#4630)
  • Handle # fmt: skip followed by a comment at the end of file (#4635)
  • Fix crash when a tuple appears in the as clause of a with statement (#4634)
  • Fix crash when tuple is used as a context manager inside a with statement (#4646)
  • Fix crash when formatting a \ followed by a \r followed by a comment (#4663)
  • Fix crash on a \\r\n (#4673)
  • Fix crash on await ... (where ... is a literal Ellipsis) (#4676)
  • Fix crash on parenthesized expression inside a type parameter bound (#4684)
  • Fix crash when using line ranges excluding indented single line decorated items (#4670)
Preview style
  • Fix a bug where one-liner functions/conditionals marked with # fmt: skip would still be formatted (#4552)
  • Improve multiline_string_handling with ternaries and dictionaries (#4657)
  • Fix a bug where string_processing would not split f-strings directly after expressions (#4680)
  • Wrap the in clause of comprehensions across lines if necessary (#4699)
  • Remove parentheses around multiple exception types in except and except* without as. (#4720)
  • Add \r style newlines to the potential newlines to normalize file newlines both from and to (#4710)
Parser
  • Rewrite tokenizer to improve performance and compliance (#4536)
  • Fix bug where certain unusual expressions (e.g., lambdas) were not accepted in type parameter bounds and defaults. (#4602)
Performance
  • Avoid using an extra process when running with only one worker (#4734)
Integrations
  • Fix the version check in the vim file to reject Python 3.8 (#4567)
  • Enhance GitHub Action psf/black to read Black version from an additional section in pyproject.toml: [project.dependency-groups] (#4606)
  • Build gallery docker image with python3-slim and reduce image size (#4686)
Documentation
  • Add FAQ entry for windows emoji not displaying (#4714)
View originalPermalink
How 25.9.0 went

25.1.0

Changed 12
  • Normalize casing of Unicode escape characters in strings to lowercase
  • Consistently add trailing commas to typed function parameters
  • Remove redundant parentheses in if guards for case blocks
  • Add parentheses to if clauses in case blocks when the line is too long
  • Whitespace before # fmt: skip comments is no longer normalized
  • Remove parentheses around sole list items
Fixed 8
  • Fix inconsistencies in whether certain strings are detected as docstrings
  • Fix line length computation for certain expressions that involve the power operator
  • Check if there is a newline before the terminating quotes of a docstring
  • Fix type annotation spacing between * and more complex type variable tuple
  • Fix formatting cells in IPython notebooks with magic methods and starting or trailing empty lines
  • Fix crash when formatting with statements containing tuple generators or unpacking
  • Fix string merging changing f-string quotes on f-strings with internal quotes
  • Prevent string_processing and wrap_long_dict_values_in_parens from removing parentheses around long dictionary values
Highlights

This release introduces the new 2025 stable style (#4558), stabilizing the following changes:

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

The following changes were not in any previous release:

  • Remove parentheses around sole list items (#4312)
  • Generic function definitions are now formatted more elegantly: parameters are split over multiple lines first instead of type parameter definitions (#4553)
Stable style
  • Fix formatting cells in IPython notebooks with magic methods and starting or trailing empty lines (#4484)
  • Fix crash when formatting with statements containing tuple generators/unpacking (#4538)
Preview style
  • Fix/remove string merging changing f-string quotes on f-strings with internal quotes (#4498)
  • Collapse multiple empty lines after an import into one (#4489)
  • Prevent string_processing and wrap_long_dict_values_in_parens from removing parentheses around long dictionary values (#4377)
  • Move wrap_long_dict_values_in_parens from the unstable to preview style (#4561)
Packaging
  • Store license identifier inside the License-Expression metadata field, see PEP 639. (#4479)
Performance
  • Speed up the is_fstring_start function in Black's tokenizer (#4541)
Integrations
  • If using stdin with --stdin-filename set to a force excluded path, stdin won't be formatted. (#4539)
View originalPermalink
How 25.1.0 went
View all

Discussion