Essential Lint Rules
Not every lint rule earns its CI time. These rule sets catch real bugs and style drift with minimal false positives for Python 3.14 projects.
Search across all documentation pages
Not every lint rule earns its CI time. These rule sets catch real bugs and style drift with minimal false positives for Python 3.14 projects.
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM", "RUF", "S", "T20"]
ignore = ["E501", "S101"] # line length via formatter; assert ok in testsWhen to reach for this:
# Violations caught by essential rules:
import os, sys # I: unsorted imports
x = 1 # F841: unused variable (F)
eval("1+1") # S307: dangerous eval (S)
print("debug") # T20: print statement (T20)
class unused: ... # F: defined but never useduv run ruff check example.py
# I001 Import block is un-sorted
# F841 Local variable `x` is assigned but never used
# S307 Use of possibly insecure function
# T201 `print` foundWhat this demonstrates:
I catches import disorder before reviewF catches dead code and undefined namesS (bandit) flags security anti-patternsT20 catches leftover debug prints| Tier | Rules | Purpose |
|---|---|---|
| Core | E, F, I, UP | Style, bugs, imports, syntax upgrades |
| Quality | B, SIM, RUF | Bugbear, simplification, ruff-specific |
| Security | S (bandit) | SQL injection, eval, hardcoded secrets |
| Hygiene | T20, PT | No print in prod; pytest best practices |
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101"] # allow assert in tests
"migrations/**" = ["E", "F"] # skip lint on Django migrationsselect = ["ALL"]) - hundreds of false positives. Fix: start with the core set; add rules incrementally.assert. Fix: per-file ignore for tests/**.target-version to requires-python.scripts/ or CLI entry points.| Alternative | Use When | Don't Use When |
|---|---|---|
| Minimal (E, F only) | Very early prototype | Production code |
| Full ALL | Security-critical systems | Small teams without lint budget |
| pylint | Deep analysis | Speed-critical CI |
At minimum: E, F, I, UP. Add B and SIM for quality, S for security-sensitive code.
ruff rule B006 prints the rule description and examples.
Ruff has flake8-type-checking (TCH) rules. Useful but can be noisy. Prefer mypy/pyright for types.
Enable new rules, run ruff check --fix, commit fixes, then add to CI.
Ruff-native rules for patterns other plugins miss (ambiguous Unicode, invalid pyproject.toml).
Yes. Allow assert (S101), print for debugging, and magic values (PLR2004) in tests.
Add to ignore = ["RULE"] in [tool.ruff.lint].
No in ruff. They are fast and high-value for web apps and CLIs handling user input.
Enable DJ (flake8-django) for Django projects. Skip for FastAPI/Flask.
When upgrading ruff. Review the changelog for new high-value rules each quarter.
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026