Skip to content

Commit ced895d

Browse files
authored
fix(pypi): don't expose source-less uv.lock packages (#3938)
> [!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: ```starlark 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.
1 parent a57eff9 commit ced895d

3 files changed

Lines changed: 17 additions & 3 deletions

File tree

news/3934.fixed.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(pypi) `pip.parse(uv_lock = ...)` no longer exposes uv workspace/root members
2+
that resolve to no wheel or sdist (e.g. `source = { virtual = "." }` or editable
3+
installs). Previously these source-less packages were added to the hub's
4+
`all_requirements` / `all_whl_requirements` with an alias to a subpackage that
5+
does not exist, breaking analysis for anything enumerating the full set such as
6+
`modules_mapping(wheels = all_whl_requirements)`
7+
([#3934](https://github.com/bazel-contrib/rules_python/issues/3934)).

python/private/pypi/parse_requirements.bzl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,14 @@ def _parse_uv_lock_json(uv_lock, all_platforms, logger, extra_pip_args = None, p
292292
versions = sorted(info["versions"].keys())
293293
item = struct(
294294
name = norm_name,
295-
is_exposed = True,
295+
# Only expose packages that resolved to at least one source. uv
296+
# workspace/root members (e.g. `source = { virtual = "." }` or
297+
# editable installs) resolve to no wheel/sdist, so exposing them
298+
# would add a dangling entry to the hub's `all_requirements` /
299+
# `all_whl_requirements` and create an alias to a subpackage that
300+
# doesn't exist. This mirrors the requirements path, which also
301+
# gates `is_exposed`.
302+
is_exposed = bool(info["resolved_srcs"]),
296303
is_multiple_versions = len(versions) > 1,
297304
index_url = info["index_url"],
298305
srcs = info["resolved_srcs"],

tests/pypi/parse_requirements/parse_requirements_tests.bzl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ def _test_uv_lock_primary_source_includes_virtual(env):
11931193
struct(
11941194
name = "virtual_pkg",
11951195
index_url = "",
1196-
is_exposed = True,
1196+
is_exposed = False,
11971197
is_multiple_versions = False,
11981198
srcs = [],
11991199
),
@@ -1620,7 +1620,7 @@ def _test_uv_lock_requires_dist_extras(env):
16201620
struct(
16211621
name = "root_pkg",
16221622
index_url = "",
1623-
is_exposed = True,
1623+
is_exposed = False,
16241624
is_multiple_versions = False,
16251625
srcs = [],
16261626
),

0 commit comments

Comments
 (0)