Skip to content

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

Description

@lpulley

Note

I diagnosed this problem and wrote this issue with AI.

Description

pip.parse(uv_lock = ...) (as of 2.2.0) exposes every [[package]] in the lock, including uv workspace/root members with source = { virtual = "." } (and editable). These resolve to no wheel/sdist (srcs = []) but are still is_exposed = True, so the hub adds them to all_requirements / all_whl_requirements and tries to create an alias 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'

Root cause (two layers)

  • _parse_uv_lock_json (python/private/pypi/parse_requirements.bzl) sets is_exposed = True unconditionally (~L295), even when nothing resolved.
  • The hub (hub_builder.bzl / extension.bzl) then materializes the dangling all_* entry + alias from that exposed-but-source-less package.

Suggested fix

Keep the entry; just stop exposing ones that resolved to nothing:

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

(mirrors the requirements path, which already gates is_exposed). This flips two tests that currently assert the opposite (_test_uv_lock_primary_source_includes_virtual and the root-pkg case in _test_uv_lock_requires_dist_extras).

Repro

Minimal uv.lock (single root project + one dep):

[[package]]
name = "myproject"
version = "0"
source = { virtual = "." }
dependencies = [{ name = "click" }]

[[package]]
name = "click"
version = "8.1.8"
source = { registry = "https://pypi.org/simple" }
wheels = [{ url = ".../click-8.1.8-py3-none-any.whl", hash = "sha256:..." }]

pip.parse(hub_name = "pip", uv_lock = "//:uv.lock", requirements_lock = "//:uv.lock", python_version = "3.13"), then modules_mapping(wheels = all_whl_requirements) → the error above. (requirements_lock is currently required even with uv_lock; it's ignored, so pointing it at the same file works.)

Environment

rules_python 2.2.0, Bazel 9.1.1, Linux.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions