💻 Coding

Flake8, isort, and Black to Ruff Migration: pyproject.toml Config with Rule Mapping and a noqa Cleanup Plan

Move a Python repo from Flake8 plus plugins, isort, and Black to Ruff. Get a rule by rule mapping, a ready tool.ruff block for pyproject.toml, a pre-commit swap, and a plan for stale noqa comments so the first CI run is not a wall of new errors.

0.0
0Reviews
P
October 5, 2026

Prompt

Act as a Python platform engineer who has migrated several monorepos from Flake8, isort, and Black to Ruff. You keep lint behavior the team already agreed on, you say clearly where Ruff differs, and you never select rules nobody asked for.

Inputs:
- Current Flake8 config (setup.cfg, tox.ini, or .flake8 section, including select, ignore, extend-ignore, per-file-ignores, max-line-length, max-complexity): [Flake8Config]
- Flake8 plugins installed (for example flake8-bugbear, flake8-comprehensions, pep8-naming, flake8-docstrings): [Plugins]
- isort settings (profile, known_first_party, force_single_line, src paths): [IsortConfig]
- Black settings (line-length, target-version, skip-string-normalization): [BlackConfig]
- Lowest Python version the code must support: [PythonVersion]
- How lint runs today (pre-commit, CI job, Makefile, editor only): [CI]
- Output format: [Format]
- Language: [Lang]

Generate:
1. Rule mapping table. For every Flake8 code family and plugin, give the Ruff prefix (E, W, F, C90, B, C4, N, D, I, UP and so on), whether Ruff implements it, and the gap if it does not (for example W503 and W504 are not implemented, E203 is preview only). Note that Flake8 selects E, F, W, C90 by default while Ruff defaults to E4, E7, E9, F, so the select list must be explicit.
2. The pyproject.toml block. Write the tool.ruff table with line-length and target-version taken from BlackConfig and PythonVersion, the tool.ruff.lint table with select, ignore, and per-file-ignores translated from Flake8Config, a tool.ruff.lint.mccabe table if max-complexity exists, a tool.ruff.lint.isort table translated from IsortConfig, a tool.ruff.lint.pydocstyle convention if D is selected, and a tool.ruff.format table matching BlackConfig. Write the TOML table headers in normal square bracket syntax in your answer.
3. Formatter conflict check. List any selected rules Ruff recommends disabling when ruff format is used (for example W191, E111, E114, E117, D206, D300, COM812, ISC001) and drop them.
4. Tool swap. Show the removed pre-commit hooks or CI steps and the new ones using the astral-sh/ruff-pre-commit repo with the ruff hook (args set to --fix) placed before ruff-format. Leave rev as a placeholder to pin.
5. noqa cleanup plan. Explain how to find stale suppressions with RUF100, how to rewrite plugin codes that changed, and when to use ruff check --add-noqa for a baseline instead of fixing everything in one PR.
6. Rollout order: one commit for config, one for ruff format churn (add it to .git-blame-ignore-revs), one for autofixes, then remove the old tools.

Constraints:
- Valid TOML only. Do not add rule prefixes that are not traceable to Flake8Config, Plugins, or IsortConfig.
- If a Flake8 plugin has no Ruff equivalent, say so and keep it out of the config rather than guessing a prefix.
- Do not invent version numbers for Ruff or hooks.
- No em dashes.

Instructions

Replace every [bracket] with your details before running. Works on ChatGPT, Claude, and Gemini.

Generated Output

This image was generated using the prompt above.

Flake8, isort, and Black to Ruff Migration: pyproject.toml Config with Rule Mapping and a noqa Cleanup Plan - Result

Examples

Example Input

Flake8Config: [flake8] max-line-length = 100, extend-ignore = E203, W503, max-complexity = 12, per-file-ignores = tests/*: S101, __init__.py: F401
Plugins: flake8-bugbear, flake8-comprehensions, flake8-bandit (only S101 is suppressed, nothing else from it is used), pep8-naming
IsortConfig: profile = black, known_first_party = ledgerline, src_paths = src, tests
BlackConfig: line-length = 100, target-version = py310
PythonVersion: 3.10
CI: pre-commit in GitHub Actions with black, isort, and flake8 hooks
Format: mapping table, then TOML, then steps
Lang: English

Example Output

1. Rule mapping
| Flake8 source | Ruff | Status |
| pycodestyle E, W | E, W | implemented; W503 not implemented, E203 preview only, so both ignores can go |
| pyflakes F | F | implemented |
| mccabe C901, max-complexity 12 | C90 + mccabe.max-complexity | implemented |
| flake8-bugbear | B | implemented |
| flake8-comprehensions | C4 | implemented |
| pep8-naming | N | implemented |
| flake8-bandit | S | implemented, but you only use it to silence S101, so S is not selected |
| isort | I | implemented as lint rule I001, fixed by ruff check --fix |

2. pyproject.toml
[tool.ruff]
line-length = 100
target-version = "py310"
src = ["src", "tests"]

[tool.ruff.lint]
select = ["E", "W", "F", "C90", "B", "C4", "N", "I"]
ignore = ["W191"]

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]

[tool.ruff.lint.mccabe]
max-complexity = 12

[tool.ruff.lint.isort]
known-first-party = ["ledgerline"]

[tool.ruff.format]
quote-style = "double"

Why tests/*: S101 is gone: S is not selected, so the ignore would be dead config. profile = black needs no translation; Ruff's isort defaults already match Black.

3. Formatter conflicts
From your select list, W191 (tab indentation) overlaps with ruff format, so it is ignored above. E111, E114, and E117 are preview rules in Ruff and stay inactive unless you enable preview, so they need no entry. If you later add COM or ISC, ignore COM812 and ISC001.

4. pre-commit swap
Remove: psf/black, pycqa/isort, pycqa/flake8 (and the flake8 additional_dependencies list).
Add:
- repo: https://github.com/astral-sh/ruff-pre-commit
  rev: <pin the Ruff version you install>
  hooks:
    - id: ruff
      args: [--fix]
    - id: ruff-format
The lint hook runs first so import sorting fixes land before formatting.

5. noqa cleanup
- Run ruff check --extend-select RUF100 once to list suppressions that no longer match a real violation, then remove them with --fix.
- Search for noqa: S101 in src/; with S unselected these are now stale and RUF100 will flag them.
- If B or N produce more hits than one PR can absorb, run ruff check --add-noqa to write a baseline, merge, then delete the baseline comments file by file.

6. Rollout
Commit 1: pyproject.toml block and pre-commit swap.
Commit 2: ruff format . alone; add its hash to .git-blame-ignore-revs.
Commit 3: ruff check --fix . (import order, comprehension rewrites).
Commit 4: delete .flake8, isort, and Black from dev dependencies once CI is green.

Reviews (0)

Please login to leave a review.
Loading reviews...