Two places where a convention this project holds everywhere else is broken, and where nothing checks it.
The yamlfix hook reports itself as pyproject-fmt
.pre-commit-config.yaml:416:
- id: yamlfix
name: pyproject-fmt
entry: uv run --extra=dev yamlfix
name: pyproject-fmt is copied from the hook at line 377, which really is pyproject-fmt-fix. Two hooks therefore display the same name:
377: name: pyproject-fmt # id: pyproject-fmt-fix
416: name: pyproject-fmt # id: yamlfix
Every other hook in the file names itself after what it runs. The cost is small but real: when yamlfix reformats a YAML file and the hook reports a failure, the output says pyproject-fmt, which sends whoever is reading it to pyproject.toml.
The autofix.ci workflow runs all pre-commit-stage hooks with --verbose --no-fail-fast, so this name appears in CI output as well as locally.
Two validators take a positional argument
Every validate_* and run_* function in src/ is keyword-only, with two exceptions:
src/mock_vws/_query_validators/accept_header_validators.py:14 validate_accept_header(request_headers)
src/mock_vws/_query_validators/auth_validators.py:90 validate_auth_header_has_signature(request_headers)
That is 2 out of every such function in the codebase — I checked by parsing all of src/ rather than by grepping.
Both call sites in _query_validators/__init__.py already pass by keyword, so nothing is broken today and this cannot break at runtime. It is a consistency point only.
Worth noting that the project pins strict-kwargs and mypy-strict-kwargs and runs both, which is what makes the exception surprising: those tools enforce keyword arguments at call sites, not keyword-only parameters at definitions, so neither catches this.
Suggested resolution
Rename the hook to yamlfix.
Add * to the two function signatures.
Both are one-line changes. The more useful half is preventing recurrence, and ci/test_custom_linters.py is the natural home for both checks, since it already holds this project's bespoke consistency rules:
- assert that every hook
id and name pair in .pre-commit-config.yaml is unique, which catches the copy-paste directly
- assert that every function in
src/ has no positional parameters, which is a stronger and simpler rule than "validators are keyword-only" and appears to already hold
The second is worth checking against the whole tree before enforcing, in case there is somewhere a positional parameter is deliberate.
Two places where a convention this project holds everywhere else is broken, and where nothing checks it.
The yamlfix hook reports itself as pyproject-fmt
.pre-commit-config.yaml:416:name: pyproject-fmtis copied from the hook at line 377, which really ispyproject-fmt-fix. Two hooks therefore display the same name:Every other hook in the file names itself after what it runs. The cost is small but real: when
yamlfixreformats a YAML file and the hook reports a failure, the output sayspyproject-fmt, which sends whoever is reading it topyproject.toml.The
autofix.ciworkflow runs all pre-commit-stage hooks with--verbose --no-fail-fast, so this name appears in CI output as well as locally.Two validators take a positional argument
Every
validate_*andrun_*function insrc/is keyword-only, with two exceptions:That is 2 out of every such function in the codebase — I checked by parsing all of
src/rather than by grepping.Both call sites in
_query_validators/__init__.pyalready pass by keyword, so nothing is broken today and this cannot break at runtime. It is a consistency point only.Worth noting that the project pins
strict-kwargsandmypy-strict-kwargsand runs both, which is what makes the exception surprising: those tools enforce keyword arguments at call sites, not keyword-only parameters at definitions, so neither catches this.Suggested resolution
Rename the hook to
yamlfix.Add
*to the two function signatures.Both are one-line changes. The more useful half is preventing recurrence, and
ci/test_custom_linters.pyis the natural home for both checks, since it already holds this project's bespoke consistency rules:idandnamepair in.pre-commit-config.yamlis unique, which catches the copy-paste directlysrc/has no positional parameters, which is a stronger and simpler rule than "validators are keyword-only" and appears to already holdThe second is worth checking against the whole tree before enforcing, in case there is somewhere a positional parameter is deliberate.