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.

A rule over the ASTyou build E722 with astruffhundreds of rules, fast, autofixChecked-in configone source of truthPre-commit + CI gateenforceable, not aspirational
Style as a codified, gated contract - like tests and types.