Released on 2026-07-23.
Check out the blog post for a migration guide and overview of the changes!
Breaking changes
Ruff now enables a much larger set of rules by default (413, up from 59). See the blog post for more details and the new Default Rules page for a full listing of the enabled rules.
Ruff can now format Python code blocks in Markdown files and will do this by default. See the documentation for more details.
Ruff now supports ruff: ignore comments at the ends of lines, like noqa comments, or on the line preceding a diagnostic. For example, these both suppress an unused-import (F401) diagnostic:
import math # ruff: ignore[F401]
# ruff: ignore[F401]
import os
Fixes are now shown in check and format --check output:
❯ ruff format --check .
unformatted: File would be reformatted
--> try.md:1:1
|
1 | ```python
- import math
2 + import math
3 | ```
|
1 file would be reformatted
This example also shows off the Markdown formatting.
format --check now supports the same output formats as the linter, including the github and gitlab outputs for rendering annotations in CI:
❯ ruff format --check --output-format github .
::error title=ruff (unformatted),file=try.md,line=2,col=8,endLine=2,endColumn=10::try.md:2:8: unformatted: File would be reformatted
See the CLI help or documentation for the full list of supported formats.
The filename, location, end_location, fix.edits[].location, and fix.edits[].end_location fields in the JSON output format may now be null rather than defaulting to the empty string and row 1, column 1, respectively.
Stabilization
The following rules have been stabilized and are no longer in preview:
airflow3-incompatible-function-signature (AIR303)
missing-copyright-notice (CPY001)
unnecessary-from-float (FURB164)
sorted-min-max (FURB192)
implicit-string-concatenation-in-collection-literal (ISC004)
log-exception-outside-except-handler (LOG004)
invalid-bool-return-type (PLE0304)
too-many-positional-arguments (PLR0917)
stop-iteration-return (PLR1708)
none-not-at-end-of-union (RUF036)
access-annotations-from-class-dict (RUF063)
duplicate-entry-in-dunder-all (RUF068)
The following behaviors have been stabilized:
blind-except (BLE001) is now suppressed when the exception is logged via logging methods other than critical, error and exception.
future-required-type-annotation (FA102) now checks for additional PEP 585-compatible APIs, such as those from collections.abc.
f-string-in-get-text-func-call (INT001), format-in-get-text-func-call (INT002), and printf-in-get-text-func-call (INT003) now check for additional common ways of using the gettext module, such as assigning it to builtins._.
suspicious-url-open-usage (S310) now resolves local string literal bindings to avoid more false positives.
snmp-insecure-version (S508) and snmp-weak-cryptography (S509) now support the recommended API from newer versions of PySNMP.
typing-text-str-alias (UP019) now recognizes typing_extensions.Text in addition to typing.Text.
Preview features
- [pyupgrade] Fix false positive with
TypeVar default before Python 3.13 (UP040) (#26888)
Bug fixes
- [ruff] Fix missing check on unrecognized early bound (RUF016) (#26986)
Rule changes
- Insert a space after the colon in Ruff suppression comments (#27123)
Performance
- [pyupgrade] Speed up
unnecessary-future-import (UP010) (#27047)
Documentation
- [ruff] Add missing period in "Why is this bad?" section (RUF200) (#26930)
- [flake8-simplify] Clarify
os.environ behavior on Windows (SIM112) (#26972)
- [pydocstyle] Document fix safety (D400) (#26971)