fix(uv): consolidate per-wheel metadata + namespace/regular-span venv merge#1092
Draft
jbedard wants to merge 2 commits into
Draft
fix(uv): consolidate per-wheel metadata + namespace/regular-span venv merge#1092jbedard wants to merge 2 commits into
jbedard wants to merge 2 commits into
Conversation
✨ Aspect Workflows Tasks📅 Fri Jun 12 20:54:41 UTC 2026 ✅ 7 successful tasks
⏱ Last updated Fri Jun 12 20:58:25 UTC 2026 · 📊 GitHub API quota 1,499/15,000 (10% used, resets in 36m) |
py_binary startup benchmark
sys.path quality
|
57482c7 to
e687292
Compare
… merge Consolidates three previously-independent branches (oai-5, oai-3, oai-azure) that each reshaped the same wheel-metadata schema and venv site-packages assembly in mutually-incompatible ways. Landing them separately would have had oai-3 and oai-azure reintroduce the exact cross-wheel metadata leak oai-5 fixes. This unifies them onto one per-wheel-keyed schema. Schema foundation (was oai-5): wheel metadata (top_levels, namespace_top_levels, console_scripts) is keyed per wheel by file basename instead of unioned across platform wheels, and the whl_install build rule selects the entry for the wheel the select chain resolved to for the active config. A union leaked an inactive wheel's surface into the active one (another platform's C-extension suffix as a dangling symlink, a win32-only console script wrapper everywhere). A lookup miss (sbuild fallback, failed extraction) emits no PyWheelsInfo and consumers fall back to .pth resolution. Namespace packages (was oai-3): PEP 420 namespace packages are now materialised CONCRETELY in site-packages via per-entry symlinks under a real namespace directory, from the new per-wheel `namespace_entries` metadata, so tools that inspect site-packages directly (mypy, pyright) see the packages and their py.typed markers — runtime .pth resolution alone left them invisible. Wheels lacking entry metadata (hand-written py_unpacked_wheel) keep the historical .pth-only fallback. Regular packages spanning wheels (was oai-azure): a regular package split across wheels (azure-core owns `azure/core/` while azure-core-tracing-opentelemetry grafts `azure/core/tracing/ext/...` into it) can't be merged by symlinks or .pth — Python locks a regular package's __path__ to one directory. The new per-wheel `namespace_dirs` / `regular_roots` metadata is cross-referenced across wheels to detect the overlap, and the conflicted subtree is physically merged by a new site_merge tool run under the (optional) exec-tools toolchain. The two assembly mechanisms coexist in _resolve_wheel_collisions: an all-namespace top-level with a spanning regular package goes to the physical merge + .pth (azure); a pure PEP 420 namespace goes to the per-entry concrete symlinks (oai-3). They never declare conflicting outputs for the same path. All metadata fields are now `attr.string_list_dict` keyed by wheel basename. e2e: pth-namespace-547 (concrete namespace, mypy-visible), azure-core-tracing-overlap (regular package spanning wheels), and the cffi abi3 snapshot (per-wheel surface) all pass; snapshots regenerated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…thing
When wheels share a PEP 420 namespace, the concrete per-entry merge
previously required entry metadata from EVERY claimant: a single
entryless contributor (a hand-written py_unpacked_wheel that omits
namespace_entries) dragged the whole group back to the .pth fallback,
re-hiding the well-formed wheels from tools that inspect site-packages
directly (mypy, pyright).
Merge the claimants that HAVE entries concretely and route only the
entryless ones to .pth. A concrete site-packages/<tl>/ directory (no
__init__.py) and a .pth/addsitedir portion both contribute to the same
namespace at runtime, so the entried wheels stay statically visible
while the entryless wheel still imports. Only when NO claimant has
entries do we keep the historical .pth-only fallback for the group.
Also documents two known limitations of the heuristic:
* the nested-namespace prefix collision where the shallower entry is a
regular package (surfaced via package_collisions, not mis-merged);
* wheels shipping namespace contributions under *.data/{purelib,platlib}/,
which aren't discovered as top-levels/entries.
Test: e2e/cases/pth-namespace-547/test_partial_merge — jaraco.classes
(entried uv whl_install) stays concrete + py.typed-visible while
jaraco.functools (entryless hand-written py_unpacked_wheel) merges via
.pth, and jaraco stays a namespace package with both portions on
__path__.
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.
Schema foundation: wheel metadata (top_levels, namespace_top_levels, console_scripts) is keyed per wheel by file basename instead of unioned across platform wheels, and the whl_install build rule selects the entry for the wheel the select chain resolved to for the active config. A union leaked an inactive wheel's surface into the active one (another platform's C-extension suffix as a dangling symlink, a win32-only console script wrapper everywhere). A lookup miss (sbuild fallback, failed extraction) emits no PyWheelsInfo and consumers fall back to .pth resolution.
Namespace packages: PEP 420 namespace packages are now materialised CONCRETELY in site-packages via per-entry symlinks under a real namespace directory, from the new per-wheel
namespace_entriesmetadata, so tools that inspect site-packages directly (mypy, pyright) see the packages and their py.typed markers — runtime .pth resolution alone left them invisible. Wheels lacking entry metadata (hand-written py_unpacked_wheel) keep the historical .pth-only fallback.Regular packages spanning wheels: a regular package split across wheels (azure-core owns
azure/core/while azure-core-tracing-opentelemetry graftsazure/core/tracing/ext/...into it) can't be merged by symlinks or .pth — Python locks a regular package's path to one directory. The new per-wheelnamespace_dirs/regular_rootsmetadata is cross-referenced across wheels to detect the overlap, and the conflicted subtree is physically merged by a new site_merge tool run under the (optional) exec-tools toolchain.The two assembly mechanisms coexist in _resolve_wheel_collisions: an all-namespace top-level with a spanning regular package goes to the physical merge + .pth (azure); a pure PEP 420 namespace goes to the per-entry concrete symlinks. They never declare conflicting outputs for the same path.
All metadata fields are now
attr.string_list_dictkeyed by wheel basename. e2e: pth-namespace-547 (concrete namespace, mypy-visible), azure-core-tracing-overlap (regular package spanning wheels), and the cffi abi3 snapshot (per-wheel surface) all pass; snapshots regenerated.Changes are visible to end-users: no
Test plan