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`
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