An extremely fast Python linter and code formatter, written in Rust.
flake8-pyi
] Allow for overloaded __exit__
and __aexit__
definitions (PYI036
) (#11057)pyupgrade
] Catch usages of "%s" % var
and provide an unsafe fix (UP031
) (#11019)refurb
] Implement new rule that suggests min/max over sorted()
(FURB192
) (#10868)noqa
codes (#11096)macos-12
for building release wheels to enable macOS 11 compatibility (#11146)flake8-blind-expect
] Allow raise from in BLE001
(#11131)flake8-pyi
] Allow simple assignments to None
in enum class scopes (PYI026
) (#11128)flake8-simplify
] Avoid raising SIM911
for non-zip
attribute calls (#11126)refurb
] Avoid operator.itemgetter
suggestion for single-item tuple (#11095)ruff
] Respect per-file-ignores for RUF100
with no other diagnostics (#11058)ruff
] Fix async comprehension false positive (RUF029
) (#11070)flake8-bugbear
] Document explicitly disabling strict zip (B905
) (#11040)flake8-type-checking
] Mention lint.typing-modules
in TCH001
, TCH002
, and TCH003
(#11144)isort
] Improve documentation around custom isort
sections (#11050)pylint
] Fix documentation oversight for invalid-X-returns
(#11094)matchit
to resolve per-file settings (#11111)pylint
] Implement invalid-hash-returned
(PLE0309
) (#10961)pylint
] Implement invalid-index-returned
(PLE0305
) (#10962)pylint
] Allow NoReturn
-like functions for __str__
, __len__
, etc. (PLE0307
) (#11017)ruff
] Ignore stub functions in unused-async
(RUF029
) (#11026)Ruff's new parser is >2x faster, which translates to a 20-40% speedup for all linting and formatting invocations. There's a lot to say about this exciting change, so check out the blog post for more details!
See #10036 for implementation details.
With this release, we also want to highlight our new language server. ruff server
is a Rust-powered language server that comes built-in with Ruff. It can be used with any editor that supports the Language Server Protocol (LSP). It uses a multi-threaded, lock-free architecture inspired by rust-analyzer
and it will open the door for a lot of exciting features. It’s also faster than our previous Python-based language server -- but you probably guessed that already.
ruff server
is only in alpha, but it has a lot of features that you can try out today:
ruff.applyAutofix
, ruff.applyFormat
, and ruff.applyOrganizeImports
source.fixAll
and source.organizeImports
source actionsTo setup ruff server
with your editor, refer to the README.md.
pycodestyle
] Do not trigger E3
rules on def
s following a function/method with a dummy body (#10704)pylint
] Implement invalid-bytes-returned
(E0308
) (#10959)pylint
] Implement invalid-length-returned
(E0303
) (#10963)pylint
] Implement self-cls-assignment
(W0642
) (#9267)pylint
] Omit stubs from invalid-bool
and invalid-str-return-type
(#11008)ruff
] New rule unused-async
(RUF029
) to detect unneeded async
keywords on functions (#9966)flake8-bandit
] Allow urllib.request.urlopen
calls with static Request
argument (S310
) (#10964)flake8-bugbear
] Treat raise NotImplemented
-only bodies as stub functions (B006
) (#10990)flake8-slots
] Respect same-file Enum
subclasses (SLOT000
) (#11006)pylint
] Support inverted comparisons (PLR1730
) (#10920)--show-settings
(#11003)BuiltinTypeChecker
(#10976)RuleTable::any_enabled
(#10971)This section is devoted to updates for our new language server, written in Rust.
RUFF_OUTPUT_FILE
environment variable support (#10992)non-augmented-assignment
for reversed, non-commutative operators (PLR6104
) (#10909)PLR6104
) (#10912)per-file-ignores
for RUF100
on blanket # noqa
(#10908)if
expression for parenthesized with items parsing (#11010)FOR_TARGET
context for all kinds of parentheses (#11009)flake8-bugbear
] Implement loop-iterator-mutation
(B909
) (#9578)pylint
] Implement rule to prefer augmented assignment (PLR6104
) (#9932)pylint
] Recode nan-comparison
rule to W0177
(#10894)pylint
] Reverse min-max logic in if-stmt-min-max
(#10890)pylint
] Implement bad-staticmethod-argument
(PLW0211
) (#10781)pylint
] Implement if-stmt-min-max
(PLR1730
, PLR1731
) (#10002)pyupgrade
] Replace str,Enum
multiple inheritance with StrEnum
UP042
(#10713)refurb
] Implement if-expr-instead-of-or-operator
(FURB110
) (#10687)refurb
] Implement int-on-sliced-str
(FURB166
) (#10650)refurb
] Implement write-whole-file
(FURB103
) (#10802)refurb
] Support itemgetter
in reimplemented-operator
(FURB118
) (#10526)flake8_comprehensions
] Add sum
/min
/max
to unnecessary comprehension check (C419
) (#10759)pydocstyle
] Require capitalizing docstrings where the first sentence is a single word (D403
) (#10776)pycodestyle
] Ignore annotated lambdas in class scopes (E731
) (#10720)flake8-pyi
] Various improvements to PYI034 (#10807)flake8-slots
] Flag subclasses of call-based typing.NamedTuple
s as well as subclasses of collections.namedtuple()
(SLOT002
) (#10808)pyflakes
] Allow forward references in class bases in stub files (F821
) (#10779)pygrep-hooks
] Improve blanket-noqa
error message (PGH004
) (#10851)FORCE_COLOR
env var (#10839)[extend-]per-file-ignores
(#10852)flake8-import-conventions
] Accept non-aliased (but correct) import in unconventional-import-alias
(ICN001
) (#10729)flake8-quotes
] Add semantic model flag when inside f-string replacement field (#10766)pep8-naming
] Recursively resolve TypeDicts
for N815 violations (#10719)flake8-quotes
] Respect Q00*
ignores in flake8-quotes
rules (#10728)flake8-simplify
] Show negated condition in needless-bool
diagnostics (SIM103
) (#10854)ruff
] Use within-scope shadowed bindings in asyncio-dangling-task
(RUF006
) (#10793)flake8-pytest-style
] Fix single-tuple conversion in pytest-parametrize-values-wrong-type
(PT007
) (#10862)flake8-return
] Ignore assignments to annotated variables in unnecessary-assign
(RET504
) (#10741)refurb
] Do not allow any keyword arguments for read-whole-file
in rb
mode (FURB101
) (#10803)pylint
] Don't recommend decorating staticmethods with @singledispatch
(PLE1519
, PLE1520
) (#10637)pydocstyle
] Use section name range for all section-related docstring diagnostics (#10740)# noqa
directives on __all__
openers (#10798)pylint
] Implement modified-iterating-set
(E4703
) (#10473)refurb
] Implement for-loop-set-mutations
(FURB142
) (#10583)refurb
] Implement unnecessary-from-float
(FURB164
) (#10647)refurb
] Implement verbose-decimal-constructor
(FURB157
) (#10533)flake8-comprehensions
] Handled special case for C401
which also matches C416
(#10596)flake8-pyi
] Mark unaliased-collections-abc-set-import
fix as "safe" for more cases in stub files (PYI025
) (#10547)numpy
] Add row_stack
to NumPy 2.0 migration rule (#10646)pycodestyle
] Allow cell magics before an import (E402
) (#10545)pycodestyle
] Avoid blank line rules for the first logical line in cell (#10291)flake8-boolean-trap
] Add setting for user defined allowed boolean trap (#10531)__all__
definitions when renaming symbols in autofixes (#10527)__all__
definitions (#10525)flake8-bugbear
] Avoid false positive for usage after continue
(B031
) (#10539)flake8-copyright
] Accept commas in default copyright pattern (#9498)flake8-datetimez
] Allow f-strings with %z
for DTZ007
(#10651)flake8-pytest-style
] Fix PT014
autofix for last item in list (#10532)flake8-quotes
] Ignore Q000
, Q001
when string is inside forward ref (#10585)isort
] Always place non-relative imports after relative imports (#10669)isort
] Respect Unicode characters in import sorting (#10529)pyflakes
] Fix F821 false negatives when from __future__ import annotations
is active (attempt 2) (#10524)pyflakes
] Make unnecessary-lambda
an always-unsafe fix (#10668)pylint
] Fixed false-positive on the rule PLW1641
(eq-without-hash
) (#10566)ruff
] Fix panic in unused # noqa
removal with multi-byte space (RUF100
) (#10682)CONTRIBUTING.md
(#10665)flake8-logging
next to the other flake8 plugins in registry (#10587)flake8-bandit
] Update warning message for rule S305
to address insecure block cipher mode use (#10602)flake8-bugbear
] Document use of anonymous assignment in useless-expression
(#10551)flake8-datetimez
] Clarify error messages and docs for DTZ
rules (#10621)pycodestyle
] Use same before vs. after numbers for space-around-operator
(#10640)ruff
] Change quadratic-list-summation
docs to use iadd
consistently (#10666)flake8-simplify
] Detect implicit else
cases in needless-bool
(SIM103
) (#10414)pylint
] Implement nan-comparison
(PLW0117
) (#10401)pylint
] Implement nonlocal-and-global
(E115
) (#10407)pylint
] Implement singledispatchmethod-function
(PLE5120
) (#10428)refurb
] Implement list-reverse-copy
(FURB187
) (#10212)flake8-pytest-style
] Add automatic fix for pytest-parametrize-values-wrong-type
(PT007
) (#10461)pycodestyle
] Allow SPDX license headers to exceed the line length (E501
) (#10481)C409
) (#10491)name
from being reformatted (#10442)W605
(#10480).pyi
files (#10512)E231
bug: Inconsistent catch compared to pycodestyle, such as when dict nested in list (#10469)Options
references to blank line docs (#10498)from __future__ import annotations
is active (#10362)"' (#10513)flake8-bugbear
] Allow tuples of exceptions (B030
) (#10437)flake8-quotes
] Avoid syntax errors due to invalid quotes (Q000, Q002
) (#10199)flake8-bandit
]: Implement S610
rule (#10316)pycodestyle
] Implement blank-line-at-end-of-file
(W391
) (#10243)pycodestyle
] Implement redundant-backslash
(E502
) (#10292)pylint
] - implement redeclared-assigned-name
(W0128
) (#9268)flake8_comprehensions
] Handled special case for C400
which also matches C416
(#10419)flake8-bandit
] Implement upstream updates for S311
, S324
and S605
(#10313)pyflakes
] Remove F401
fix for __init__
imports by default and allow opt-in to unsafe fix (#10365)pylint
] Implement invalid-bool-return-type
(E304
) (#10377)pylint
] Include builtin warnings in useless-exception-statement (PLW0133
) (#10394)ruff check
(#8631)PIE970
] Allow trailing ellipsis in typing.TYPE_CHECKING
(#10413)TRIO115
if the argument is a variable (#10376)F811
] Avoid removing shadowed imports that point to different symbols (#10387)F821
and F822
false positives in .pyi
files (#10341)F821
false negatives in .py
files when from __future__ import annotations
is active (#10362)Indexer
fails to identify continuation preceded by newline #10351 (#10354)Settings
display (#10370)C413
] Wrap expressions in parentheses when negating (#10346)pycodestyle
] Do not ignore lines before the first logical line in blank lines rules. (#10382)pycodestyle
] Do not trigger E225
and E275
when the next token is a ')' (#10315)pylint
] Avoid false-positive slot non-assignment for __dict__
(PLE0237
) (#10348)ruff.toml
format in README (#10393)RUF008
] Make it clearer that a mutable default in a dataclass is only valid if it is typed as a ClassVar (#10395)pylint
] Extend docs and test in invalid-str-return-type
(E307
) (#10400).
from check
and format
commands (#10217)with
item formatting for Python 3.8 or older (#10276)pyupgrade
] Allow fixes for f-string rule regardless of line length (UP032
) (#10263)pycodestyle
] Include actual conditions in E712 diagnostics (#10254)with
items formatting (#10274)Parameter
range for *args
and **kwargs
(#10283)typing.Annotated
subscripts as type definitions (#10285)pycodestyle
] Fix E301 not triggering on decorated methods. (#10117)pycodestyle
] Respect isort
settings in blank line rules (E3*
) (#10096)pycodestyle
] Make blank lines in typing stub files optional (E3*
) (#10098)pylint
] Implement singledispatch-method
(E1519
) (#10140)pylint
] Implement useless-exception-statement
(W0133
) (#10176)flake8-debugger
] Check for use of debugpy
and ptvsd
debug modules (#10177) (#10194)pyupgrade
] Generate diagnostic for all valid f-string conversions regardless of line length (UP032
) (#10238)pep8_naming
] Add fixes for N804
and N805
(#10215)ruff format --diff
(#10110)--config
and --isolated
global flags (#10150)--config
(#10219)required-version
(#10216)default-section
setting (#10149)CapWords
message (#10220)flake8-raise
] Avoid false-positives for parens-on-raise with future.exception()
(RSE102
) (#10206)pylint
] Add fix for unary expressions in PLC2801
(#9587)ruff
] Fix RUF028 not allowing # fmt: skip
on match cases (#10178)