mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-01 20:31:57 +00:00
Summary -- During the release today, I noticed that the changelog is finally too long to render at all on GitHub. This PR follows the same splitting procedure as in uv (astral-sh/uv#11510, astral-sh/uv#12099): first splitting the file into one per minor version, and then reversing the contents of each file to start with the breaking release (`changelogs/0.11.x.md` starts with 0.11.0 instead of 0.11.13 as in the old changelog). For the second part, I used [`reverse-changelog.py`](https://github.com/astral-sh/uv/blob/main/scripts/reverse-changelog.py) from the uv repo, so hopefully everything is correct. I spot-checked 0.7.0 at least.
36 KiB
36 KiB
Changelog 0.9.x
0.9.0
Check out the blog post for a migration guide and overview of the changes!
Breaking changes
Ruff now formats your code according to the 2025 style guide. As a result, your code might now get formatted differently. See the formatter section for a detailed list of changes.
This release doesn’t remove or remap any existing stable rules.
Stabilization
The following rules have been stabilized and are no longer in preview:
stdlib-module-shadowing(A005). This rule has also been renamed: previously, it was calledbuiltin-module-shadowing.builtin-lambda-argument-shadowing(A006)slice-to-remove-prefix-or-suffix(FURB188)boolean-chained-comparison(PLR1716)decimal-from-float-literal(RUF032)post-init-default(RUF033)useless-if-else(RUF034)
The following behaviors have been stabilized:
pytest-parametrize-names-wrong-type(PT006): Detectpytest.parametrizecalls outside decorators and calls with keyword arguments.module-import-not-at-top-of-file(E402): Ignorepytest.importorskipcalls between import statements.mutable-dataclass-default(RUF008) andfunction-call-in-dataclass-default-argument(RUF009): Add support forattrs.bad-version-info-comparison(PYI006): Extend the rule to check non-stub files.
The following fixes or improvements to fixes have been stabilized:
redundant-numeric-union(PYI041)duplicate-union-members(PYI016)
Formatter
This release introduces the new 2025 stable style (#13371), stabilizing the following changes:
- Format expressions in f-string elements (#7594)
- Alternate quotes for strings inside f-strings (#13860)
- Preserve the casing of hex codes in f-string debug expressions (#14766)
- Choose the quote style for each string literal in an implicitly concatenated f-string rather than for the entire string (#13539)
- Automatically join an implicitly concatenated string into a single string literal if it fits on a single line (#9457)
- Remove the
ISC001incompatibility warning (#15123) - Prefer parenthesizing the
assertmessage over breaking the assertion expression (#9457) - Automatically parenthesize over-long
ifguards inmatchcaseclauses (#13513) - More consistent formatting for
matchcasepatterns (#6933) - Avoid unnecessary parentheses around return type annotations (#13381)
- Keep the opening parentheses on the same line as the
ifkeyword for comprehensions where the condition has a leading comment (#12282) - More consistent formatting for
withstatements with a single context manager for Python 3.8 or older (#10276) - Correctly calculate the line-width for code blocks in docstrings when using
max-doc-code-line-length = "dynamic"(#13523)
Preview features
- [
flake8-bugbear] Implementclass-as-data-structure(B903) (#9601) - [
flake8-type-checking] Applyquoted-type-aliasmore eagerly inTYPE_CHECKINGblocks and ignore it in stubs (TC008) (#15180) - [
pylint] Ignoreeq-without-hashin stub files (PLW1641) (#15310) - [
pyupgrade] SplitUP007into two individual rules:UP007forUnionandUP045forOptional(UP007,UP045) (#15313) - [
ruff] New rule that detects classes that are both an enum and adataclass(RUF049) (#15299) - [
ruff] RecodeRUF025toRUF037(RUF037) (#15258)
Rule changes
- [
flake8-builtins] Ignorestdlib-module-shadowingin stub files(A005) (#15350) - [
flake8-return] Add support for functions returningtyping.Never(RET503) (#15298)
Server
- Improve the observability by removing the need for the "trace" value to turn on or off logging. The server logging is solely controlled using the
logLevelserver setting which defaults toinfo. This addresses the issue where users were notified about an error and told to consult the log, but it didn’t contain any messages. (#15232) - Ignore diagnostics from other sources for code action requests (#15373)
CLI
- Improve the error message for
--config key=valuewhen thekeyis for a table and it’s a simplevalue
Bug fixes
- [
eradicate] Ignore metadata blocks directly followed by normal blocks (ERA001) (#15330) - [
flake8-django] Recognize other magic methods (DJ012) (#15365) - [
pycodestyle] Avoid false positives related to type aliases (E252) (#15356) - [
pydocstyle] Avoid treating newline-separated sections as sub-sections (D405) (#15311) - [
pyflakes] Remove call when removing final argument fromformat(F523) (#15309) - [
refurb] Mark fix as unsafe when the right-hand side is a string (FURB171) (#15273) - [
ruff] Treat)as a regex metacharacter (RUF043,RUF055) (#15318) - [
ruff] Parenthesize theint-call argument when removing theintcall would change semantics (RUF046) (#15277)
0.9.1
Preview features
- [
pycodestyle] Runtoo-many-newlines-at-end-of-fileon each cell in notebooks (W391) (#15308) - [
ruff] Omit diagnostic for shadowed private function parameters inused-dummy-variable(RUF052) (#15376)
Rule changes
- [
flake8-bugbear] Improveassert-raises-exceptionmessage (B017) (#15389)
Formatter
- Preserve trailing end-of line comments for the last string literal in implicitly concatenated strings (#15378)
Server
- Fix a bug where the server and client notebooks were out of sync after reordering cells (#15398)
Bug fixes
- [
flake8-pie] Correctly remove wrapping parentheses (PIE800) (#15394) - [
pyupgrade] Handle comments and multiline expressions correctly (UP037) (#15337)
0.9.2
Preview features
- [
airflow] Fix typo "security_managr" to "security_manager" (AIR303) (#15463) - [
airflow] extend and fix AIR302 rules (#15525) - [
fastapi] Handle parameters withDependscorrectly (FAST003) (#15364) - [
flake8-pytest-style] Implement pytest.warns diagnostics (PT029,PT030,PT031) (#15444) - [
flake8-pytest-style] Test function parameters with default arguments (PT028) (#15449) - [
flake8-type-checking] Avoid false positives for|inTC008(#15201)
Rule changes
- [
flake8-todos] Allow VSCode GitHub PR extension style links inmissing-todo-link(TD003) (#15519) - [
pyflakes] Show syntax error message forF722(#15523)
Formatter
- Fix curly bracket spacing around f-string expressions containing curly braces (#15471)
- Fix joining of f-strings with different quotes when using quote style
Preserve(#15524)
Server
- Avoid indexing the same workspace multiple times (#15495)
- Display context for
ruff.configurationerrors (#15452)
Configuration
- Remove
flattento improve deserialization error messages (#15414)
Bug fixes
- Parse triple-quoted string annotations as if parenthesized (#15387)
- [
fastapi] UpdateAnnotatedfixes (FAST002) (#15462) - [
flake8-bandit] Check forbuiltinsinstead ofbuiltin(S102,PTH123) (#15443) - [
flake8-pathlib] Fix--selectforos-path-dirname(PTH120) (#15446) - [
ruff] Fix false positive on global keyword (RUF052) (#15235)
0.9.3
Preview features
- [
airflow] Argumentfail_stopin DAG has been renamed asfail_fast(AIR302) (#15633) - [
airflow] ExtendAIR303with more symbols (#15611) - [
flake8-bandit] Report all references to suspicious functions (S3) (#15541) - [
flake8-pytest-style] Do not emit diagnostics for emptyforloops (PT012,PT031) (#15542) - [
flake8-simplify] Avoid double negations (SIM103) (#15562) - [
pyflakes] Fix infinite loop with unused local import in__init__.py(F401) (#15517) - [
pylint] Do not report methods with only oneEM101-compatibleraise(PLR6301) (#15507) - [
pylint] Implementredefined-slots-in-subclass(W0244) (#9640) - [
pyupgrade] Add rules to use PEP 695 generics in classes and functions (UP046,UP047) (#15565, #15659) - [
refurb] Implementfor-loop-writes(FURB122) (#10630) - [
ruff] Implementneedless-elseclause (RUF047) (#15051) - [
ruff] Implementstarmap-zip(RUF058) (#15483)
Rule changes
- [
flake8-bugbear] Do not raise error if keyword argument is present and target-python version is less or equals than 3.9 (B903) (#15549) - [
flake8-comprehensions] strip parentheses around generators inunnecessary-generator-set(C401) (#15553) - [
flake8-pytest-style] Rewrite references to.exception(PT027) (#15680) - [
flake8-simplify] Mark fixes as unsafe (SIM201,SIM202) (#15626) - [
flake8-type-checking] Fix some safe fixes being labeled unsafe (TC006,TC008) (#15638) - [
isort] Omit trailing whitespace inunsorted-imports(I001) (#15518) - [
pydoclint] Allow ignoring one line docstrings forDOCrules (#13302) - [
pyflakes] Apply redefinition fixes by source code order (F811) (#15575) - [
pyflakes] Avoid removing too many imports inredefined-while-unused(F811) (#15585) - [
pyflakes] Group redefinition fixes by source statement (F811) (#15574) - [
pylint] Include name of base class in message forredefined-slots-in-subclass(W0244) (#15559) - [
ruff] Update fix forRUF055to usevar == value(#15605)
Formatter
- Fix bracket spacing for single-element tuples in f-string expressions (#15537)
- Fix unstable f-string formatting for expressions containing a trailing comma (#15545)
Performance
- Avoid quadratic membership check in import fixes (#15576)
Server
- Allow
unsafe-fixessettings for code actions (#15666)
Bug fixes
- [
flake8-bandit] Add missing single-line/dotall regex flag (S608) (#15654) - [
flake8-import-conventions] Fix infinite loop betweenICN001andI002(ICN001) (#15480) - [
flake8-simplify] Do not emit diagnostics for expressions inside string type annotations (SIM222,SIM223) (#15405) - [
pyflakes] Treat arguments passed to thedefault=parameter ofTypeVaras type expressions (F821) (#15679) - [
pyupgrade] Avoid syntax error when the iterable is a non-parenthesized tuple (UP028) (#15543) - [
ruff] ExemptNewTypecalls where the original type is immutable (RUF009) (#15588) - Preserve raw string prefix and escapes in all codegen fixes (#15694)
Documentation
- Generate documentation redirects for lowercase rule codes (#15564)
TRY300: Add some extra notes on not catching exceptions you didn't expect (#15036)
0.9.4
Preview features
- [
airflow] Extend airflow context parameter check forBaseOperator.execute(AIR302) (#15713) - [
airflow] UpdateAIR302to check for deprecated context keys (#15144) - [
flake8-bandit] Permit suspicious imports within stub files (S4) (#15822) - [
pylint] Do not triggerPLR6201on empty collections (#15732) - [
refurb] Do not emit diagnostic when loop variables are used outside loop body (FURB122) (#15757) - [
ruff] Add support for morerepatterns (RUF055) (#15764) - [
ruff] Check for shadowedmapbefore suggesting fix (RUF058) (#15790) - [
ruff] Do not emit diagnostic when all arguments tozip()are variadic (RUF058) (#15744) - [
ruff] Parenthesize fix when argument spans multiple lines forunnecessary-round(RUF057) (#15703)
Rule changes
- Preserve quote style in generated code (#15726, #15778, #15794)
- [
flake8-bugbear] ExemptNewTypecalls where the original type is immutable (B008) (#15765) - [
pylint] Honor banned top-level imports byTID253inPLC0415. (#15628) - [
pyupgrade] Ignoreis_typeddictandTypedDictfordeprecated-import(UP035) (#15800)
CLI
- Fix formatter warning message for
flake8-quotesoption (#15788) - Implement tab autocomplete for
ruff config(#15603)
Bug fixes
- [
flake8-comprehensions] Do not emitunnecessary-mapdiagnostic when lambda has different arity (C417) (#15802) - [
flake8-comprehensions] Parenthesizesortedwhen needed forunnecessary-call-around-sorted(C413) (#15825) - [
pyupgrade] Handle end-of-line comments forquoted-annotation(UP037) (#15824)
Documentation
- Add missing config docstrings (#15803)
- Add references to
trio.run_processandanyio.run_process(#15761) - Use
uv init --libin tutorial (#15718)
0.9.5
Preview features
- Recognize all symbols named
TYPE_CHECKINGforin_type_checking_block(#15719) - [
flake8-comprehensions] Handle builtins at top of file correctly forunnecessary-dict-comprehension-for-iterable(C420) (#15837) - [
flake8-logging].exception()andexc_info=outside exception handlers (LOG004,LOG014) (#15799) - [
flake8-pyi] Fix incorrect behaviour ofcustom-typevar-return-typepreview-mode autofix iftypingwas already imported (PYI019) (#15853) - [
flake8-pyi] Fix more complex cases (PYI019) (#15821) - [
flake8-pyi] MakePYI019autofixable for.pyfiles in preview mode as well as stubs (#15889) - [
flake8-pyi] Remove type parameter correctly when it is the last (PYI019) (#15854) - [
pylint] Fix missing parens in unsafe fix forunnecessary-dunder-call(PLC2801) (#15762) - [
pyupgrade] Better messages and diagnostic range (UP015) (#15872) - [
pyupgrade] Rename private type parameters in PEP 695 generics (UP049) (#15862) - [
refurb] Also report non-name expressions (FURB169) (#15905) - [
refurb] Mark fix as unsafe if there are comments (FURB171) (#15832) - [
ruff] Classes with mixed type variable style (RUF053) (#15841) - [
airflow]BashOperatorhas been moved toairflow.providers.standard.operators.bash.BashOperator(AIR302) (#15922) - [
flake8-pyi] Add autofix for unused-private-type-var (PYI018) (#15999) - [
flake8-pyi] Significantly improve accuracy ofPYI019if preview mode is enabled (#15888)
Rule changes
- Preserve triple quotes and prefixes for strings (#15818)
- [
flake8-comprehensions] Skip whenTypeErrorpresent from too many (kw)args forC410,C411, andC418(#15838) - [
flake8-pyi] RenamePYI019and improve its diagnostic message (#15885) - [
pep8-naming] Ignore@overridemethods (N803) (#15954) - [
pyupgrade] Reuse replacement logic fromUP046andUP047to preserve more comments (UP040) (#15840) - [
ruff] Analyze deferred annotations before enforcingmutable-(data)class-defaultandfunction-call-in-dataclass-default-argument(RUF008,RUF009,RUF012) (#15921) - [
pycodestyle] Exemptsys.path += ...calls (E402) (#15980)
Configuration
- Config error only when
flake8-import-conventionsalias conflicts withisort.required-importsbound name (#15918) - Workaround Even Better TOML crash related to
allOf(#15992)
Bug fixes
- [
flake8-comprehensions] Unnecessarylistcomprehension (rewrite as asetcomprehension) (C403) - Handle extraneous parentheses around list comprehension (#15877) - [
flake8-comprehensions] Handle trailing comma in fixes forunnecessary-generator-list/set(C400,C401) (#15929) - [
flake8-pyi] Fix several correctness issues withcustom-type-var-return-type(PYI019) (#15851) - [
pep8-naming] Consider any number of leading underscore forN801(#15988) - [
pyflakes] Visit forward annotations inTypeAliasTypeas types (F401) (#15829) - [
pylint] Correct min/max auto-fix and suggestion for (PL1730) (#15930) - [
refurb] Handle unparenthesized tuples correctly (FURB122,FURB142) (#15953) - [
refurb] AvoidNone | Noneas well as better detection and fix (FURB168) (#15779)
Documentation
- Add deprecation warning for
ruff-lsprelated settings (#15850) - Docs (
linter.md): clarify that Python files are always searched for in subdirectories (#15882) - Fix a typo in
non_pep695_generic_class.rs(#15946) - Improve Docs: Pylint subcategories' codes (#15909)
- Remove non-existing
lint.extendIgnoreeditor setting (#15844) - Update black deviations (#15928)
- Mention
UP049inUP046andUP047, addSee alsosection toUP040(#15956) - Add instance variable examples to
RUF012(#15982) - Explain precedence for
ignoreandselectconfig (#15883)
0.9.6
Preview features
- [
airflow] Addexternal_task.{ExternalTaskMarker, ExternalTaskSensor}forAIR302(#16014) - [
flake8-builtins] Make strict module name comparison optional (A005) (#15951) - [
flake8-pyi] Extend fix to Python <= 3.9 forredundant-none-literal(PYI061) (#16044) - [
pylint] Also report when the object isn't a literal (PLE1310) (#15985) - [
ruff] Implementindented-form-feed(RUF054) (#16049) - [
ruff] Skip type definitions formissing-f-string-syntax(RUF027) (#16054)
Rule changes
- [
flake8-annotations] Correct syntax fortyping.Unionin suggested return type fixes forANN20xrules (#16025) - [
flake8-builtins] Match upstream module name comparison (A005) (#16006) - [
flake8-comprehensions] Detect overshadowedlist/set/dict, ignore variadics and named expressions (C417) (#15955) - [
flake8-pie] Remove following comma correctly when the unpacked dictionary is empty (PIE800) (#16008) - [
flake8-simplify] Only triggerSIM401on known dictionaries (#15995) - [
pylint] Do not report calls when object type and argument type mismatch, remove custom escape handling logic (PLE1310) (#15984) - [
pyupgrade] Comments within parenthesized value ranges should not affect applicability (UP040) (#16027) - [
pyupgrade] Don't introduce invalid syntax when upgrading old-style type aliases with parenthesized multiline values (UP040) (#16026) - [
pyupgrade] Ensure we do not rename two type parameters to the same name (UP049) (#16038) - [
pyupgrade] [ruff] Don't apply renamings if the new name is shadowed in a scope of one of the references to the binding (UP049,RUF052) (#16032) - [
ruff] UpdateRUF009to behave similar toB008and ignore attributes with immutable types (#16048)
Server
- Root exclusions in the server to project root (#16043)
Bug fixes
- [
flake8-datetime] Ignore.replace()calls while looking for.astimezone(#16050) - [
flake8-type-checking] AvoidTC004false positive where the runtime definition is provided by__getattr__(#16052)
Documentation
0.9.7
Preview features
- Consider
__new__methods as special function type for enforcing class method or static method rules (#13305) - [
airflow] Improve the internal logic to differentiate deprecated symbols (AIR303) (#16013) - [
refurb] Manual timezone monkeypatching (FURB162) (#16113) - [
ruff] Implicit class variable in dataclass (RUF045) (#14349) - [
ruff] Skip singleton starred expressions forincorrectly-parenthesized-tuple-in-subscript(RUF031) (#16083) - [
refurb] Check for subclasses includes subscript expressions (FURB189) (#16155)
Rule changes
- [
flake8-debugger] Also flagsys.breakpointhookandsys.__breakpointhook__(T100) (#16191) - [
pycodestyle] Exemptsite.addsitedir(...)calls (E402) (#16251)
Formatter
- Fix unstable formatting of trailing end-of-line comments of parenthesized attribute values (#16187)
Server
- Fix handling of requests received after shutdown message (#16262)
- Ignore
source.organizeImports.ruffandsource.fixAll.ruffcode actions for a notebook cell (#16154) - Include document specific debug info for
ruff.printDebugInformation(#16215) - Update server to return the debug info as string with
ruff.printDebugInformation(#16214)
CLI
- Warn on invalid
noqaeven when there are no diagnostics (#16178) - Better error messages while loading configuration
extends (#15658)
Bug fixes
- [
flake8-comprehensions] Handle trailing comma inC403fix (#16110) - [
flake8-pyi] Avoid flaggingcustom-typevar-for-selfon metaclass methods (PYI019) (#16141) - [
pydocstyle] Handle arguments with the same names as sections (D417) (#16011) - [
pylint] Correct ordering of arguments in fix forif-stmt-min-max(PLR1730) (#16080) - [
pylint] Do not offer fix for raw strings (PLE251) (#16132) - [
pyupgrade] Do not upgrade functionalTypedDictswith private field names to the class-based syntax (UP013) (#16219) - [
pyupgrade] Handle micro version numbers correctly (UP036) (#16091) - [
pyupgrade] Unwrap unary expressions correctly (UP018) (#15919) - [
refurb] Correctly handle lengths of literal strings inslice-to-remove-prefix-or-suffix(FURB188) (#16237) - [
ruff] SkipRUF001diagnostics when visiting string type definitions (#16122)
Documentation
0.9.8
Preview features
- Start detecting version-related syntax errors in the parser (#16090)
Rule changes
- [
pylint] Mark fix unsafe (PLW1507) (#16343) - [
pylint] Catchcase np.nan/case math.naninmatchstatements (PLW0177) (#16378) - [
ruff] Add more Pydantic models variants to the list of default copy semantics (RUF012) (#16291)
Server
- Avoid indexing the project if
configurationPreferenceiseditorOnly(#16381) - Avoid unnecessary info at non-trace server log level (#16389)
- Expand
ruff.configurationto allow inline config (#16296) - Notify users for invalid client settings (#16361)
Configuration
- Add
per-file-target-versionoption (#16257)
Bug fixes
- [
refurb] Do not consider docstring(s) (FURB156) (#16391) - [
flake8-self] Ignore attribute accesses on instance-like variables (SLF001) (#16149) - [
pylint] Fix false positives, add missing methods, and support positional-only parameters (PLE0302) (#16263) - [
flake8-pyi] MarkPYI030fix unsafe when comments are deleted (#16322)
Documentation
- Fix example for
S611(#16316) - Normalize inconsistent markdown headings in docstrings (#16364)
- Document MSRV policy (#16384)
0.9.9
Preview features
- Fix caching of unsupported-syntax errors (#16425)
Bug fixes
- Only show unsupported-syntax errors in editors when preview mode is enabled (#16429)
0.9.10
Preview features
- [
ruff] Add new ruleRUF059: Unused unpacked assignment (#16449) - [
syntax-errors] Detect assignment expressions before Python 3.8 (#16383) - [
syntax-errors] Named expressions in decorators before Python 3.9 (#16386) - [
syntax-errors] Parenthesized keyword argument names after Python 3.8 (#16482) - [
syntax-errors] Positional-only parameters before Python 3.8 (#16481) - [
syntax-errors] Tuple unpacking inreturnandyieldbefore Python 3.8 (#16485) - [
syntax-errors] Type parameter defaults before Python 3.13 (#16447) - [
syntax-errors] Type parameter lists before Python 3.12 (#16479) - [
syntax-errors]except*before Python 3.11 (#16446) - [
syntax-errors]typestatements before Python 3.12 (#16478)
Bug fixes
- Escape template filenames in glob patterns in configuration (#16407)
- [
flake8-simplify] Exempt unittest context methods forSIM115rule (#16439) - Formatter: Fix syntax error location in notebooks (#16499)
- [
pyupgrade] Do not offer fix when at least one target isglobal/nonlocal(UP028) (#16451) - [
flake8-builtins] Ignore variables matching module attribute names (A001) (#16454) - [
pylint] Convertcodekeyword argument to a positional argument in fix for (PLR1722) (#16424)
CLI
- Move rule code from
descriptiontocheck_namein GitLab output serializer (#16437)
Documentation
- [
pydocstyle] Clarify thatD417only checks docstrings with an arguments section (#16494)