Skip to content

refactor(python): one module per function for the extension-resolution helpers - #1077

Merged
thekevinscott merged 5 commits into
mainfrom
claude/1066-p1-resolve-extension
Sep 5, 2026
Merged

thekevinscott merged 5 commits into
mainfrom
claude/1066-p1-resolve-extension

Conversation

@thekevinbot

@thekevinbot thekevinbot commented Sep 5, 2026 •

Copy link
Copy Markdown
Collaborator

Lane packages/python/dirsql of the #1020 ratchet endgame. Brings both remaining one_function_per_file offenders in the package to max_lines = 1.

Originally opened as the first of a stacked pair; #1087 (the resolve_config_extensions.py split) 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, holder resolve_extension_path):

Moved To Carried with it
_platform_patterns dirsql/platform_patterns.py —
is_bare_name dirsql/is_bare_name.py _LOADABLE_SUFFIXES (nothing else reads it)
_resolve_package dirsql/resolve_package.py —

resolve_config_extensions.py (3 flagged, holder resolve_config_extension_specs):

Moved To Carried with it
_load_toml_module dirsql/toml_module.py the _toml = _load_toml_module() binding (its only reader moves too)
_load_extension_entries dirsql/load_extension_entries.py —
_has_bare_name dirsql/has_bare_name.py —

6 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 lint isolation — a sibling source module is an unmocked collaborator, so e.g. resolve_extension_test.py now mocks _resolve_package rather than reaching through it.

resolve_configs_extension_specs.py repoints its three helper imports at the new modules. That is an import-only change, which trips the colocated-test co-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.toml to max_lines = 1, running the gate, then restoring it so the config is not in this diff: packages/python/dirsql reports 0 violations at max_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.md names only resolve_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 preflight was run clean on each step before push (0 failing pairs, 3 skipped — the three packaging pairs, 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-running unit mutation on 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 back survived rather than killed). If CI reports a lone survivor here, re-run before changing a test.

  • unit mutation (diff-scoped): 38 mutants / 0 survivors on the resolve_extension step, 20 / 0 on the resolve_config_extensions step, 58 / 0 on the combined diff against origin/main
  • unit coverage: 100% line + branch across packages/python/dirsql (307 stmts, 90 branches, 0 miss); changed-lines check clean
  • unit one-function-per-file at max_lines = 1: clean across the package
  • unit lint, colocated-test (incl. co-change), integration lint, declared-deps: clean
  • Unit suite 134 passed; hermetic integration 26 passed

Manual run (uv run python -c ... against the package):

>>> resolve_extension_path('ext/vec0.so', base='/cfg', resolve_relative=True)
/cfg/ext/vec0.so
>>> is_bare_name('sqlite_vec'), is_bare_name('ext/vec0.so')
True False
>>> resolve_extension_path('definitely_not_installed_pkg', base='/tmp', resolve_relative=True)
ValueError: could not resolve extension package 'definitely_not_installed_pkg': not installed
>>> resolve_config_extension_specs('<tmp>/.dirsql.toml')   # [[extensions]] path = "sqlite_vec"
None   # unresolvable bare name -> caller falls back

E2E Verification

  • Ran e2e suites locally for every affected SDK
  • Python SDK e2e: pass
  • TypeScript SDK e2e: N/A
  • Rust core e2e (if applicable): N/A
  • packages/python/e2e-attestations/<branch>.json receipt written if packages/python changed (just e2e-attest-python)
  • packages/ts/e2e-attestations/<branch>.json receipt written if packages/ts changed (just e2e-attest-ts)
  • Command(s) run: cargo build -p dirsql --features cli, just test-e2e, just e2e-attest-python
  • Result summary: 37 passed on each step. Receipts at packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json and .../claude-1079-p2-resolve-config-extensions.json; git show --stat on 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

  • Changelog fragment added under <root>/<pkg>/changelog.d/ for each changed package (or: skip-changelog trailer on a commit with reason)
  • Migration fragment added under <root>/<pkg>/migrations.d/ (or: not required -- additive/bugfix only)

packages/python/changelog.d/2026-09-05-resolve-extension-split.md and packages/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

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
…nfig-extensions

refactor(python): split resolve_config_extensions into one module per function
@thekevinbot thekevinbot changed the title refactor(python): split resolve_extension into one module per function refactor(python): one module per function for the extension-resolution helpers Sep 5, 2026
@thekevinscott
thekevinscott merged commit d9aada4 into main Sep 5, 2026
39 of 40 checks passed
@thekevinscott
thekevinscott deleted the claude/1066-p1-resolve-extension branch September 5, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants