Skip to content

fix(pypi): don't expose source-less uv.lock packages#3938

Merged
aignas merged 3 commits into
bazel-contrib:mainfrom
lpulley:fix/uv-lock-virtual-exposed
Jul 21, 2026
Merged

fix(pypi): don't expose source-less uv.lock packages#3938
aignas merged 3 commits into
bazel-contrib:mainfrom
lpulley:fix/uv-lock-virtual-exposed

Conversation

@lpulley

@lpulley lpulley commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Note

I created this PR with AI.

Fixes #3934.

Problem

pip.parse(uv_lock = ...) exposes every [[package]] in the lock, including uv workspace/root members with source = { virtual = "." } (and editable installs). These resolve to no wheel/sdist (srcs = []) but were still marked is_exposed = True, so the hub adds them to all_requirements / all_whl_requirements and creates an alias to a subpackage that doesn't exist. Anything enumerating the full set then fails analysis, e.g. modules_mapping(wheels = all_whl_requirements):

ERROR: no such package '@@rules_python++pip+pip//myproject': BUILD file not found ... and referenced by '//:modules_map'

Fix

_parse_uv_lock_json in python/private/pypi/parse_requirements.bzl set is_exposed = True unconditionally. This gates it on whether the package actually resolved to any sources:

is_exposed = bool(info["resolved_srcs"]),

The entry is still kept; it just isn't exposed when nothing resolved. This mirrors the requirements path, which already gates is_exposed.

Tests

As called out in the issue, this flips the expectations in two existing tests, both of which assert on source-less packages:

  • _test_uv_lock_primary_source_includes_virtual (the virtual_pkg entry)
  • _test_uv_lock_requires_dist_extras (the root_pkg entry)

Both now expect is_exposed = False.

A news/3934.fixed.md fragment is included.

lpulley added 3 commits July 20, 2026 09:49
Add news fragment for the uv.lock virtual/root package exposure fix.
`pip.parse(uv_lock = ...)` exposed every package in the lock, including uv
workspace/root members with `source = { virtual = "." }` (and editable installs).
These resolve to no wheel/sdist (srcs = []) but were still marked is_exposed,
so the hub added them to all_requirements / all_whl_requirements and created an
alias to a subpackage that does not exist. Anything enumerating the full set
then failed analysis, e.g. modules_mapping(wheels = all_whl_requirements).

Gate is_exposed on whether the package resolved to any sources, mirroring the
requirements path which already gates is_exposed.

Fixes bazel-contrib#3934
Update _test_uv_lock_primary_source_includes_virtual and the root-pkg case
in _test_uv_lock_requires_dist_extras to expect is_exposed = False now that
source-less uv.lock packages are no longer exposed.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request ensures that pip.parse(uv_lock = ...) does not expose uv workspace or root members that do not resolve to any wheel or sdist (such as virtual packages or editable installs). This is achieved by setting is_exposed to bool(info["resolved_srcs"]) in _parse_uv_lock_json. Corresponding unit tests have been updated to reflect this change. There are no review comments to address.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@lpulley
lpulley marked this pull request as ready for review July 20, 2026 15:15
@lpulley
lpulley requested review from aignas and rickeylev as code owners July 20, 2026 15:15
@aignas
aignas added this pull request to the merge queue Jul 20, 2026
Merged via the queue into bazel-contrib:main with commit ced895d Jul 21, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pip.parse(uv_lock=...) exposes the virtual root project as a wheel-less package, breaking all_requirements/modules_mapping

2 participants