refactor: replace black, isort and pylint with ruff - #353
Conversation
Merges the linting and formatting dependency groups into a single ruff==0.16.0 install, translates the old black/isort/pylint config into [tool.ruff]/[tool.ruff.lint], rewrites .pre-commit-config.yaml to use astral-sh/ruff-pre-commit, and swaps the CI lint/format jobs to ruff check/ruff format --check while preserving the existing required status check names.
There was a problem hiding this comment.
🟡 Not ready to approve
Ruff configuration and workflow naming/documentation have a few correctness/clarity issues that should be addressed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
Refactors the repository’s Python linting/formatting toolchain to consolidate on Ruff, updating dependency groups, pre-commit hooks, CI workflows, and documentation accordingly.
Changes:
- Replaces
black/isort/pylintwithruffinpyproject.tomldependency groups and tooling configuration. - Updates pre-commit hooks and GitHub Actions workflows to run
ruff check/ruff formatwhile preserving existing required status check names. - Removes legacy pylint configuration and updates README references/instructions to match the new tooling.
File summaries
| File | Description |
|---|---|
uv.lock |
Removes black/isort/pylint dependency tree and adds ruff. |
unittests/.pylintrc |
Deletes pylint-specific configuration no longer used. |
README.md |
Updates documentation and badges to reference Ruff instead of black/isort/pylint. |
pyproject.toml |
Replaces black/isort/pylint tool configuration with Ruff configuration and updates dependency groups. |
.pre-commit-config.yaml |
Switches pre-commit formatting/lint hooks to astral-sh/ruff-pre-commit. |
.github/workflows/pythonlint.yml |
Replaces pylint invocation with ruff check in the linting job matrix. |
.github/workflows/formatting.yml |
Keeps legacy check names but routes formatting/import-order checks through Ruff. |
Review details
- Files reviewed: 6/7 changed files
- Comments generated: 4
- Review effort level: Low
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
| - linter-env: linting | ||
| commands: | | ||
| uv run pylint src/mypackage | ||
| uv run pylint unittests --rcfile=unittests/.pylintrc | ||
| uv run ruff check src/mypackage unittests |
There was a problem hiding this comment.
Good catch, fixed in e08c2c0: renamed the job id from pylint to lint. Confirmed this is safe for branch protection — the required status check name comes from the job's explicit name: Python Code Quality and Lint field (plus the matrix suffix), not the YAML job id, so this doesn't touch the required-checks list.
| @@ -18,10 +18,8 @@ It doesn't contain any useful code but only a minimal working setup for a Python | |||
| - ready to use **Github Actions** for | |||
There was a problem hiding this comment.
Correct, but this is a pre-existing typo unrelated to the black/isort/pylint→ruff swap (that line never mentioned any of the removed tools). Per this migration's scope, I'm leaving it as a separate cosmetic follow-up rather than fixing it inline here.
| @@ -86,16 +84,15 @@ All paths mentioned in this section are relative to the repository root. | |||
|
|
|||
| 1. Open the folder with VS Code. | |||
| 2. **Select the python interpreter** ([official docs](https://code.visualstudio.com/docs/python/environments#_manually-specify-an-interpreter)) which is created by uv. Open the command pallett with `CTRL + P` and type `Python: Select Interpreter`. Select the interpreter which is placed in `.venv/Scripts/python.exe` under Windows or `.venv/bin/python` under Linux and macOS. | |||
There was a problem hiding this comment.
Same as the Github/GitHub comment above: this is a pre-existing typo unrelated to the tool swap this PR is about, so I'm leaving it out of scope rather than fixing it inline here.
| [tool.ruff] | ||
| line-length = 120 | ||
| target_version = ["py311", "py312", "py313", "py314"] | ||
| extend-exclude = ["*.md"] |
There was a problem hiding this comment.
Checked with uv run ruff check --show-settings src/mypackage/mymodule.py: ruff already resolves linter.unresolved_target_version = 3.11 / formatter.unresolved_target_version = 3.11 on its own, inferred from requires-python = ">=3.11" in [project]. So an explicit target-version in [tool.ruff] would be redundant, not a fix for a gap — same as how isort's line-length is inferred without extra config. Leaving it as-is.
The job id was a leftover from before the ruff migration - the job now runs ruff, mypy and codespell, not pylint. The job's explicit `name:` (not the YAML key) is what drives the required status check name, so this rename doesn't affect branch protection.
Summary
lintingdependency group down toruff==0.16.0only (dropspylint); drops the now-emptyformattinggroup (wasblack/isort).[tool.black]/[tool.isort]/[tool.pylint."MESSAGES CONTROL"]into[tool.ruff]/[tool.ruff.lint](line-length 120,select = ["E", "W", "F", "I", "UP", "B", "N", "PL", "RUF"], standardPLR0913/PLR0917/PLR0912/PLR0915/PLR2004ignores,extend-exclude = ["*.md"]soruff formatdoesn't touch fenced code blocks in docs).unittests/.pylintrc- none of its disables (too-few-public-methods,redefined-outer-name,duplicate-code) have a ruff equivalent to translate to, and we're not selecting pydocstyle (D) rules either..pre-commit-config.yaml: replacespsf/black+pycqa/isortwithastral-sh/ruff-pre-commit(tag verified to exist),ruff-checkscoped tosrc/mypackage+unittests(pylint's old scope),ruff-formatunscoped (black/isort's old scope).pythonlint.yml'slintingmatrix entry now runsruff check src/mypackage unittests.formatting.ymlkeeps itstool: [black, isort]matrix values (both are required status checks, confirmed via branch protection) but each now runs a real ruff command viamatrix.include, with an explicit jobname: "format (${{ matrix.tool }})"so the reported check names stay byte-identical.Test plan
ruff check src/mypackage unittests(pylint's old scope) - cleanruff format --check .(black/isort's old scope) - clean, confirmed*.mdis excluded via--verboseuv.lockdiff reviewed - only the pylint/black/isort transitive dep tree removed and ruff added, no unrelated version bumps🤖 Generated with Claude Code