Skip to content

Releases: astral-sh/ruff

v0.4.3

03 May 23:14
1e91a09
Compare
Choose a tag to compare

Changes

Enhancements

  • Add support for PEP 696 syntax (#11120)

Preview features

  • [refurb] Use function range for reimplemented-operator diagnostics (#11271)
  • [refurb] Ignore methods in reimplemented-operator (FURB118) (#11270)
  • [refurb] Implement fstring-number-format (FURB116) (#10921)
  • [ruff] Implement redirected-noqa (RUF101) (#11052)
  • [pyflakes] Distinguish between first-party and third-party imports for fix suggestions (#11168)

Rule changes

  • [flake8-bugbear] Ignore non-abstract class attributes when enforcing B024 (#11210)
  • [flake8-logging] Include inline instantiations when detecting loggers (#11154)
  • [pylint] Also emit PLR0206 for properties with variadic parameters (#11200)
  • [ruff] Detect duplicate codes as part of unused-noqa (RUF100) (#10850)

Formatter

  • Avoid multiline expression if format specifier is present (#11123)

LSP

  • Write ruff server setup guide for Helix (#11183)
  • ruff server no longer hangs after shutdown (#11222)
  • ruff server reads from a configuration TOML file in the user configuration directory if no local configuration exists (#11225)
  • ruff server respects per-file-ignores configuration (#11224)
  • ruff server: Support a custom TOML configuration file (#11140)
  • ruff server: Support setting to prioritize project configuration over editor configuration (#11086)

Bug fixes

  • Avoid debug assertion around NFKC renames (#11249)
  • [pyflakes] Prioritize redefined-while-unused over unused-import (#11173)
  • [ruff] Respect async expressions in comprehension bodies (#11219)
  • [pygrep_hooks] Fix blanket-noqa panic when last line has noqa with no newline (PGH004) (#11108)
  • [perflint] Ignore list-copy recommendations for async for loops (#11250)
  • [pyflakes] Improve invalid-print-syntax documentation (#11171)

Performance

  • Avoid allocations for isort module names (#11251)
  • Build a separate ARM wheel for macOS (#11149)

Contributors

v0.4.2

25 Apr 17:55
77c93fd
Compare
Choose a tag to compare

Changes

Rule changes

  • [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)

Server

  • Fix an issue with missing diagnostics for Neovim and Helix (#11092)
  • Implement hover documentation for noqa codes (#11096)
  • Introduce common Ruff configuration options with new server settings (#11062)

Bug fixes

  • Use 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)

Documentation

  • [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)

Performance

  • Use matchit to resolve per-file settings (#11111)

Contributors

v0.4.1

19 Apr 12:32
0ff25a5
Compare
Choose a tag to compare

Changes

Preview features

  • [pylint] Implement invalid-hash-returned (PLE0309) (#10961)
  • [pylint] Implement invalid-index-returned (PLE0305) (#10962)

Bug fixes

  • [pylint] Allow NoReturn-like functions for __str__, __len__, etc. (PLE0307) (#11017)
  • Parser: Use empty range when there's "gap" in token source (#11032)
  • [ruff] Ignore stub functions in unused-async (RUF029) (#11026)
  • Parser: Expect indented case block instead of match stmt (#11033)

Contributors

v0.4.0

18 Apr 19:53
e751b4e
Compare
Choose a tag to compare

Changes

A new, hand-written parser

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.

A new language server in Rust

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:

  • Lints Python files automatically and shows quick-fixes when available
  • Formats Python files, with support for range formatting
  • Comes with commands for quickly performing actions: ruff.applyAutofix, ruff.applyFormat, and ruff.applyOrganizeImports
  • Supports source.fixAll and source.organizeImports source actions
  • Automatically reloads your project configuration when you change it

To setup ruff server with your editor, refer to the README.md.

Preview features

  • [pycodestyle] Do not trigger E3 rules on defs 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)

Rule changes

  • [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)

Linter

  • Improve handling of builtin symbols in linter rules (#10919)
  • Improve display of rules in --show-settings (#11003)
  • Improve inference capabilities of the BuiltinTypeChecker (#10976)
  • Resolve classes and functions relative to script name (#10965)
  • Improve performance of RuleTable::any_enabled (#10971)

Server

This section is devoted to updates for our new language server, written in Rust.

  • Enable ruff-specific source actions (#10916)
  • Refreshes diagnostics for open files when file configuration is changed (#10988)
  • Important errors are now shown as popups (#10951)
  • Introduce settings for directly configuring the linter and formatter (#10984)
  • Resolve configuration for each document individually (#10950)
  • Write a setup guide for Neovim (#10987)

Configuration

  • Add RUFF_OUTPUT_FILE environment variable support (#10992)

Bug fixes

  • Avoid non-augmented-assignment for reversed, non-commutative operators (PLR6104) (#10909)
  • Limit commutative non-augmented-assignments to primitive data types (PLR6104) (#10912)
  • Respect per-file-ignores for RUF100 on blanket # noqa (#10908)
  • Consider if expression for parenthesized with items parsing (#11010)
  • Consider binary expr for parenthesized with items parsing (#11012)
  • Reset FOR_TARGET context for all kinds of parentheses (#11009)

Contributors

v0.3.7

12 Apr 03:55
2e37cf6
Compare
Choose a tag to compare

Changes

Preview features

  • [flake8-bugbear] Implement loop-iterator-mutation (B909) (#9578)
  • [pylint] Implement rule to prefer augmented assignment (PLR6104) (#9932)

Bug fixes

  • Avoid TOCTOU errors in cache initialization (#10884)
  • [pylint] Recode nan-comparison rule to W0177 (#10894)
  • [pylint] Reverse min-max logic in if-stmt-min-max (#10890)

Contributors

v0.3.6

11 Apr 16:29
4e8a846
Compare
Choose a tag to compare

Changes

Preview features

  • [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)

Rule changes

  • [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.NamedTuples 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)

CLI

  • Support FORCE_COLOR env var (#10839)

Configuration

  • Support negated patterns in [extend-]per-file-ignores (#10852)

Bug fixes

  • [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)
  • Respect # noqa directives on __all__ openers (#10798)

Contributors

v0.3.5

01 Apr 17:41
200ebee
Compare
Choose a tag to compare

Changes

Preview features

  • [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)

Rule changes

  • [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)

Configuration

  • Respected nested namespace packages (#10541)
  • [flake8-boolean-trap] Add setting for user defined allowed boolean trap (#10531)

Bug fixes

  • Correctly handle references in __all__ definitions when renaming symbols in autofixes (#10527)
  • Track ranges of names inside __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)

Documentation

  • Add PR title format to CONTRIBUTING.md (#10665)
  • Fix list markup to include blank lines required (#10591)
  • Put 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)

Contributors

v0.3.4

23 Mar 13:29
5062572
Compare
Choose a tag to compare

Changes

Preview features

  • [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)

Rule changes

  • [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)

Formatter

  • Fix unstable formatting for trailing subscript end-of-line comment (#10492)

Bug fixes

  • Avoid code comment detection in PEP 723 script tags (#10464)
  • Avoid incorrect tuple transformation in single-element case (C409) (#10491)
  • Bug fix: Prevent fully defined links name from being reformatted (#10442)
  • Consider raw source code for W605 (#10480)
  • Docs: Link inline settings when not part of options section (#10499)
  • Don't treat annotations as redefinitions in .pyi files (#10512)
  • Fix E231 bug: Inconsistent catch compared to pycodestyle, such as when dict nested in list (#10469)
  • Fix pylint upstream categories not showing in docs (#10441)
  • Add missing Options references to blank line docs (#10498)
  • 'Revert "F821: Fix false negatives in .py files when from __future__ import annotations is active (#10362)"' (#10513)
  • Apply NFKC normalization to unicode identifiers in the lexer (#10412)
  • Avoid failures due to non-deterministic binding ordering (#10478)
  • [flake8-bugbear] Allow tuples of exceptions (B030) (#10437)
  • [flake8-quotes] Avoid syntax errors due to invalid quotes (Q000, Q002) (#10199)

Contributors

v0.3.3

15 Mar 18:13
608df9a
Compare
Choose a tag to compare

Changes

Preview features

  • [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)

Rule changes

  • [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)

CLI

  • Add message on success to ruff check (#8631)

Bug fixes

  • [PIE970] Allow trailing ellipsis in typing.TYPE_CHECKING (#10413)
  • Avoid TRIO115 if the argument is a variable (#10376)
  • [F811] Avoid removing shadowed imports that point to different symbols (#10387)
  • Fix F821 and F822 false positives in .pyi files (#10341)
  • Fix F821 false negatives in .py files when from __future__ import annotations is active (#10362)
  • Fix case where Indexer fails to identify continuation preceded by newline #10351 (#10354)
  • Sort hash maps in Settings display (#10370)
  • Track conditional deletions in the semantic model (#10415)
  • [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)
  • Gate f-string struct size test for Rustc < 1.76 (#10371)

Documentation

  • Use 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)
  • Remove . from check and format commands (#10217)

Contributors

v0.3.2

09 Mar 01:24
a892fc7
Compare
Choose a tag to compare

Changes

Preview features

  • Improve single-with item formatting for Python 3.8 or older (#10276)

Rule changes

  • [pyupgrade] Allow fixes for f-string rule regardless of line length (UP032) (#10263)
  • [pycodestyle] Include actual conditions in E712 diagnostics (#10254)

Bug fixes

  • Fix trailing kwargs end of line comment after slash (#10297)
  • Fix unstable with items formatting (#10274)
  • Avoid repeating function calls in f-string conversions (#10265)
  • Fix E203 false positive for slices in format strings (#10280)
  • Fix incorrect Parameter range for *args and **kwargs (#10283)
  • Treat typing.Annotated subscripts as type definitions (#10285)

Contributors