Summary
The 29 Python scripts in utils/ are reached by no lint, format or
type gate. They are the scripts that gate everything else — the gates are
themselves ungated.
Where the scoping excludes them
.pre-commit-config.yaml:26-30 — both ruff-check and ruff-format
carry files: ^big-code-analysis-py/.*\.py$.
Makefile — py-lint / py-fmt-check run ruff over $(BCA_PY_DIR)
(big-code-analysis-py) and $(SMOKE_PY_DIR) (scripts/smoke) only;
py-typecheck runs mypy --strict python tests examples $(SMOKE_LIB_PY)
from inside big-code-analysis-py.
utils/ is in none of those paths.
Measured
Using the bindings crate's own ruff and config
(big-code-analysis-py/.venv/bin/ruff --config big-code-analysis-py/pyproject.toml):
| Check |
Result |
ruff check utils |
835 errors |
ruff format --check utils |
27 of 29 files would be reformatted |
mypy --strict utils |
29 errors in 16 files |
The 835 is misleading, and that decides the fix
Rule breakdown of the ruff findings:
| Code |
Count |
What |
PT009 |
744 |
use a plain assert instead of unittest's assertEqual |
PT027 |
41 |
use pytest.raises instead of assertRaises |
PT018 |
13 |
split a composite assertion |
PT008 |
4 |
patch-style monkeypatching |
| everything else |
33 |
E501, UP037, PERF401, SIM117, UP006, SIM118, … |
802 of 835 are flake8-pytest-style rules fired at code that
deliberately uses unittest. The utils/*-test.py self-tests are
unittest.TestCase suites run directly (python3 utils/<gate>-test.py),
not under pytest — that is why they are shaped this way, and the bindings
crate's config enables the PT family because it is a pytest suite.
So adopting the bindings config wholesale for utils/ is the wrong move:
it would demand rewriting ~800 assertions to satisfy a rule about a test
runner these files do not use. The real backlog is the 33 non-PT
findings plus the formatting and typing gaps.
Why it matters
These are not incidental scripts. AGENTS.md lists them as the gates run
by make pre-commit / make ci: check-versions.py,
check-snapshot-anchors.py, check-rustfmt-bail.py,
check-manpage-drift.py, check-diagnostic-prefix.py,
check-safety-doc-pin.py, check-grammar-marker-sync.py,
check-excluded-manifests.py, check-ruff-lockstep.py,
check-publish-metadata.py, and now check-feature-gates.py.
A gate that silently stops working is the worst failure mode in the
repository — check-snapshot-anchors.py already has a lesson attached to
exactly that (#1192, where a mis-lexed char literal made the gate report
clean files). Type errors and unreviewed formatting in that code are
carrying real risk.
Suggested shape
- A
utils/-scoped ruff config that inherits the house style but
drops flake8-pytest-style, since these suites are unittest by
design. Either a [tool.ruff] section in a utils/pyproject.toml or a
per-directory extend-per-file-ignores.
- Fix the 33 real findings and run
ruff format — a one-time
reformat of 27 files, best landed on its own so it does not hide behind
a functional change.
mypy --strict over utils/, fixing the 29 errors. Most are
no-untyped-call on the shared _load_module helper the *-test.py
files use to import a hyphenated script, so typing that one helper
likely clears a large fraction.
- Wire it in: extend the pre-commit
files: patterns and add a
utils/ arm to make py-lint / py-fmt-check / py-typecheck.
One constraint
AGENTS.md's "One ruff version, four declarations" rule applies:
big-code-analysis-py/uv.lock is the anchor, and the rev: in
.pre-commit-config.yaml, the requirements/dev.txt export and
pyproject.toml's bound must follow it. Whatever config utils/ gets
must not introduce a fifth place where a ruff version is named —
make check-ruff-lockstep only knows about the four.
Summary
The 29 Python scripts in
utils/are reached by no lint, format ortype gate. They are the scripts that gate everything else — the gates are
themselves ungated.
Where the scoping excludes them
.pre-commit-config.yaml:26-30— bothruff-checkandruff-formatcarry
files: ^big-code-analysis-py/.*\.py$.Makefile—py-lint/py-fmt-checkrun ruff over$(BCA_PY_DIR)(
big-code-analysis-py) and$(SMOKE_PY_DIR)(scripts/smoke) only;py-typecheckrunsmypy --strict python tests examples $(SMOKE_LIB_PY)from inside
big-code-analysis-py.utils/is in none of those paths.Measured
Using the bindings crate's own ruff and config
(
big-code-analysis-py/.venv/bin/ruff --config big-code-analysis-py/pyproject.toml):ruff check utilsruff format --check utilsmypy --strict utilsThe 835 is misleading, and that decides the fix
Rule breakdown of the ruff findings:
PT009assertinstead ofunittest'sassertEqualPT027pytest.raisesinstead ofassertRaisesPT018PT008E501,UP037,PERF401,SIM117,UP006,SIM118, …802 of 835 are
flake8-pytest-stylerules fired at code thatdeliberately uses
unittest. Theutils/*-test.pyself-tests areunittest.TestCasesuites run directly (python3 utils/<gate>-test.py),not under pytest — that is why they are shaped this way, and the bindings
crate's config enables the
PTfamily because it is a pytest suite.So adopting the bindings config wholesale for
utils/is the wrong move:it would demand rewriting ~800 assertions to satisfy a rule about a test
runner these files do not use. The real backlog is the 33 non-
PTfindings plus the formatting and typing gaps.
Why it matters
These are not incidental scripts.
AGENTS.mdlists them as the gates runby
make pre-commit/make ci:check-versions.py,check-snapshot-anchors.py,check-rustfmt-bail.py,check-manpage-drift.py,check-diagnostic-prefix.py,check-safety-doc-pin.py,check-grammar-marker-sync.py,check-excluded-manifests.py,check-ruff-lockstep.py,check-publish-metadata.py, and nowcheck-feature-gates.py.A gate that silently stops working is the worst failure mode in the
repository —
check-snapshot-anchors.pyalready has a lesson attached toexactly that (#1192, where a mis-lexed char literal made the gate report
clean files). Type errors and unreviewed formatting in that code are
carrying real risk.
Suggested shape
utils/-scoped ruff config that inherits the house style butdrops
flake8-pytest-style, since these suites areunittestbydesign. Either a
[tool.ruff]section in autils/pyproject.tomlor aper-directory
extend-per-file-ignores.ruff format— a one-timereformat of 27 files, best landed on its own so it does not hide behind
a functional change.
mypy --strictoverutils/, fixing the 29 errors. Most areno-untyped-callon the shared_load_modulehelper the*-test.pyfiles use to import a hyphenated script, so typing that one helper
likely clears a large fraction.
files:patterns and add autils/arm tomake py-lint/py-fmt-check/py-typecheck.One constraint
AGENTS.md's "One ruff version, four declarations" rule applies:big-code-analysis-py/uv.lockis the anchor, and therev:in.pre-commit-config.yaml, therequirements/dev.txtexport andpyproject.toml's bound must follow it. Whatever configutils/getsmust not introduce a fifth place where a ruff version is named —
make check-ruff-locksteponly knows about the four.