fix: pkgutil namespace package __init__.py collisions when multiple wheels share a namespace stub#1270
fix: pkgutil namespace package __init__.py collisions when multiple wheels share a namespace stub#1270xangcastle wants to merge 2 commits into
Conversation
✨ Aspect Workflows Tasks📅 Tue Jul 7 19:51:55 UTC 2026 ✅ 36 successful tasks
⏱ Last updated Tue Jul 7 19:55:34 UTC 2026 · 📊 GitHub API quota 1,392/15,000 (9% used, resets in 34m) |
py_binary startup benchmark
sys.path quality
Bazel analysis benchmark
Auxiliary metrics
|
794953c to
57025ec
Compare
| # Only emitted for wheels that contribute to a namespace — keeps the | ||
| # generated BUILD files (and their e2e snapshots) unchanged for the | ||
| # common regular-top-level-only case. | ||
| if pkgutil_namespace_top_levels_by_whl: |
There was a problem hiding this comment.
Seems like we have no snapshot tests covering this case?
|
Do we want to merge #1205 first to avoid waiting for that bot to rebase? |
| """ | ||
| if filecmp.cmp(str(src_file), str(dest), shallow=False): | ||
| return True | ||
| if src_file.name != "__init__.py" or dest.name != "__init__.py": |
There was a problem hiding this comment.
If both are __init__.py files should we only do the _is_namespace_init_stub() calls and not filecmp.cmp()?
Today (just like in the rust version) we are reading the file twice, so 2x the IO operations, when both files are __init__.py. I think when analyzing the AST there's no point doing it twice?
| try: | ||
| tree = ast.parse(content) | ||
| except SyntaxError: | ||
| return False |
There was a problem hiding this comment.
What if the file was empty? Do we have a test for that?
| continue | ||
| meaningful.append(stmt) | ||
|
|
||
| if len(meaningful) != 1: |
There was a problem hiding this comment.
Is an empty body not an "init ast"?
|
Robot feedback, possibly all 7 cases should have unit tests and be fixed? |
|
What does native uv/pip/python do though? Can we include references to those docs or implementations? |
This PR fixes false-positive package collisions for namespace packages like backports where each wheel ships an equivalent
__init__.pythat only declares apkgutilorpkg_resourcesnamespace. The wheel metadata extractor now detects these stubs, marks the top-level as a namespace package, and the venv assembly merges the entries with individual symlinks instead of treating it as a collision. site_merge.py also learns to treat equivalent namespace stubs as the same file during physical merges as a defensive fallback.Changes are visible to end-users: yes/no
Test plan