Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/uv.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@ gazelle_python_manifest(
- `include_stub_packages` — Whether to index conventional stub distributions such as
`types-requests` and `asyncpg-stubs`. The Gazelle Python extension then adds matching
stub dependencies automatically. Defaults to `False`.
- `platform_parents` — Single-element list holding the parent platform for the synthetic
platforms this rule uses to pin each venv's dependency group (Bazel's `platform()` rule
accepts at most one parent). Defaults to `["@platforms//host"]`, which carries only bare
OS and CPU constraints. Set it when that isn't enough: pass your custom `--host_platform`
when hermetic C++ toolchains gate on extra constraints, so sdist builds in the hub can
still resolve a cc toolchain; or pass the target platform when cross-compiling, so wheel
selection follows it instead of snapping back to the host.
- `venvs` — List of dependency group names whose wheels should be indexed. Module mappings
from all listed dependency groups are merged into a single manifest.

Expand Down
13 changes: 13 additions & 0 deletions e2e/cases/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -241,5 +241,18 @@ write_source_files(
# modules_mapping so generator drift (module additions, stub
# synthesis, merge ordering) surfaces as a diff.
"snapshots/uv_gazelle_778.gazelle_python.yaml": "//uv-gazelle-778:gazelle_python_manifest",

# Gazelle manifest built by //gazelle-platform-parents-1416 with a
# caller-supplied `platform_parents` (issue #1416). Pins that the
# manifest builds end-to-end when the macro's synthetic per-venv
# platforms parent onto a custom platform rather than
# `@platforms//host`.
"snapshots/gazelle_platform_parents_1416.gazelle_python.yaml": "//gazelle-platform-parents-1416:gazelle_python_manifest",
# Companion probe: a genrule transitioned onto the macro-generated
# platform, selecting on a constraint only the custom parent carries.
# Pins "custom-parent": if the macro ignores `platform_parents` the
# constraint is dropped and the diff test fails, rather than the
# regression silently building.
"snapshots/gazelle_platform_parents_1416.probe_out.txt": "//gazelle-platform-parents-1416:probe",
},
)
65 changes: 65 additions & 0 deletions e2e/cases/gazelle-platform-parents-1416/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
load("@aspect_rules_py//uv:defs.bzl", "gazelle_python_manifest")
load("@bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")

# Regression test for `gazelle_python_manifest(platform_parents = ...)`
# (issue #1416: the macro's synthetic per-venv platforms were pinned to
# `@platforms//host`, breaking cross-compilation and custom host platforms).
# Reads from the //uv-deps-650 hub, which already declares an `extras` venv.
#
# Documented exception to per-case isolation: this test applies Gazelle to a
# venv from another case (//uv-deps-650), so the cross-case reference is by
# design.
package(default_visibility = ["//:__pkg__"])

# A case-local constraint that only `:parent_platform` carries: observing it
# downstream proves the macro-generated platform inherited from
# `:parent_platform`.
constraint_setting(name = "parentage")

constraint_value(
name = "custom_parent",
constraint_setting = ":parentage",
)

# Stands in for a user's custom `--host_platform` — e.g. one carrying the extra
# constraints a hermetic C++ toolchain gates on. Parenting it on
# `@platforms//host` keeps the case host-OS-agnostic.
platform(
name = "parent_platform",
constraint_values = [":custom_parent"],
parents = ["@platforms//host"],
)

gazelle_python_manifest(
name = "gazelle_python_manifest",
hub = "pypi_uv_deps_650",
platform_parents = [":parent_platform"],
venvs = ["extras"],
)

# The macro generates a synthetic platform named `_{name}_{hub}_{venv}` in
# this package; `:probe` depends on that naming scheme, so a rename inside the
# macro breaks this target with a missing-target analysis error.
#
# The snapshot pins "custom-parent": if the macro ignores `platform_parents`,
# the generated platform loses `:custom_parent`, the select falls through to
# "default-parent", and the snapshot diff test fails.
config_setting(
name = "under_custom_parent",
constraint_values = [":custom_parent"],
)

genrule(
name = "probe_src",
outs = ["probe_out.txt"],
cmd = select({
":under_custom_parent": "echo custom-parent > $@",
"//conditions:default": "echo default-parent > $@",
}),
)

platform_transition_filegroup(
name = "probe",
srcs = [":probe_src"],
target_platform = ":_gazelle_python_manifest_pypi_uv_deps_650_extras",
)

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 27 additions & 4 deletions uv/private/gazelle_manifest/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ _modules_mapping = rule(

update = Label(":update.sh")

def gazelle_python_manifest(name, hub, venvs = [], include_stub_packages = False):
def gazelle_python_manifest(
name,
hub,
venvs = [],
include_stub_packages = False,
platform_parents = None):
"""Generates a Gazelle Python manifest from uv-managed wheels.

Args:
Expand All @@ -79,7 +84,27 @@ def gazelle_python_manifest(name, hub, venvs = [], include_stub_packages = False
venvs: Dependency groups whose wheels should be indexed.
include_stub_packages: Whether conventional stub distributions should be
indexed for Gazelle's automatic stub dependency resolution.
platform_parents: Single-element list holding the parent platform for the
synthetic platforms this macro uses to select each venv's wheels.
(Bazel's `platform()` rule accepts at most one parent; the list shape
mirrors its `parents` attribute.) Defaults to
`[Label("@platforms//host")]`, resolved in rules_py's own repository —
you do not need a `bazel_dep` on `platforms` to use the default. The
host platform carries only OS and CPU constraints; point this at the
platform the wheels should be resolved for when that is not enough:

- If the build sets a custom `--host_platform` (for example to carry
the constraints hermetic C++ toolchains require), pass that
platform here so sdist builds inside the hub can still resolve a
cc toolchain.
- When cross-compiling, pass the target platform so wheel selection
follows it instead of snapping back to the host.
"""
if platform_parents == None:
platform_parents = [Label("@platforms//host")]
if len(platform_parents) != 1:
fail("gazelle_python_manifest: platform_parents must contain exactly one platform label (Bazel's platform() rule accepts at most one parent); got {}".format(platform_parents))

file = "gazelle_python.yaml"
hub = hub.lstrip("@")

Expand All @@ -88,9 +113,7 @@ def gazelle_python_manifest(name, hub, venvs = [], include_stub_packages = False
platform_name = "_{}_{}_{}".format(name, hub, venv)
native.platform(
name = platform_name,
parents = [
"@platforms//host",
],
parents = platform_parents,
flags = [
"--@{}//dep_group={}".format(hub, venv),
],
Expand Down
Loading