Files
ruff/python/ruff-ecosystem
Brent Westbrook aad0e909ef Allow rules without codes (#28049)
Summary
--

This PR allows adding rules that only belong to categories and only have
names rather than requiring
a linter group and code.

The first non-empty commit uses `Rule::name` instead of
`Rule::noqa_code` throughout the linter tests, causing a huge number of
file renames without changes.

The second commit updates `FixTable` from a mapping of `SecondaryCode ->
(name, fix_count)` to
`DiagnosticId -> (Option<SecondaryCode>, fix_count)`. This doesn't
really change its usage but
involves minor diffs to a substantial number of lines. It also allows us
to drop some of the special
`hashbrown` handling and the `hashbrown` dependency in `ruff_linter`,
which is nice.

The third commit contains the bulk of the change, including the macro
changes needed to support
`map_codes` entries like that for the `pytest-fixture-autouse` rule in
the fourth commit:

```rust
() => rules::ruff::rules::PytestFixtureAutouse,
```

These changes are pretty mechanical overall, just handling cases where
the linter or noqa code could
be missing, which fortunately seemed pretty straightforward in every
case.

The fourth commit takes advantage of these changes to reinstate `RUF076`
as our first purely
`pedantic` rule. I'm happy to drop that if it's too controversial or
opens too many questions about
the previously-removed rule and its code, but I thought it was nice to
have a motivating example. We
moved this rule from `preview` to `removed` because it was too pedantic
for the `RUF` category, even
in preview, so it's exactly the kind of rule we can support now with the
categories.

Finally, the fifth commit updates the contributing docs to reflect that
linters and codes are
optional. This may need to be adjusted if we back out the `RUF076`
change.

Test Plan
--

Existing tests, plus a few new ones for `pytest-fixture-autouse`
2026-08-27 11:26:35 -04:00
..

ruff-ecosystem

Compare lint and format results for two different ruff versions (e.g. main and a PR) on real world projects.

Installation

From the Ruff project root, install with uv:

uv tool install -e ./python/ruff-ecosystem

Usage

ruff-ecosystem <check | format> <baseline executable> <comparison executable>

Note executable paths may be absolute, relative to the current working directory, or will be looked up in the current Python environment and PATH.

Run ruff check ecosystem checks comparing your debug build to your system Ruff:

ruff-ecosystem check ruff "./target/debug/ruff"

Run ruff format ecosystem checks comparing your debug build to your system Ruff:

ruff-ecosystem format ruff "./target/debug/ruff"

Run ruff format ecosystem checks comparing with changes to code that is already formatted:

ruff-ecosystem format ruff "./target/debug/ruff" --format-comparison ruff-then-ruff

Run ruff format ecosystem checks comparing with the Black formatter:

ruff-ecosystem format black ruff -v --cache python/checkouts --format-comparison black-and-ruff

The default output format is markdown, which includes nice summaries of the changes. You can use --output-format json to display the raw data — this is particularly useful when making changes to the ecosystem checks.

Development

When developing, it can be useful to set the --pdb flag to drop into a debugger on failure:

ruff-ecosystem check ruff "./target/debug/ruff" --pdb

You can also provide a path to cache checkouts to speed up repeated runs:

ruff-ecosystem check ruff "./target/debug/ruff" --cache ./repos