Repository navigation
refactor(python): one module per function for the extension-resolution helpers - #1077
Merged
Merged
Conversation
The one-function-per-file gate at max_lines = 1 flags every module-scope function past the first substantial one. resolve_extension.py held four: _platform_patterns, is_bare_name, _resolve_package and the module's named export resolve_extension_path. Keep the export in place and move the three helpers out, one module each: platform_patterns.py, is_bare_name.py (carrying _LOADABLE_SUFFIXES, which nothing else reads) and resolve_package.py. Colocated tests follow their subjects; the resolve_extension_path tests now mock _resolve_package rather than reaching through it. No call site changes: resolve_extension.py still imports is_bare_name, so dirsql.resolve_extension keeps exporting both names. Refs #1066
… function The one-function-per-file gate at max_lines = 1 flags every module-scope function past the first substantial one. resolve_config_extensions.py held four: _load_toml_module, _load_extension_entries, _has_bare_name and the module's named export resolve_config_extension_specs. Keep the export in place and move the three helpers out, one module each: toml_module.py (carrying the _toml binding it produces), load_extension_entries.py and has_bare_name.py. The plural resolver now imports the two it uses from their own modules rather than through the singular one; its test pins where each is bound from. With this the whole packages/python/dirsql tree is clean at max_lines = 1. Refs #1079
thekevinscott
enabled auto-merge
September 5, 2026 02:01
6 of 8 tasks
…nfig-extensions refactor(python): split resolve_config_extensions into one module per function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lane
packages/python/dirsqlof the #1020 ratchet endgame. Brings both remainingone_function_per_fileoffenders in the package tomax_lines = 1.Originally opened as the first of a stacked pair; #1087 (the
resolve_config_extensions.pysplit) merged into this branch on 2026-09-05, so this PR now carries the whole lane. Per the no-stacking rule it was left as-is rather than retargeted.The gate flags every module-scope function past the first substantial one in a file. The holder is a free choice, so each module's named export keeps the file and the private helpers move out, one module each.
resolve_extension.py(3 flagged, holderresolve_extension_path):_platform_patternsdirsql/platform_patterns.pyis_bare_namedirsql/is_bare_name.py_LOADABLE_SUFFIXES(nothing else reads it)_resolve_packagedirsql/resolve_package.pyresolve_config_extensions.py(3 flagged, holderresolve_config_extension_specs):_load_toml_moduledirsql/toml_module.py_toml = _load_toml_module()binding (its only reader moves too)_load_extension_entriesdirsql/load_extension_entries.py_has_bare_namedirsql/has_bare_name.py6 flagged, 6 moves — zero spillover. Both constants that had to move have exactly one reader, so each rode along inside its function's new module. No leaf vocabulary module was needed and no import cycle appeared, against a budgeted ~15% extra.
Colocated tests follow their subjects. Several unit tests were re-scoped to satisfy
unit lintisolation — a sibling source module is an unmocked collaborator, so e.g.resolve_extension_test.pynow mocks_resolve_packagerather than reaching through it.resolve_configs_extension_specs.pyrepoints its three helper imports at the new modules. That is an import-only change, which trips thecolocated-testco-change gate; it is answered with three real assertions pinning each helper's__module__, not a whitespace edit and not an exemption. The repo's exemption count stays zero.Config untouched. Per #1020 the committed ceiling stays at 12; a separate final PR deletes the key once every lane is clean. Verified locally by temporarily setting
packages/python/testing-conventions.tomltomax_lines = 1, running the gate, then restoring it so the config is not in this diff:packages/python/dirsqlreports 0 violations atmax_lines = 1.Red/green does not apply: pure moves, no behavior change. Tests were relocated and re-scoped, not written for new behavior.
PARITY.md needs no change. None of the moved functions is in
dirsql.__all__;PARITY.mdnames onlyresolve_config_extension_specs/resolve_configs_extension_specs, neither of which moves. No parity drift — this is a file layout change inside one SDK, and the TypeScript mirror is being split in its own lane.Gates
just preflightwas run clean on each step before push (0 failing pairs, 3 skipped — the threepackagingpairs, which need a built artifact), and again on the combined branch after #1087 merged in.The combined re-run first reported one surviving mutant (
toml_module.py:16,ReplaceComparisonOperator_GtE_Is). Re-runningunit mutationon the identical tree reported 58 mutants tested, 0 survivors — so that was a flake, not a real survivor, and no assertion was added or weakened for it. Worth knowing for anyone else in the #1020 endgame: the python mutation gate appears to be nondeterministic under load (the flaky mutant makes its module raise at import, and the larger the mutant set, the more often it came backsurvivedrather thankilled). If CI reports a lone survivor here, re-run before changing a test.unit mutation(diff-scoped): 38 mutants / 0 survivors on theresolve_extensionstep, 20 / 0 on theresolve_config_extensionsstep, 58 / 0 on the combined diff againstorigin/mainunit coverage: 100% line + branch acrosspackages/python/dirsql(307 stmts, 90 branches, 0 miss); changed-lines check cleanunit one-function-per-fileatmax_lines = 1: clean across the packageunit lint,colocated-test(incl. co-change),integration lint,declared-deps: cleanManual run (
uv run python -c ...against the package):E2E Verification
packages/python/e2e-attestations/<branch>.jsonreceipt written ifpackages/pythonchanged (just e2e-attest-python)packages/ts/e2e-attestations/<branch>.jsonreceipt written ifpackages/tschanged (just e2e-attest-ts)cargo build -p dirsql --features cli,just test-e2e,just e2e-attest-pythonpackages/python/e2e-attestations/claude-1066-p1-resolve-extension.jsonand.../claude-1079-p2-resolve-config-extensions.json;git show --staton each attest commit confirms it adds exactly one file and deletes no sibling receipts (e2e attest silently deletes other branches' attestation receipts #1041).Changelog / Migrations
<root>/<pkg>/changelog.d/for each changed package (or:skip-changelogtrailer on a commit with reason)<root>/<pkg>/migrations.d/(or: not required -- additive/bugfix only)packages/python/changelog.d/2026-09-05-resolve-extension-split.mdandpackages/python/changelog.d/2026-09-05-config-extension-loader-split.md. No migration fragment: pure refactor, no public API or runtime behavior change.Fixes #1066
Fixes #1079