An extremely fast Python linter and code formatter, written in Rust.
This release introduces the new Ruff formatter 2024.2 style and adds a new lint rule to detect invalid formatter suppression comments.
flake8-bandit
] Remove suspicious-lxml-import (S410
) (#10154)pycodestyle
] Allow os.environ
modifications between imports (E402
) (#10066)pycodestyle
] Don't warn about a single whitespace character before a comma in a tuple (E203
) (#10094)eradicate
] Detect commented out case
statements (ERA001
) (#10055)eradicate
] Detect single-line code for try:
, except:
, etc. (ERA001
) (#10057)flake8-boolean-trap
] Allow boolean positionals in __post_init__
(#10027)flake8-copyright
] Allow © in copyright notices (#10065)isort
]: Use one blank line after imports in typing stub files (#9971)pylint
] New Rule dict-iter-missing-items
(PLE1141
) (#9845)pylint
] Ignore sys.version
and sys.platform
(PLR1714
) (#10054)pyupgrade
] Detect literals with unary operators (UP018
) (#10060)ruff
] Expand rule for list(iterable).pop(0)
idiom (RUF015
) (#10148)This release introduces the Ruff 2024.2 style, stabilizing the following changes:
with
parentheses when targeting Python 3.9 or newer (#9222)...
) in typing stub files (#9155)...
) body (#7440, #9240)extend
as part of a --config
flag (#10135)build
from the default exclusion list (#10093)ruff <path>
, ruff --explain
, ruff --clean
, and ruff --generate-shell-completion
in favor of ruff check <path>
, ruff rule
, ruff clean
, and ruff generate-shell-completion
(#10169)--format
from ruff rule
and ruff linter
(#10170)flake8-bugbear
] Avoid adding default initializers to stubs (B006
) (#10152)flake8-type-checking
] Respect runtime-required decorators for function signatures (#10091)pycodestyle
] Mark fixes overlapping with a multiline string as unsafe (W293
) (#10049)pydocstyle
] Trim whitespace when removing blank lines after section (D413
) (#10162)pylint
] Delete entire statement, including semicolons (PLR0203
) (#10074)ruff
] Avoid f-string false positives in gettext
calls (RUF027
) (#10118)ruff
crashing on PowerPC systems because of too small page size (#10080)line-length
option: fix link to pycodestyle.max-line-length
(#10136)Highlights include:
--preview
).--config
argument (e.g., --config "lint.isort.combine-as-imports=false"
).pycodestyle
] Add blank line(s) rules (E301
, E302
, E303
, E304
, E305
, E306
) (#9266)refurb
] Implement readlines_in_for
(FURB129
) (#9880)ruff
] Ensure closing parentheses for multiline sequences are always on their own line (RUF022
, RUF023
) (#9793)numpy
] Add missing deprecation violations (NPY002
) (#9862)flake8-bandit
] Detect mark_safe
usages in decorators (#9887)ruff
] Expand asyncio-dangling-task
(RUF006
) to include new_event_loop
(#9976)flake8-pyi
] Ignore 'unused' private type dicts in class scopes (#9952)indent-style=tabs
(#9915)preserve
mode (#9922)show-settings
filters directory-agnostic (#9866)DebugText
(#9953)flake8-simplify
] Avoid false positive with async
for loops (SIM113
) (#9996)flake8-trio
] Respect async with
in timeout-without-await
(#9859)perflint
] Catch a wider range of mutations in PERF101
(#9955)pycodestyle
] Fix E30X
panics on blank lines with trailing white spaces (#9907)pydocstyle
] Allow using parameters
as a subsection header (D405
) (#9894)pydocstyle
] Fix blank-line docstring rules for module-level docstrings (#9878)pylint
] Accept 0.0 and 1.0 as common magic values (PLR2004
) (#9964)pylint
] Avoid suggesting set rewrites for non-hashable types (#9956)ruff
] Avoid false negatives with string literals inside of method calls (RUF027
) (#9865)ruff
] Fix panic on with f-string detection (RUF027
) (#9990)ruff
] Ignore builtins when detecting missing f-strings (#9849)This release includes support for range formatting (i.e., the ability to format specific lines within a source file).
__get__
and __set__
from unnecessary-dunder-call
(#9791)Protocol
in ellipsis removal (#9841)C408
(#9822)C400
, C401
, C410
, and C418
(#9819)AhoCorasick
to speed up quote match (#9773)C405
and C409
(#9821)zero-sleep-call
(#9766)C403
(#9818)max-pos-args
example to max-positional-args
(#9797)weak_cryptographic_key.rs
(#9774)ANN
rules in changelog (#9771)max-positional-args
(#9838)Check out the blog post for a migration guide and overview of the changes!
NURSERY
selector cannot be used anymoreSee also, the "Remapped rules" section which may result in disabled rules.
The following rules are now deprecated:
missing-type-self
(ANN101
)missing-type-cls
(ANN102
)The following command line options are now deprecated:
--show-source
; use --output-format full
instead--no-show-source
; use --output-format concise
instead--output-format text
; use full
or concise
insteadThe following settings have moved and the previous name is deprecated:
ruff.allowed-confusables
→ ruff.lint.allowed-confusables
ruff.dummy-variable-rgx
→ ruff.lint.dummy-variable-rgx
ruff.explicit-preview-rules
→ ruff.lint.explicit-preview-rules
ruff.extend-fixable
→ ruff.lint.extend-fixable
ruff.extend-ignore
→ ruff.lint.extend-ignore
ruff.extend-per-file-ignores
→ ruff.lint.extend-per-file-ignores
ruff.extend-safe-fixes
→ ruff.lint.extend-safe-fixes
ruff.extend-select
→ ruff.lint.extend-select
ruff.extend-unfixable
→ ruff.lint.extend-unfixable
ruff.extend-unsafe-fixes
→ ruff.lint.extend-unsafe-fixes
ruff.external
→ ruff.lint.external
ruff.fixable
→ ruff.lint.fixable
ruff.flake8-annotations
→ ruff.lint.flake8-annotations
ruff.flake8-bandit
→ ruff.lint.flake8-bandit
ruff.flake8-bugbear
→ ruff.lint.flake8-bugbear
ruff.flake8-builtins
→ ruff.lint.flake8-builtins
ruff.flake8-comprehensions
→ ruff.lint.flake8-comprehensions
ruff.flake8-copyright
→ ruff.lint.flake8-copyright
ruff.flake8-errmsg
→ ruff.lint.flake8-errmsg
ruff.flake8-gettext
→ ruff.lint.flake8-gettext
ruff.flake8-implicit-str-concat
→ ruff.lint.flake8-implicit-str-concat
ruff.flake8-import-conventions
→ ruff.lint.flake8-import-conventions
ruff.flake8-pytest-style
→ ruff.lint.flake8-pytest-style
ruff.flake8-quotes
→ ruff.lint.flake8-quotes
ruff.flake8-self
→ ruff.lint.flake8-self
ruff.flake8-tidy-imports
→ ruff.lint.flake8-tidy-imports
ruff.flake8-type-checking
→ ruff.lint.flake8-type-checking
ruff.flake8-unused-arguments
→ ruff.lint.flake8-unused-arguments
ruff.ignore
→ ruff.lint.ignore
ruff.ignore-init-module-imports
→ ruff.lint.ignore-init-module-imports
ruff.isort
→ ruff.lint.isort
ruff.logger-objects
→ ruff.lint.logger-objects
ruff.mccabe
→ ruff.lint.mccabe
ruff.pep8-naming
→ ruff.lint.pep8-naming
ruff.per-file-ignores
→ ruff.lint.per-file-ignores
ruff.pycodestyle
→ ruff.lint.pycodestyle
ruff.pydocstyle
→ ruff.lint.pydocstyle
ruff.pyflakes
→ ruff.lint.pyflakes
ruff.pylint
→ ruff.lint.pylint
ruff.pyupgrade
→ ruff.lint.pyupgrade
ruff.select
→ ruff.lint.select
ruff.task-tags
→ ruff.lint.task-tags
ruff.typing-modules
→ ruff.lint.typing-modules
ruff.unfixable
→ ruff.lint.unfixable
The following rules have been remapped to new codes:
raise-without-from-inside-except
: TRY200
to B904
suspicious-eval-usage
: PGH001
to S307
logging-warn
: PGH002
to G010
static-key-dict-comprehension
: RUF011
to B035
runtime-string-union
: TCH006
to TCH010
The following rules have been stabilized and are no longer in preview:
trio-timeout-without-await
(TRIO100
)trio-sync-call
(TRIO105
)trio-async-function-with-timeout
(TRIO109
)trio-unneeded-sleep
(TRIO110
)trio-zero-sleep-call
(TRIO115
)unnecessary-escaped-quote
(Q004
)enumerate-for-loop
(SIM113
)zip-dict-keys-and-values
(SIM911
)timeout-error-alias
(UP041
)flask-debug-true
(S201
)tarfile-unsafe-members
(S202
)ssl-insecure-version
(S502
)ssl-with-bad-defaults
(S503
)ssl-with-no-version
(S504
)weak-cryptographic-key
(S505
)ssh-no-host-key-verification
(S507
)django-raw-sql
(S611
)mako-templates
(S702
)generator-return-from-iter-method
(PYI058
)runtime-string-union
(TCH006
)numpy2-deprecation
(NPY201
)quadratic-list-summation
(RUF017
)assignment-in-assert
(RUF018
)unnecessary-key-check
(RUF019
)never-union
(RUF020
)direct-logger-instantiation
(LOG001
)invalid-get-logger-argument
(LOG002
)exception-without-exc-info
(LOG007
)undocumented-warn
(LOG009
)Fixes for the following rules have been stabilized and are now available without preview:
triple-single-quotes
(D300
)non-pep604-annotation
(UP007
)dict-get-with-none-default
(SIM910
)in-dict-keys
(SIM118
)collapsible-else-if
(PLR5501
)if-with-same-arms
(SIM114
)useless-else-on-loop
(PLW0120
)unnecessary-literal-union
(PYI030
)unnecessary-spread
(PIE800
)error-instead-of-exception
(TRY400
)redefined-while-unused
(F811
)duplicate-value
(B033
)multiple-imports-on-one-line
(E401
)non-pep585-annotation
(UP006
)Fixes for the following rules have been promoted from unsafe to safe:
unaliased-collections-abc-set-import
(PYI025
)The following behaviors have been stabilized:
module-import-not-at-top-of-file
(E402
) allows sys.path
modifications between importsreimplemented-container-builtin
(PIE807
) includes lambdas that can be replaced with dict
unnecessary-placeholder
(PIE790
) applies to unnecessary ellipses (...
)if-else-block-instead-of-dict-get
(SIM401
) applies to if-else
expressionsrefurb
] Implement metaclass_abcmeta
(FURB180
) (#9658)blank_line_after_nested_stub_class
preview style (#9155)and-or-ternary
(PLR1706
) was removedflake8-async
] Take pathlib.Path
into account when analyzing async functions (#9703)flake8-return
] - fix indentation syntax error (RET505
) (#9705)RUF022
, RUF023
: never add two trailing commas to the end of a sequence (#9698)RUF023
: Don't sort __match_args__
, only __slots__
(#9724)flake8-simplify
] - Fix syntax error in autofix (SIM114
) (#9704)pylint
] Show verbatim constant in magic-value-comparison
(PLR2004
) (#9694)IfExp
with dual string arms in invalid-envvar-default
(#9734)pylint
] Add __mro_entries__
to known dunder methods (PLW3201
) (#9706)NURSERY
selector is used with --preview
(#9682)flake8-return
] Add fixes for all rules (RET505
, RET506
, RET507
, RET508
) (#9595)flake8-simplify
] Add fix for if-with-same-arms
(SIM114
) (#9591)pycodestyle
] Add fix for multiple-imports-on-one-line
(E401
) (#9518)pylint
] Add fix for collapsible-else-if
(PLR5501
) (#9594)pylint
] Add fix for useless-else-on-loop
(PLW0120
) (#9590)pylint
] Implement assigning-non-slot
(E0237
) (#9623)pylint
] Implement potential-index-error
(PLE0643
) (#9545)pylint
] Implement too-many-nested-blocks
(PLR1702
) (#9172)ruff
] Add rule to sort __slots__
and __match_args__
(#9564)ruff
] Detect unnecessary dict
comprehensions for iterables (RUF025
) (#9613)ruff
] Guard against use of default_factory
as a keyword argument (RUF026
) (#9651)ruff
] Implement mutable-fromkeys-value
(RUF024
) (#9597)--help
output (#9633)flake8-no-pep420
] Include global --config
when determining namespace packages (#9603)flake8-pie
] Omit bound tuples passed to .startswith
or .endswith
(#9661)flake8-return
] Avoid panic when fixing inlined else blocks (#9657)flake8-return
] Consider exception suppression in unnecessary assignment (#9673)flake8-return
] Take NoReturn
annotation into account when analyzing implicit returns (#9636)flake8-simplify
] Support inverted returns in needless-bool
(SIM103
) (#9619)flake8-type-checking
] Add Pydantic's BaseConfig
to default-copy list (#9650)flake8-type-checking
] Avoid marking InitVar
as a typing-only annotation (#9688)pycodestyle
] Allow dtype
comparisons in type-comparison
(#9676)pydocstyle
] Re-implement last-line-after-section
(D413
) (#9654)flake8-pytest-style
] Add fix safety documentation for duplicate-parameterize-test-cases
(#9678)pylint
] Document literal-membership
fix safety conditions (#9677)isort
] Fix reference to isort
rule code (#9598)flake8-bugbear
] Add fix for duplicate-value
(B033
) (#9510)flake8-simplify
] Implement enumerate-for-loop
(SIM113
) (#7777)pygrep_hooks
] Add fix for deprecated-log-warn
(PGH002
) (#9519)pylint
] Implement import-private-name
(C2701
) (#5920)refurb
] Implement regex-flag-alias
with fix (FURB167
) (#9516)ruff
] Add rule and fix to sort contents of __all__
(RUF022
) (#9474)tryceratops
] Add fix for error-instead-of-exception
(TRY400
) (#9520)flake8-pyi
] Fix PYI047
false negatives on PEP-695 type aliases (#9566)flake8-pyi
] Fix PYI049
false negatives on call-based TypedDict
s (#9567)pylint
] Exclude self
and cls
when counting method arguments (PLR0917
) (#9563)--show-settings
displays active settings in a far more readable format (#9464)--extension
support to the formatter (#9483)pycodestyle
] Use the configured tab size when expanding indents (#9506)flake8-simplify
] Avoid some more enumerate-for-loop
false positives (SIM113
) (#9515)pandas-vet
] Limit inplace diagnostics to methods that accept inplace (#9495)pylint
] Add the __prepare__
method to the list of recognized dunder method (#9529)pylint
] Ignore unnecessary dunder calls within dunder definitions (#9496)refurb
] Avoid bailing when reimplemented-operator
is called on function (FURB118
) (#9556)ruff
] Avoid treating named expressions as static keys (RUF011
) (#9494)noqa
with isort rules (#9555)cargo bench -p ruff_benchmark
(#9535)emacs-ruff-format
(#9403)flake8-blind-except
] Document exceptions to blind-except
rule (#9580)flake8-simplify
] Account for possibly-empty f-string values in truthiness logic (#9484)pylint
] Add the missing period in unnecessary-dunder-call
(#9485)pylint
] Fix __aenter__
message in unnecessary-dunder-call
(#9492)flake8-bandit
] Add ssl-with-no-version
(S504
) (#9384)flake8-bandit
] Implement ssl-insecure-version
(S502
) (#9390)flake8-bandit
] Implement ssl-with-bad-defaults
(S503
) (#9391)flake8-bandit
] Implement suspicious import rules (S4XX
) (#8831)flake8-simplify
] Implement zip-dict-keys-and-values
(SIM911
) (#9460)pyflakes
] Add a fix for redefined-while-unused
(F811
) (#9419)pylint
] Implement unnecessary-dunder-call
(C2801
) (#9166)ruff
] Add parenthesize-chained-operators
(RUF021
) to enforce parentheses in a or b and c
(#9440)flake8-boolean-trap
] Allow Boolean positional arguments in setters (#9429)flake8-builtins
] Restrict builtin-attribute-shadowing
(A003
) to actual shadowed references (#9462)flake8-pyi
] Add fix for generator-return-from-iter-method
(PYI058
) (#9355)pyflakes
] Don't flag redefined-while-unused
(F811
) in if
branches (#9418)pyupgrade
] Add some additional Python 3.12 typing members to deprecated-import
(#9445)ruff
] Add fix for parenthesize-chained-operators
(RUF021
) (#9449)ruff
] Include subscripts and attributes in static key rule (RUF011
) (#9416)ruff
] Support variable keys in static dictionary key rule (RUF011
) (#9411)# fmt: skip
with interspersed same-line comments (#9395)None
comparisons (#9376)DisplayParseError
for stdin parser errors (#9409)comment_ranges
for isort directive extraction (#9414)flake8-pyi
] Exclude warnings.deprecated
and typing_extensions.deprecated
arguments (#9423)flake8-pyi
] Fix false negative for unused-private-protocol
(PYI046
) with unused generic protocols (#9405)pydocstyle
] Disambiguate argument descriptors from section headers (#9427)pylint
] Homogenize PLR0914
message to match other PLR09XX
rules (#9399)ruff
] Allow Hashable = None
in type annotations (RUF013
) (#9442)dummy_implementations
preview style formatting (#9240)with
statements (#9222)flake8-pyi
] Implement generator-return-from-iter-method
(PYI058
) (#9313)pylint
] Implement empty-comment
(PLR2044
) (#9174)refurb
] Implement bit-count
(FURB161
) (#9265)ruff
] Add never-union
rule to detect redundant typing.NoReturn
and typing.Never
(#9217)asyncio-dangling-task
for nonlocal and global bindings (#9263)__str__
definitions from super classes (#9338)unused-noqa
via per-file-ignores
(#9300)typing_extensions
members as typing aliases (#9335)Display
for formatter parse errors (#9316)flake8-annotations
] Avoid adding return types to stub methods (#9277)flake8-annotations
] Respect mixed return
and raise
cases in return-type analysis (#9310)flake8-bandit
] Don't report violations when SafeLoader
is imported from yaml.loader
(S506
) (#9299)pylint
] Avoid panic when comment is preceded by Unicode (#9331)pylint
] Change PLR0917
error message to match other PLR09XX
messages (#9308)refurb
] Avoid false positives for math-constant
(FURB152
) (#9290)perflint
] Document PERF102
fix un-safety (#9351)pyupgrade
] Document UP007
fix un-safety (#9306)