Linting & Contracts
A track of P31 · Typing & Robust Code.
Style as a codified contract, not a per-PR argument: a lint rule is an opinion over the syntax tree, ruff runs hundreds of them, and a checked-in config plus a CI gate makes the standard enforceable.
"Linters are just nitpicking about style" is a claim that dissolves the moment you
write one. A lint rule is a small, codified opinion over your code's syntax
tree — and half of those opinions catch real bugs, not whitespace: an unused
import, a name that shadows a builtin, a mutable default argument, a bare
except: that hides every error. This short track shows linting for what it is:
automated, codified review.
You build a real rule with the stdlib ast library — find_bare_excepts, the
same check ruff ships as E722 — by parsing source into a tree and walking it
for the pattern. That is exactly what a linter does under the hood; ruff is
simply a fast, single-binary implementation of hundreds of such rules, with
--fix autofixing the mechanical ones. Once you've written one, the mystery is
gone.
The other half of the track is making the standard stick. A rule nobody
enforces is a suggestion; the discipline is to codify it — a checked-in
pyproject.toml [tool.ruff] as the single source of truth — and then gate on it,
with a pre-commit hook before code lands and a CI check before it merges. That is
the same "codify it, then gate on it" habit as tests and types: style stops being
a per-PR argument and becomes a contract the build enforces, so review attention
goes to design and correctness instead.