diff options
| author | user <user@clank> | 2026-08-17 14:35:59 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-17 14:35:59 +0200 |
| commit | b1fe06633d68ec611d0b1269f4c95db82ac456f5 (patch) | |
| tree | 4059660e61805eaec6db011e3229a48cb0c26d7a /ruff.toml | |
| parent | sl0ppty: let git blame walk past the reformat (diff) | |
| download | slosh-b1fe06633d68ec611d0b1269f4c95db82ac456f5.tar.gz slosh-b1fe06633d68ec611d0b1269f4c95db82ac456f5.tar.xz slosh-b1fe06633d68ec611d0b1269f4c95db82ac456f5.zip | |
sl0ppty: ruff formats the Python, and sorts its imports
The other half of the pre-commit hook. C goes through clang-format, Python through
ruff: `ruff check --select I --fix` to sort the imports, then `ruff format` to lay
them out. `make fmt` does both, `make fmt-check` reports, `make hooks` installs it.
ruff rather than black because it is one static binary instead of a Python
dependency chain, and fast enough that a hook is free. Its formatter is
black-compatible, so this is the ecosystem's formatting rather than a dialect --
measured at 9,935 changed lines against black's 9,953, which is the same answer.
**Left entirely at the defaults**, which is the opposite of what `.clang-format`
does. That file argues with LLVM in five places because the C here was
hand-formatted into a house style worth keeping. The Python was not, and a
formatter of this kind is only worth having when there is nothing left to argue
about: every knob turned is an argument somebody has to have again later. 88
columns, double quotes, ruff's own line breaking.
**Import sorting is on, and C include sorting stays off.** Not an inconsistency: a
C include order can be load-bearing -- `_GNU_SOURCE` ahead of the system headers,
and a grouping somebody wrote by hand -- while Python import order is not. Where it
genuinely is, a statement between imports ends the block ruff will sort, and the
test files lean on exactly that:
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from harness import Session, check, report
`from harness import` cannot be hoisted above the line that makes it importable,
because the `sys.path.insert` between them is a barrier. Verified before touching
anything, since getting it wrong would have broken every test in the suite at once.
Two details in the hook worth naming. `--select I` is passed on the command line as
well as set in `ruff.toml`, so a stray `select` in somebody's own config cannot
turn a formatting hook into a linter that refuses a commit over an unused variable.
And the two tools are named together when either is missing, so setting up a
machine installs both at once instead of finding the second one on the next commit.
`set -e` and `[ -n "$c_files" ] && clang-format ...` do not mix: when the list is
empty the AND-list returns non-zero and the shell exits, so a Python-only commit
would have aborted with no message at all. They are `if` blocks. Found by testing
the case rather than by reading it.
Verified in a scratch clone, seven paths: Python alone, C alone, both in one
commit, imports sorted with the `sys.path` barrier intact, a `contrib/` script that
is Python with no extension on it, a partly staged Python file refused with `HEAD`
unchanged, and a commit with no code in it drawing no comment.
Diffstat (limited to 'ruff.toml')
| -rw-r--r-- | ruff.toml | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..32112bd --- /dev/null +++ b/ruff.toml @@ -0,0 +1,36 @@ +# How the Python in this tree is formatted, and how its imports are ordered. +# `make fmt` applies both, `make fmt-check` asks, and the pre-commit hook in +# `.githooks/` does it for what you staged (`make hooks`). +# +# ruff rather than black: it is one static binary instead of a Python dependency +# chain, it is fast enough that a pre-commit hook is free, and its formatter is +# black's output -- so this is the ecosystem's formatting, not a dialect of it. +# +# Unlike the C side, this is left at the defaults. `.clang-format` argues with +# LLVM in five places because the C here was hand-formatted into a house style +# worth keeping; the Python was not, and a formatter of this kind is only worth +# having if there is nothing left to argue about. Every knob turned here is an +# argument somebody has to have again later. + +target-version = "py39" +line-length = 88 + +# The vendored terminal core is somebody else's tree, pinned by commit (D12), and +# `.scratch/` is where experiments go to be untidy in peace. +extend-exclude = ["vendor", ".scratch"] + +[lint] +# Import sorting, and nothing else. `ruff check` can enforce a great deal more and +# one day it might, but this hook's job is formatting: one that also refused a +# commit over an unused variable would be a different feature, and not one anybody +# asked for. +# +# Sorting imports is safe here in a way sorting C includes is not -- which is why +# `.clang-format` says `SortIncludes: Never` and this does the opposite. A C +# include order can be load-bearing (`_GNU_SOURCE` before the system headers, and +# a grouping somebody wrote by hand); Python import order is not, and where it +# genuinely is, a statement between the imports ends the block ruff will sort. The +# test files rely on exactly that: `sys.path.insert(...)` sits between the standard +# library and `from harness import ...`, so the harness import cannot be hoisted +# above the line that makes it importable. +select = ["I"] |
