Ruff v0.13.0 is available now! Install it from PyPI, or with your package manager of choice:

uv tool install ruff@latest

As a reminder: Ruff is an extremely fast Python linter and formatter, written in Rust. Ruff can be used to replace Black, Flake8 (plus dozens of plugins), isort, pydocstyle, pyupgrade, and more, all while executing tens or hundreds of times faster than any individual tool.

Migrating to v0.13

Ruff v0.13 has only a few breaking changes, and most users should expect to upgrade without any updates to their code or configuration. A few of the possible exceptions are described in more detail below.

Several rules can now add from __future__ import annotations automatically

Some rules that behave differently when annotations are not evaluated at runtime can now add a __future__ import as part of their fixes.

Adding from __future__ import annotations to a Python file enables PEP-563 deferred annotations. Deferring annotations in this way allows for a few common patterns, such as avoiding the overhead of an expensive import or enabling recursive type definitions. Several Ruff rules, namely TC001, TC002, TC003, RUF013, and UP037, can take advantage of this to offer different fixes in the presence of deferred annotations. For the TC rules, this means that more imports can be moved into TYPE_CHECKING blocks, while UP037 can unquote more annotations, and RUF013 can use PEP-604 unions (e.g. str | int) on Python versions before 3.10.

This behavior can be enabled via the new lint.future-annotations setting, which is still off by default. Note also that other UP rules like UP006, UP007, and UP045 do not yet use this new functionality. Instead, they still rely on the use of FA100 to add the __future__ import.

Full module paths are now used to verify first-party modules

Ruff now checks that the full path to a module exists on disk before categorizing it as a first-party import.

For example, import foo.bar.baz will only be marked as first-party if foo/bar/baz is a directory, or foo/bar is a directory containing baz.py or baz.pyi. This change makes first-party import detection more accurate, helping to avoid false positives on local directories with the same name as a third-party dependency, for example. This change most often affects import sorting rules like I001, but a few other rules like TC001, TC002, and TC003 rely on this import categorization too.

See the FAQ section on import categorization for more details.

Deprecated rules must now be selected by exact rule code

Ruff will no longer activate deprecated rules selected by their group name or prefix.

On Ruff v0.12, selecting a group of rules with their prefix, such as the pyupgrade rules with UP, would activate both the stable and deprecated rules. Starting with v0.13, this is no longer the case. Deprecated rules must be selected with their full rule code. Sticking with the UP example, a selection like this would be required to select all of the UP rules, including the deprecated UP0381:

ruff check my_code.py --select UP,UP038

This builds on a change from Ruff v0.5, where the special ALL rule selector was updated to exclude deprecated rules. This change should help to prevent new users from activating deprecated rules by mistake and also surface deprecation warnings earlier to make future breaking changes smoother for everyone.

The deprecated macOS configuration directory fallback has been removed

Ruff will no longer look for a user-level configuration file at ~/Library/Application Support/ruff/ruff.toml on macOS.

This feature was deprecated in favor of using the XDG specification (usually resolving to ~/.config/ruff/ruff.toml), like on Linux. That deprecation also took place in v0.5, when the XDG directory was made the default, and a warning was added if files were found in ~/Library/Application Support. The fallback and warning have now been removed.

Rule stabilizations

The following rules have been stabilized and are no longer in preview:

Other behavior stabilizations

This release also stabilizes some additional behavior, previously only available in preview mode:

Rule removals

  • pandas-df-variable-name (PD901) has been removed. It was deprecated in v0.12 because it was highly opinionated and less likely to be useful than the other PD rules.
  • non-pep604-isinstance (UP038) has also been removed. It was deprecated in v0.10 because the PEP 604 union syntax in isinstance and issubclass calls is not actually idiomatic and may also hurt performance. See this issue and its references for more details.

See the full changelog on GitHub for other, smaller changes.

Thank you!

Thank you to everyone who provided feedback regarding the changes included in Ruff's preview mode and to our contributors. It's an honor building Ruff with you!


View the full changelog on GitHub.

Read more about Astral — the company behind Ruff.

Footnotes

  1. This example won't actually work on Ruff v0.13 because UP038 has also been removed. In fact, all of the previously-deprecated rules have now been removed, but this feature should still be helpful in the future if we need to deprecate more rules.