Released on 2026-06-04.
- [
flake8-async] Implementyield-in-context-manager-in-async-generator(ASYNC119) (#24644) - [
pylint] Narrow diagnostic range and exclude cases without exception handlers (PLW0717) (#25440) - [
ruff] Treatyieldbeforebreakfrom a terminal loop as terminal (RUF075) (#25447)
- [
eradicate] Avoid flaggingruff:ignorecomments as code (ERA001) (#25537) - [
eradicate] FixERA001/RUF100conflict whennoqais on commented-out code (#25414) - [
pyflakes] Avoid removing theformatcall when it would change behavior (F523) (#25320) - [
pylint] Avoid syntax errors in invalid character replacements in f-strings before Python 3.12 (PLE2510,PLE2512,PLE2513,PLE2514,PLE2515) (#25544) - [
pyupgrade] Avoid convertingformatcalls with more kinds of side effects (UP032) (#25484)
- [
flake8-pytest-style] Avoid fixes for ambiguousargnamesandargvaluescombinations (PT006) (#24776)
- Drop excess capacity from statement suites during parsing (#25368)
- [
pydocstyle] Improve discoverability of rules enabled for each convention (#24973) - [
ruff] Restore example code for Python versions before 3.15 (RUF017) (#25439) - Fix typo
bin/active→bin/activatein tutorial (#25473)
- Shrink additional parser AST collections (#25465)
- @Redslayer112
- @koriyoshi2041
- @George-Ogden
- @TejasAmle
- @anishgirianish
- @ntBre
- @MichaReiser
- @loganrosen
- @RafaelJohn9
- @adityasingh2400
Released on 2026-05-28.
- Fix Markdown closing fence handling (#25310)
- [
pyflakes] Report duplicate imports intyping.TYPE_CHECKINGblock (F811) (#22560)
- [
pyflakes] Treat function-scope bare annotations as locals per PEP 526 (F821) (#21540)
- Avoid redundant
TokenValuedrops in the lexer (#25300) - Reduce memory usage by dropping token-excess capacity and improve performance by approximating the initial tokens
Vecsize (#25354) - Use
ThinVecin AST to shrinkStmt(#25361)
- Fix
line-lengthexample for--configoption (#25389) - [
flake8-comprehensions] DocumentRecursionErroredge case in__len__(C416) (#25286) - [
mccabe] Improve example (C901) (#25287) - [
pyupgrade] Clarify fix safety docs (UP007,UP045) (#25288) - [
refurb] DocumentFURB192exception change for empty sequences (#25317) - [
ruff] Document false negative for user-defined types (RUF013) (#25289)
- Fix formatting of lambdas nested within f-strings (#25398)
- Return code action for
codeAction/resolverequests that contain no or no valid URL (#25365)
- Expand semantic syntax errors for invalid walruses (#25415)
- @chirizxc
- @ntBre
- @adityasingh2400
- @charliermarsh
- @fallintoplace
- @martin-schlossarek
- @MichaReiser
- @Ruchir28
Released on 2026-05-21.
- [
airflow] Implementairflow-task-implicit-multiple-outputs(AIR202) (#25152) - [
flake8-use-pathlib] MarkPTH101fix as unsafe when first argument is a class attribute annotated asint(#25086) - [
pylint] Implementtoo-many-try-statements(W0717) (#23970) - [
ruff] Addincorrect-decorator-order(RUF074) (#23461) - [
ruff] Addfallible-context-manager(RUF075) (#22844)
- Fix lambda formatting in interpolated string expressions (#25144)
- Treat generic
frozensetannotations as immutable (#25251) - [
flake8-type-checking] Avoidstrictbehavior whenfuture-annotationsare enabled (TC001,TC002,TC003) (#25035) - [
pylint] Avoid false positives inelseclause (PLR1733) (#25177)
- [
flake8-comprehensions] SkipC417for lambdas with positional-only parameters (#25272) - [
flake8-simplify] Preserve f-string source verbatim inSIM101fix (#25061)
- Avoid unnecessary parser lookahead for operators (#25290)
- Update code example setting Neovim LSP log level (#25284)
- Add full PEP 798 support (#25104)
- Add a parser recursion limit (#24810)
- Update various
ruff_python_stdlibAPIs (#25273)
- @ocaballeror
- @lerebear
- @samuelcolvin
- @baltasarblanco
- @aconal-com
- @anishgirianish
- @JelleZijlstra
- @AlexWaygood
- @ntBre
- @adityasingh2400
- @charliermarsh
- @Dev-iL
- @neutrinoceros
- @shivamtiwari3
- @Dev-X25874
Released on 2026-05-14.
- Add a rule to flag lazy imports that are eagerly evaluated (#25016)
- [
pylint] Standardize diagnostic message (PLR0914,PLR0917) (#24996)
- Fix
F811false positive for class methods (#24933) - Fix setting selection for multi-folder workspace (#24819)
- [
eradicate] Fix false positive for lines with leading whitespace (ERA001) (#25122) - [
flake8-pyi] Fix false positive for f-string debug specifier (PYI016) (#24098)
- Always include panic payload in panic diagnostic message (#24873)
- Restrict
PYI034for in-place operations to enclosing class (#24511) - Improve error message for parameters that are declared
global(#24902) - Update known stdlib (#25103)
- [
isort] Avoid constructingglob::Patterns for literal known modules (#25123)
- Increase max allowed value of
line-lengthsetting (#24962)
- Add
D203to rules that conflict with the formatter (#25044) - Clarify
COM819and formatter interaction (#25045) - Clarify that
NotImplementedis a value, not an exception (F901) (#25054) - Update number of lint rules supported (#24942)
- Simplify the playground's markdown template (#24924)
- @MichaReiser
- @brian-c11
- @Andrej730
- @denyszhak
- @darestack
- @sharkdp
- @charliermarsh
- @EkriirkE
- @eyupcanakman
- @Hrk84ya
- @thernstig
- @ntBre
Released on 2026-04-24.
- Implement
#ruff:file-ignorefile-level suppressions (#23599) - Implement
#ruff:ignorelogical-line suppressions (#23404) - Revert preview changes to displayed diagnostic severity in LSP (#24789)
- [
airflow] Implementtask-branch-as-short-circuit(AIR004) (#23579) - [
flake8-bugbear] Fixbreak/continuehandling inloop-iterator-mutation(B909) (#24440) - [
pylint] FixPLC2701for type parameter scopes (#24576)
- [
pandas-vet] Suggest.arrayas well inPD011(#24805)
- Respect default Unix permissions for cache files (#24794)
- [
pylint] FixPLR0124description not to claim self-comparison always returns the same value (#24749) - [
pyupgrade] Expand docs on reusableTypeVars and scoping (UP046) (#24153) - Improve rules table accessibility (#24711)
- @dylwil3
- @AlexWaygood
- @woodruffw
- @avasis-ai
- @Dev-iL
- @denyszhak
- @ShipItAndPray
- @anishgirianish
- @augustelalande
- @amyreese
- @majiayu000
Released on 2026-04-16.
- [
ruff] IgnoreRUF029when function is decorated withasynccontextmanager(#24642) - [
airflow] Implementairflow-xcom-pull-in-template-string(AIR201) (#23583) - [
flake8-bandit] FixS103false positives and negatives in mask analysis (#24424)
- [
flake8-async] Omit overridden methods forASYNC109(#24648)
- [
flake8-async] Add override mention toASYNC109docs (#24666) - Update Neovim config examples to use
vim.lsp.config(#24577)
Released on 2026-04-09.
- [
flake8-logging] Allow closures in except handlers (LOG004) (#24464) - [
flake8-self] MakeSLFdiagnostics robust to non-self-named variables (#24281) - [
flake8-simplify] Make the fix forcollapsible-ifsafe inpreview(SIM102) (#24371)
- Avoid emitting multi-line f-string elements before Python 3.12 (#24377)
- Avoid syntax error from
E502fixes in f-strings and t-strings (#24410) - Strip form feeds from indent passed to
dedent_to(#24381) - [
pyupgrade] Fix panic caused by handling of octals (UP012) (#24390) - Reject multi-line f-string elements before Python 3.12 (#24355)
- [
ruff] Treat f-string interpolation as potential side effect (RUF019) (#24426)
- Add support for custom file extensions (#24463)
Released on 2026-04-02.
- [
pyflakes] Flag annotated variable redeclarations asF811in preview mode (#24244) - [
ruff] Allow dunder-named assignments in non-strict mode forRUF067(#24089)
- [
flake8-errmsg] Avoid shadowing existingmsgin fix forEM101(#24363) - [
flake8-simplify] Ignore pre-initialization references inSIM113(#24235) - [
pycodestyle] FixW391fixes for consecutive empty notebook cells (#24236) - [
pyupgrade] FixUP008nested class matching (#24273) - [
pyupgrade] Ignore strings with string-only escapes (UP012) (#16058) - [
ruff]RUF072: skip formfeeds on dedent (#24308) - [
ruff] Avoid re-using symbol inRUF024fix (#24316) - [
ruff] Parenthesize expression inRUF050fix (#24234) - Disallow starred expressions as values of starred expressions (#24280)
- [
flake8-simplify] SuppressSIM105forexcept*before Python 3.12 (#23869) - [
pyflakes] ExtendF507to flag%-format strings with zero placeholders (#24215) - [
pyupgrade]UP018should detect more unnecessarily wrapped literals (UP018) (#24093) - [
pyupgrade] FixUP008callable scope handling to support lambdas (#24274) - [
ruff]RUF010: Mark fix as unsafe when it deletes a comment (#24270)
- Add
nested-string-quote-styleformatting option (#24312)
- [
flake8-bugbear] Clarify RUF071 fix safety for non-path string comparisons (#24149) - [
flake8-type-checking] Clarify import cycle wording forTC001/TC002/TC003(#24322)
- Avoid rendering fix lines with trailing whitespace after
|(#24343)
- @charliermarsh
- @MichaReiser
- @tranhoangtu-it
- @dylwil3
- @zsol
- @renovate
- @bitloi
- @danparizher
- @chinar-amrutkar
- @second-ed
- @getehen
- @Redovo1
- @matthewlloyd
- @zanieb
- @InSyncWithFoo
- @RenzoMXD
Released on 2026-03-26.
- [
ruff] New ruleunnecessary-if(RUF050) (#24114) - [
ruff] New ruleuseless-finally(RUF072) (#24165) - [
ruff] New rulef-string-percent-format(RUF073): warn when using%operator on an f-string (#24162) - [
pyflakes] Recognizefrozendictas a builtin for Python 3.15+ (#24100)
- [
flake8-async] Use fully-qualifiedanyio.lowlevelimport in autofix (ASYNC115) (#24166) - [
flake8-bandit] Check tuple arguments for partial paths inS607(#24080) - [
pyflakes] Skipundefined-name(F821) for conditionally deleted variables (#24088) E501/W505/formatter: Exclude nested pragma comments from line width calculation (#24071)- Fix
%foo?parsing in IPython assignment expressions (#24152) analyze graph: resolve string imports that reference attributes, not just modules (#24058)
- [
eradicate] ignorety: ignorecomments inERA001(#24192) - [
flake8-bandit] Treatsys.executableas trusted input inS603(#24106) - [
flake8-self] RecognizeSelfannotation andselfassignment inSLF001(#24144) - [
pyflakes]F507: Fix false negative for non-tuple RHS in%-formatting (#24142) - [
refurb] Parenthesize generator arguments inFURB142fixer (#24200)
- Speed up diagnostic rendering (#24146)
- Warn when Markdown files are skipped due to preview being disabled (#24150)
- Clarify
extend-ignoreandextend-selectsettings documentation (#24064) - Mention AI policy in PR template (#24198)
- Use trusted publishing for NPM packages (#24171)
- @bitloi
- @Sim-hu
- @mvanhorn
- @chinar-amrutkar
- @markjm
- @RenzoMXD
- @vivekkhimani
- @seroperson
- @moktamd
- @charliermarsh
- @ntBre
- @zanieb
- @dylwil3
- @MichaReiser
Released on 2026-03-19.
- [
pycodestyle] Recognizepyrefly:as a pragma comment (E501) (#24019)
- Don't return code actions for non-Python documents (#23905)
- Add company AI policy to contributing guide (#24021)
- Document editor features for Markdown code formatting (#23924)
- [
pylint] Improve phrasing (PLC0208) (#24033)
- Use PEP 639 license information (#19661)
Released on 2026-03-12.
- Add support for
lazyimport parsing (#23755) - Add support for star-unpacking of comprehensions (PEP 798) (#23788)
- Reject semantic syntax errors for lazy imports (#23757)
- Drop a few rules from the preview default set (#23879)
- [
airflow] FlagVariable.get()calls outside of task execution context (AIR003) (#23584) - [
airflow] Flag runtime-varying values in DAG/task constructor arguments (AIR304) (#23631) - [
flake8-bugbear] Implementdelattr-with-constant(B043) (#23737) - [
flake8-tidy-imports] AddTID254to enforce lazy imports (#23777) - [
flake8-tidy-imports] Allow users to ban lazy imports withTID254(#23847) - [
isort] Retainlazykeyword when sorting imports (#23762) - [
pyupgrade] Addfrom __future__ import annotationsautomatically (UP006) (#23260) - [
refurb] Supportnewlineparameter inFURB101for Python 3.13+ (#23754) - [
ruff] Addos-path-commonprefix(RUF071) (#23814) - [
ruff] Add unsafe fix for os-path-commonprefix (RUF071) (#23852) - [
ruff] LimitRUF036to typing contexts; make it unsafe for non-typing-only (#23765) - [
ruff] Use starred unpacking forRUF017in Python 3.15+ (#23789)
- Fix
--add-noqacreating unwanted leading whitespace (#23773) - Fix
--add-noqabreaking shebangs (#23577) - [formatter] Fix lambda body formatting for multiline calls and subscripts (#23866)
- [formatter] Preserve required annotation parentheses in annotated assignments (#23865)
- [formatter] Preserve type-expression parentheses in the formatter (#23867)
- [
flake8-annotations] Fix stack overflow inANN401on quoted annotations with escape sequences (#23912) - [
pep8-naming] Check naming conventions inmatchpattern bindings (N806,N815,N816) (#23899) - [
perflint] Fix comment duplication in fixes (PERF401,PERF403) (#23729) - [
pyupgrade] Properly triggersuperchange in nested class (UP008) (#22677) - [
ruff] Avoid syntax errors inRUF036fixes (#23764)
- [
flake8-bandit] FlagS501withrequests.request(#23873) - [
flake8-executable] Fix WSL detection in non-Docker containers (#22879) - [
flake8-print] Ignorepprintcalls withstream=(#23787)
- Update docs for Markdown code block formatting (#23871)
- [
flake8-bugbear] Fix misleading description forB904(#23731)
- @zsol
- @carljm
- @ntBre
- @Bortlesboat
- @sososonia-cyber
- @chirizxc
- @leandrobbraga
- @11happy
- @Acelogic
- @anishgirianish
- @amyreese
- @xvchris
- @charliermarsh
- @getehen
- @Dev-iL
Released on 2026-03-05.
- Discover Markdown files by default in preview mode (#23434)
- [
perflint] ExtendPERF102to comprehensions and generators (#23473) - [
refurb] FixFURB101andFURB103false positives when I/O variable is used later (#23542) - [
ruff] Add fix fornone-not-at-end-of-union(RUF036) (#22829) - [
ruff] Fix false positive forre.splitwith empty string pattern (RUF055) (#23634)
- [
fastapi] Handle callable class dependencies with__call__method (FAST003) (#23553) - [
pydocstyle] Fix numpy section ordering (D420) (#23685) - [
pyflakes] Fix false positive for names shadowing re-exports (F811) (#23356) - [
pyupgrade] Avoid inserting redundantNoneelements inUP045(#23459)
- Document extension mapping for Markdown code formatting (#23574)
- Update default Python version examples (#23605)
- Publish releases to Astral mirror (#23616)
Released on 2026-02-26.
This is a follow-up release to 0.15.3 that resolves a panic when the new rule PLR1712 was enabled with any rule that analyzes definitions, such as many of the ANN or D rules.
- Fix panic on access to definitions after analyzing definitions (#23588)
- [
pyflakes] Suppress false positive inF821for names used beforedelin stub files (#23550)
Released on 2026-02-26.
-
Drop explicit support for
.qmdfile extension (#23572)This can now be enabled instead by setting the
extensionoption:# ruff.toml extension = { qmd = "markdown" } # pyproject.toml [tool.ruff] extension = { qmd = "markdown" }
-
Include configured extensions in file discovery (#23400)
-
[
flake8-bandit] Allow suspicious imports inTYPE_CHECKINGblocks (S401-S415) (#23441) -
[
flake8-bugbear] AllowB901in pytest hook wrappers (#21931) -
[
flake8-import-conventions] Add missing conventions from upstream (ICN001,ICN002) (#21373) -
[
pydocstyle] Add rule to enforce docstring section ordering (D420) (#23537) -
[
pylint] Implementswap-with-temporary-variable(PLR1712) (#22205) -
[
ruff] Addunnecessary-assign-before-yield(RUF070) (#23300) -
[
ruff] Support file-level noqa inRUF102(#23535) -
[
ruff] Suppress diagnostic for invalid f-strings before Python 3.12 (RUF027) (#23480) -
[
flake8-bandit] Don't flagBaseLoader/CBaseLoaderas unsafe (S506) (#23510)
- Avoid infinite loop between
I002andPYI025(#23352) - [
pyflakes] Fix false positive for@overloadfromlint.typing-modules(F811) (#23357) - [
pyupgrade] Fix false positive forTypeVardefault before Python 3.12 (UP046) (#23540) - [
pyupgrade] Fix handling of\Nin raw strings (UP032) (#22149)
-
Render sub-diagnostics in the GitHub output format (#23455)
-
[
flake8-bugbear] Tag certainB007diagnostics as unnecessary (#23453) -
[
ruff] Ignore unknown rule codes inRUF100(#23531)These are now flagged by
RUF102instead.
- Fix missing settings links for several linters (#23519)
- Update isort action comments heading (#23515)
- [
pydocstyle] Fix double comma in description ofD404(#23440)
- Update the Python module (notably
find_ruff_bin) for parity with uv (#23406)
- @zanieb
- @o1x3
- @assadyousuf
- @kar-ganap
- @denyszhak
- @amyreese
- @carljm
- @anishgirianish
- @Bnyro
- @danparizher
- @ntBre
- @gcomneno
- @jaap3
- @stakeswky
Released on 2026-02-19.
-
Expand the default rule set (#23385)
In preview, Ruff now enables a significantly expanded default rule set of 412 rules, up from the stable default set of 59 rules. The new rules are mostly a superset of the stable defaults, with the exception of these rules, which are removed from the preview defaults:
multiple-imports-on-one-line(E401)module-import-not-at-top-of-file(E402)module-import-not-at-top-of-file(E701)multiple-statements-on-one-line-semicolon(E702)useless-semicolon(E703)none-comparison(E711)true-false-comparison(E712)not-in-test(E713)not-is-test(E714)type-comparison(E721)lambda-assignment(E731)ambiguous-variable-name(E741)ambiguous-class-name(E742)ambiguous-function-name(E743)undefined-local-with-import-star(F403)undefined-local-with-import-star-usage(F405)undefined-local-with-nested-import-star-usage(F406)forward-annotation-syntax-error(F722)
If you use preview and prefer the old defaults, you can restore them with configuration like:
# ruff.toml [lint] select = ["E4", "E7", "E9", "F"] # pyproject.toml [tool.ruff.lint] select = ["E4", "E7", "E9", "F"]
If you do give them a try, feel free to share your feedback in the GitHub discussion!
-
[
flake8-pyi] Also check string annotations (PYI041) (#19023)
- [
flake8-async] Fixin_async_contextlogic (#23426) - [
ruff] Fix forRUF102should delete entire comment (#23380) - [
ruff] Suppress diagnostic for strings with backslashes in interpolations before Python 3.12 (RUF027) (#21069) - [
flake8-bugbear] FixB023false positive for immediately-invoked lambdas (#23294) - [parser] Fix false syntax error for match-like annotated assignments (#23297)
- [parser] Fix indentation tracking after line continuations (#23417)
- [
flake8-executable] Allow global flags in uv shebangs (EXE003) (#22582) - [
pyupgrade] Fix handling oftyping.{io,re}(UP035) (#23131) - [
ruff] DetectPLC0207on chainedstr.split()calls (#23275)
- Remove invalid inline
noqawarning (#23270)
- Add extension mapping to configuration file options (#23384)
- Add
Q004to the list of conflicting rules (#23340) - [
ruff] Expandlint.externaldocs and add sub-diagnostic (RUF100,RUF102) (#23268)
- @dylwil3
- @Jkhall81
- @danparizher
- @dhruvmanila
- @harupy
- @ngnpope
- @amyreese
- @kar-ganap
- @robsdedude
- @shaanmajid
- @ntBre
- @toslunar
Released on 2026-02-12.
- [
airflow] Add ruff rules to catch deprecated Airflow imports for Airflow 3.1 (AIR321) (#22376) - [
airflow] Third positional parameter not namedti_keyshould be flagged forBaseOperatorLink.get_link(AIR303) (#22828) - [
flake8-gettext] Fix false negatives for plural argument ofngettext(INT001,INT002,INT003) (#21078) - [
pyflakes] Fix infinite loop in preview fix forunused-import(F401) (#23038) - [
pygrep-hooks] Detect non-existent mock methods in standalone expressions (PGH005) (#22830) - [
pylint] Allow dunder submodules and improve diagnostic range (PLC2701) (#22804) - [
pyupgrade] Improve diagnostic range for tuples (UP024) (#23013) - [
refurb] Check subscripts in tuple do not use lambda parameters inreimplemented-operator(FURB118) (#23079) - [
ruff] Detect mutable defaults infieldcalls (RUF008) (#23046) - [
ruff] Ignore stdcmath.inf(RUF069) (#23120) - [
ruff] New rulefloat-equality-comparison(RUF069) (#20585) - Don't format unlabeled Markdown code blocks (#23106)
- Markdown formatting support in LSP (#23063)
- Support Quarto Markdown language markers (#22947)
- Support formatting
pyconMarkdown code blocks (#23112) - Use extension mapping to select Markdown code block language (#22934)
- Avoid false positive for undefined variables in
FAST001(#23224) - Avoid introducing syntax errors for
FAST003autofix (#23227) - Avoid suggesting
InitVarfor__post_init__that references PEP 695 type parameters (#23226) - Deduplicate type variables in generic functions (#23225)
- Fix exception handler parenthesis removal for Python 3.14+ (#23126)
- Fix f-string middle panic when parsing t-strings (#23232)
- Wrap
RUF020target for multiline fixes (#23210) - Wrap
UP007target for multiline fixes (#23208) - Fix missing diagnostics for last range suppression in file (#23242)
- [
pyupgrade] Fix syntax error on string with newline escape and comment (UP037) (#22968)
- Use
ruffinstead ofRuffas the program name in GitHub output format (#23240) - [
PT006] Fix syntax error when unpacking nested tuples inparametrizefixes (#22441) (#22464) - [
airflow] Catch deprecated attribute access from context key for Airflow 3.0 (AIR301) (#22850) - [
airflow] Capture deprecated arguments and a decorator (AIR301) (#23170) - [
flake8-boolean-trap] Addmultiprocessing.Valueto excluded functions forFBT003(#23010) - [
flake8-bugbear] Add a secondary annotation showing the previous occurrence (B033) (#22634) - [
flake8-type-checking] Add sub-diagnostic showing the runtime use of an annotation (TC004) (#23091) - [
isort] Support configurable import section heading comments (#23151) - [
ruff] Improve the diagnostic forRUF012(#23202)
- Suppress diagnostic output for
format --check --silent(#17736)
- Add tabbed shell completion documentation (#23169)
- Explain how to enable Markdown formatting for pre-commit hook (#23077)
- Fixed import in
runtime-evaluated-decoratorsexample (#23187) - Update ruff server contributing guide (#23060)
- Exclude WASM artifacts from GitHub releases (#23221)
- @mkniewallner
- @bxff
- @dylwil3
- @Avasam
- @amyreese
- @charliermarsh
- @Alex-ley-scrub
- @Kalmaegi
- @danparizher
- @AiyionPrime
- @eureka928
- @11happy
- @Jkhall81
- @chirizxc
- @leandrobbraga
- @tvatter
- @anishgirianish
- @shaanmajid
- @ntBre
- @sjyangkevin
Released on 2026-02-03.
Check out the blog post for a migration guide and overview of the changes!
-
Ruff now formats your code according to the 2026 style guide. See the formatter section below or in the blog post for a detailed list of changes.
-
The linter now supports block suppression comments. For example, to suppress
N803for all parameters in this function:# ruff: disable[N803] def foo( legacyArg1, legacyArg2, legacyArg3, legacyArg4, ): ... # ruff: enable[N803]
See the documentation for more details.
-
The
ruff:alpineDocker image is now based on Alpine 3.23 (up from 3.21). -
The
ruff:debianandruff:debian-slimDocker images are now based on Debian 13 "Trixie" instead of Debian 12 "Bookworm." -
Binaries for the
ppc64(64-bit big-endian PowerPC) architecture are no longer included in our releases. It should still be possible to build Ruff manually for this platform, if needed. -
Ruff now resolves all
extended configuration files before falling back on a default Python version.
The following rules have been stabilized and are no longer in preview:
blocking-http-call-httpx-in-async-function(ASYNC212)blocking-path-method-in-async-function(ASYNC240)blocking-input-in-async-function(ASYNC250)map-without-explicit-strict(B912)if-exp-instead-of-or-operator(FURB110)single-item-membership-test(FURB171)missing-maxsplit-arg(PLC0207)unnecessary-lambda(PLW0108)unnecessary-empty-iterable-within-deque-call(RUF037)in-empty-collection(RUF060)legacy-form-pytest-raises(RUF061)non-octal-permissions(RUF064)invalid-rule-code(RUF102)invalid-suppression-comment(RUF103)unmatched-suppression-comment(RUF104)replace-str-enum(UP042)
The following behaviors have been stabilized:
- The
--output-formatflag is now respected when running Ruff in--watchmode, and thefulloutput format is now used by default, matching the regular CLI output. builtin-attribute-shadowing(A003) now detects the use of shadowed built-in names in additional contexts like decorators, default arguments, and other attribute definitions.duplicate-union-member(PYI016) now considerstyping.Optionalwhen searching for duplicate union members.split-static-string(SIM905) now offers an autofix when themaxsplitargument is provided, even without asepargument.dict-get-with-none-default(SIM910) now applies to more types of key expressions.super-call-with-parameters(UP008) now has a safe fix when it will not delete comments.unnecessary-default-type-args(UP043) now applies to stub (.pyi) files on Python versions before 3.13.
This release introduces the new 2026 style guide, with the following changes:
- Lambda parameters are now kept on the same line and lambda bodies will be parenthesized to let them break across multiple lines (#21385)
- Parentheses around tuples of exceptions in
exceptclauses will now be removed on Python 3.14 and later (#20768) - A single empty line is now permitted at the beginning of function bodies (#21110)
- Parentheses are avoided for long
ascaptures inmatchstatements (#21176) - Extra spaces between escaped quotes and ending triple quotes can now be omitted (#17216)
- Blank lines are now enforced before classes with decorators in stub files (#18888)
-
Apply formatting to Markdown code blocks (#22470, #22990, #22996)
See the documentation for more details.
- Fix suppression indentation matching (#22903)
- Customize where the
fix_titlesub-diagnostic appears (#23044) - [
FastAPI] Add sub-diagnostic explaining why a fix was unavailable (FAST002) (#22565) - [
flake8-annotations] Don't suggestNoReturnfor functions raisingNotImplementedError(ANN201,ANN202,ANN205,ANN206) (#21311) - [
pyupgrade] Make fix unsafe if it deletes comments (UP017) (#22873) - [
pyupgrade] Make fix unsafe if it deletes comments (UP020) (#22872) - [
pyupgrade] Make fix unsafe if it deletes comments (UP033) (#22871) - [
refurb] Do not addabc.ABCif already present (FURB180) (#22234) - [
refurb] Make fix unsafe if it deletes comments (FURB110) (#22768) - [
ruff] Add sub-diagnostics with permissions (RUF064) (#22972)
- Identify notebooks by LSP
didOpeninstead of.ipynbfile extension (#22810)
- Add
--colorCLI option to force colored output (#22806)
- Document
-stdin convention in CLI help text (#22817) - [
refurb] Change example tore.searchwith^anchor (FURB167) (#22984) - Fix link to Sphinx code block directives (#23041)
- [
pydocstyle] Clarify which quote styles are allowed (D300) (#22825) - [
flake8-bugbear] Improve docs forno-explicit-stacklevel(B028) (#22538)
- Update MSRV to 1.91 (#22874)
- @danparizher
- @chirizxc
- @amyreese
- @Jkhall81
- @cwkang1998
- @manzt
- @11happy
- @hugovk
- @caiquejjx
- @ntBre
- @akawd
- @konstin
See changelogs/0.9.x
See changelogs/0.8.x
See changelogs/0.7.x
See changelogs/0.6.x
See changelogs/0.5.x
See changelogs/0.4.x
See changelogs/0.3.x
See changelogs/0.2.x
See changelogs/0.1.x