feat(standards): cut python-tooling 1.18 for the three adoption reports - #225
Merged
Merged
Conversation
Three adopters hit python-tooling 1.17 in the same week. All three fixes land in
1.18; 1.17's bytes are frozen at the v5.27.0 tag.
1.17's adopt.md said a deliberately non-installable repository "needs no
[project] table" two lines above the PT-PROJECT-METADATA block that exists
because the required `uv lock` cannot read such a file, and _metadata_findings
short-circuited to no findings whenever that backend was selected. uv refuses
any pyproject.toml with no [project] table whatever the backend, and classifies
[project] without [build-system] as source = { virtual = "." }. The
short-circuit is gone, the guide is corrected, and the finding's own hint no
longer offers `build_backend = "none"` as a way out — from 1.18 it is not one.
The message drops its "installable adoption" framing for uv-resolvability,
which is what the guard has always actually enforced.
This tightens behavior for an existing `none` consumer with no [project]. That
repository was already failing at `uv lock`, so the finding surfaces an
existing failure at reconcile --check rather than breaking a working adoption.
The migration note is in the family README, the versioned README, adopt.md, and
the CHANGELOG.
Declared roots feed checker, Ruff, coverage, and pytest scopes; none of them
makes a package under a subproject importable, so conftest still fails with
ModuleNotFoundError. A new troubleshooting row gives both fixes and what each
covers: pythonpath written into [tool.pytest.ini_options] (pytest only), or a
uv workspace member plus additional_dev_dependencies (every uv run). That
option also gained the explanatory prose it never had.
Only minversion, testpaths, addopts, and markers are package-owned in
[tool.pytest.ini_options]; every other key there is consumer-owned and survives
reconcile, apply, validate, and an option change that rewrites an owned key in
the same table. The new row says so and quotes the ordering trap verbatim:
while the plugin is absent, the package-owned --strict-config aborts with
`ERROR: Unknown config option: asyncio_mode`, collected 0 items, exit 4 — a
message naming neither the flag nor the plugin. Core keys like pythonpath are
exempt. No generic passthrough and no per-plugin option, per the rejected
alternatives on record.
Also bounded: additional_dev_dependencies entries are checked for stringness
before _dependency_name's re.split reaches them, so a bad entry raises the
provider's ValueError rather than a raw TypeError. It cannot route through
_string_list like its siblings, because that helper rejects `<` and `>` and both
are ordinary characters in a PEP 508 requirement.
No option, unit identity, or rendered byte moves, so no migration edge is
declared. test_python_tooling_1_17.py keeps only what a retired version can still
prove; its family-root navigation row is dropped for the same reason the 1.16 and
1.15 rows were at the previous cut. _BASELINE_REF advances to v5.27.0, which its
own comment requires of the activation commit.
Refs #204, #205, #206
chrisdpurcell
marked this pull request as ready for review
September 1, 2026 12:19
This was referenced Sep 1, 2026
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.
Summary
python-tooling 1.18 (1.17 retained, byte-immutable) for the three adoption reports:
adopt.mdno longer claimsbuild_backend = "none"needs no[project]table (uv refuses anypyproject.tomlwithout one;[project]without[build-system]issource = { virtual = "." })._metadata_findingsdrops thebuild_backend == "none"short-circuit soPT-PROJECT-METADATAfires for every adoption; the hint no longer tells the blocked adopter to select the very option that used to skip the check. Migration note in the family README,adopt.md, and the CHANGELOGChangedentry: affected repositories were already failing atuv lock, the finding now names it up front.source_layout = "explicit"troubleshooting row states that declared roots feed checker/Ruff/coverage/pytest scopes without making a subproject importable, and gives both fixes (pythonpathin[tool.pytest.ini_options]for pytest only; uv workspace member +additional_dev_dependenciesfor everyuv run).additional_dev_dependenciesgains explanatory prose.[tool.pytest.ini_options]key outside the package-ownedminversion/testpaths/addopts/markersis consumer-owned and may be written straight into the managed table; install its plugin viaadditional_dev_dependenciesfirst, or--strict-configreportsERROR: Unknown config option: asyncio_mode. Confirmed end-to-end in a live consumer repro (keys survivereconcile --apply,validate, and an option change that rewrites the same table).additional_dev_dependenciesentry now raises the boundedValueErrornaming the option instead of a rawTypeError(PEP 508 bounds like>=1.0,<2still render).Wiring:
standard.toml,catalogs/5.toml(1.18 default),standards/catalog.md, projection, family-root and README pins,_BASELINE_REF→v5.27.0, CHANGELOG[Unreleased]. Tests:test_python_tooling_1_18.py(17 rows, including a permanent control row that reproduces #204 against 1.17), retained flip in_1_17.py.Rebased onto
testingafter markdown-tooling 1.16 landed; the two textual conflicts (CHANGELOG sections, README pin table) were resolved keep-both by the orchestrator and re-verified.Governing work
Final: #204
#205 and #206 ship in the same cut and are closed separately with this PR as their evidence.
Acceptance coverage
adopt.md:21corrected; AC2 short-circuit removed, docstring reframed to uv-resolvability, migration note present; AC3 contract test —build_backend = "none"without[project]→ one blockingPT-PROJECT-METADATA; with[project]and no[build-system]→ none; the 1.17 control row still reports nothing.pythonpath; alternative documented with its scope;additional_dev_dependenciesexplained.--strict-configerror; ordering trap stated; no passthrough option added.git diff --stat 3bda3cf4 -- …/1.17empty).Verification
check-release --baseline v5.27.0 --json→ onlyPC-RELEASE-PROJECTION(mid-train by design);classify_catalog_diff(v5.27.0 → tree, 5.27.0→5.28.0)→minor, no findings.validate-packages,validate-graph,render-catalog --check,sync-payload-projection --check→ OK; ruff format/check → 0;rexec -- uv run basedpyright→ 0..standards/catalog.tomlstaleness class; fulltests/package_contract→ 1755 passed, 21 failed = those 2 + 19 workernpm ciprovisioning.test_python_tooling_1_18.py,_1_17.py,test_python_tooling_reconstruction.py,test_repository_hygiene.py,test_catalog_roles.py→ 133 passed; render-catalog / projection / validate-packages OK on the rebased tree.