Practical guide to the modern Python quality stack: what to use, how to configure, how to enforce in CI.
The 2026 Stack
| Layer |
Tool |
Role |
| Linter + Formatter |
Ruff |
Replaces Flake8, Black, isort, bandit, pyupgrade (900+ rules, Rust speed) |
| Type checker |
mypy |
Static type analysis (strict mode in CI) |
| Type checker (IDE) |
Pyright / Pylance |
Real-time feedback in VS Code |
| Strict style |
wemake-python-styleguide |
Flake8 plugin, complements Ruff (WPS rules) |
| Pre-commit |
pre-commit |
Run all checks on git commit |
| Test coverage |
pytest-cov + coverage.py |
Line + branch coverage measurement |
| Mutation testing |
pytest-gremlins / cosmic-ray |
Verify test assertions actually catch bugs |
Section Map
| File |
Topics |
| 01 Ruff: Linting & Formatting |
Install, configure, rule sets, auto-fix, format, CI |
| 02 Type Checkers |
mypy strict, pyright, wemake-python-styleguide |
| 03 Pre-Commit Hooks |
Setup, hook ordering, CI integration |
| 04 Test Coverage |
pytest-cov, branch coverage, mutation testing |
| 05 Config Template |
Copy-paste pyproject.toml + .pre-commit-config.yaml |
Quick Start
uv add --dev ruff mypy pytest-cov
uv run ruff check . --fix && uv run ruff format .
uv run mypy .
uv run pytest --cov=src --cov-branch --cov-fail-under=100
Golden Rules
- Ruff replaces Flake8 + Black + isort for most teams (keep Flake8 only if you use WPS rules).
- Run
ruff check before ruff format (linter may auto-fix code that needs reformatting).
- Use
mypy --strict in CI; Pyright in IDE for instant feedback.
- Enforce 100% coverage gate in CI with
--cov-fail-under=100.
- Line coverage alone is not enough — consider mutation testing for critical paths.
- Pre-commit hooks = last safety net before code reaches the repo.
See also