Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4cb8412

Browse filesBrowse files
authored
feat(uv): parse the dist-manifest.json to not hardcode sha256 in rules_python (#2578)
Finalize the `uv` extension interface employing a builder pattern so that the users can specify the exact version that needs to be registered. This also moves the registration of the actual toolchain to `rules_python` itself and ensures that an incompatible noop toolchain is registered if nothing is configured. This ensures that the `register_toolchains("@uv//:all")` never fails. If the `url/sha256` values are not specified, this is falling back to using the `dist-manifest.json` on the GH releases page so that we can get the expected `sha256` value of each available file and download all of the usable archives. This means that `rules_python` no longer needs to be updated for `uv` version bumps. The remaining bits for closing the ticket: - [ ] Finalize the `lock` interface. - [ ] Add the locking target to the `pip.parse` hub repo if `pyproject.toml` is passed in. - [ ] Add a rule/target for `venv` creation. Work towards #1975.
1 parent 52712b9 commit 4cb8412
Copy full SHA for 4cb8412
Expand file treeCollapse file tree

17 files changed

+1371
-284
lines changed

‎CHANGELOG.md

Copy file name to clipboardExpand all lines: CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ Unreleased changes template.
8080
* {obj}`//python/bin:python`: convenience target for directly running an
8181
interpreter. {obj}`--//python/bin:python_src` can be used to specify a
8282
binary whose interpreter to use.
83+
* (uv) Now the extension can be fully configured via `bzlmod` APIs without the
84+
need to patch `rules_python`. The documentation has been added to `rules_python`
85+
docs but usage of the extension may result in your setup breaking without any
86+
notice. What is more, the URLs and SHA256 values will be retrieved from the
87+
GitHub releases page metadata published by the `uv` project.
8388
* (pypi) An extra argument to add the interpreter lib dir to `LDFLAGS` when
8489
building wheels from `sdist`.
8590

‎MODULE.bazel

Copy file name to clipboardExpand all lines: MODULE.bazel
+75-8Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,83 @@ use_repo(
174174
"build_bazel_bazel_self",
175175
)
176176

177-
# EXPERIMENTAL: This is experimental and may be removed without notice
178-
uv = use_extension(
177+
# TODO @aignas 2025-01-27: should this be moved to `//python/extensions:uv.bzl` or should
178+
# it stay as it is? I think I may prefer to move it.
179+
uv = use_extension("//python/uv:uv.bzl", "uv")
180+
181+
# Here is how we can define platforms for the `uv` binaries - this will affect
182+
# all of the downstream callers because we are using the extension without
183+
# `dev_dependency = True`.
184+
uv.default(
185+
base_url = "https://github.com/astral-sh/uv/releases/download",
186+
manifest_filename = "dist-manifest.json",
187+
version = "0.6.3",
188+
)
189+
uv.default(
190+
compatible_with = [
191+
"@platforms//os:macos",
192+
"@platforms//cpu:aarch64",
193+
],
194+
platform = "aarch64-apple-darwin",
195+
)
196+
uv.default(
197+
compatible_with = [
198+
"@platforms//os:linux",
199+
"@platforms//cpu:aarch64",
200+
],
201+
platform = "aarch64-unknown-linux-gnu",
202+
)
203+
uv.default(
204+
compatible_with = [
205+
"@platforms//os:linux",
206+
"@platforms//cpu:ppc",
207+
],
208+
platform = "powerpc64-unknown-linux-gnu",
209+
)
210+
uv.default(
211+
compatible_with = [
212+
"@platforms//os:linux",
213+
"@platforms//cpu:ppc64le",
214+
],
215+
platform = "powerpc64le-unknown-linux-gnu",
216+
)
217+
uv.default(
218+
compatible_with = [
219+
"@platforms//os:linux",
220+
"@platforms//cpu:s390x",
221+
],
222+
platform = "s390x-unknown-linux-gnu",
223+
)
224+
uv.default(
225+
compatible_with = [
226+
"@platforms//os:macos",
227+
"@platforms//cpu:x86_64",
228+
],
229+
platform = "x86_64-apple-darwin",
230+
)
231+
uv.default(
232+
compatible_with = [
233+
"@platforms//os:windows",
234+
"@platforms//cpu:x86_64",
235+
],
236+
platform = "x86_64-pc-windows-msvc",
237+
)
238+
uv.default(
239+
compatible_with = [
240+
"@platforms//os:linux",
241+
"@platforms//cpu:x86_64",
242+
],
243+
platform = "x86_64-unknown-linux-gnu",
244+
)
245+
use_repo(uv, "uv")
246+
247+
register_toolchains("@uv//:all")
248+
249+
uv_dev = use_extension(
179250
"//python/uv:uv.bzl",
180251
"uv",
181252
dev_dependency = True,
182253
)
183-
uv.toolchain(uv_version = "0.4.25")
184-
use_repo(uv, "uv_toolchains")
185-
186-
register_toolchains(
187-
"@uv_toolchains//:all",
188-
dev_dependency = True,
254+
uv_dev.configure(
255+
version = "0.6.2",
189256
)

‎examples/bzlmod/MODULE.bazel

Copy file name to clipboardExpand all lines: examples/bzlmod/MODULE.bazel
+9-6Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,15 @@ python.single_version_platform_override(
101101
# rules based on the `python_version` arg values.
102102
use_repo(python, "python_3_10", "python_3_9", "python_versions", "pythons_hub")
103103

104-
# EXPERIMENTAL: This is experimental and may be removed without notice
105-
uv = use_extension("@rules_python//python/uv:uv.bzl", "uv")
106-
uv.toolchain(uv_version = "0.4.25")
107-
use_repo(uv, "uv_toolchains")
108-
109-
register_toolchains("@uv_toolchains//:all")
104+
# EXPERIMENTAL: This is experimental and may be changed or removed without notice
105+
uv = use_extension(
106+
"@rules_python//python/uv:uv.bzl",
107+
"uv",
108+
# Use `dev_dependency` so that the toolchains are not defined pulled when your
109+
# module is used elsewhere.
110+
dev_dependency = True,
111+
)
112+
uv.configure(version = "0.6.2")
110113

111114
# This extension allows a user to create modifications to how rules_python
112115
# creates different wheel repositories. Different attributes allow the user

‎python/uv/private/BUILD.bazel

Copy file name to clipboardExpand all lines: python/uv/private/BUILD.bazel
+7-14Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,19 @@ bzl_library(
4747
name = "uv_bzl",
4848
srcs = ["uv.bzl"],
4949
visibility = ["//python/uv:__subpackages__"],
50-
deps = [":uv_repositories_bzl"],
51-
)
52-
53-
bzl_library(
54-
name = "uv_repositories_bzl",
55-
srcs = ["uv_repositories.bzl"],
56-
visibility = ["//python/uv:__subpackages__"],
5750
deps = [
5851
":toolchain_types_bzl",
52+
":uv_repository_bzl",
5953
":uv_toolchains_repo_bzl",
60-
":versions_bzl",
6154
],
6255
)
6356

57+
bzl_library(
58+
name = "uv_repository_bzl",
59+
srcs = ["uv_repository.bzl"],
60+
visibility = ["//python/uv:__subpackages__"],
61+
)
62+
6463
bzl_library(
6564
name = "uv_toolchain_bzl",
6665
srcs = ["uv_toolchain.bzl"],
@@ -82,9 +81,3 @@ bzl_library(
8281
"//python/private:text_util_bzl",
8382
],
8483
)
85-
86-
bzl_library(
87-
name = "versions_bzl",
88-
srcs = ["versions.bzl"],
89-
visibility = ["//python/uv:__subpackages__"],
90-
)

‎python/uv/private/lock.bzl

Copy file name to clipboardExpand all lines: python/uv/private/lock.bzl
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ def lock(*, name, srcs, out, upgrade = False, universal = True, args = [], **kwa
3030
"""Pin the requirements based on the src files.
3131
3232
Differences with the current {obj}`compile_pip_requirements` rule:
33-
- This is implemented in shell and uv.
33+
- This is implemented in shell and `uv`.
3434
- This does not error out if the output file does not exist yet.
3535
- Supports transitions out of the box.
36+
- The execution of the lock file generation is happening inside of a build
37+
action in a `genrule`.
3638
3739
Args:
3840
name: The name of the target to run for updating the requirements.
@@ -41,8 +43,8 @@ def lock(*, name, srcs, out, upgrade = False, universal = True, args = [], **kwa
4143
upgrade: Tell `uv` to always upgrade the dependencies instead of
4244
keeping them as they are.
4345
universal: Tell `uv` to generate a universal lock file.
44-
args: Extra args to pass to `uv`.
45-
**kwargs: Extra kwargs passed to the {obj}`py_binary` rule.
46+
args: Extra args to pass to the rule.
47+
**kwargs: Extra kwargs passed to the binary rule.
4648
"""
4749
pkg = native.package_name()
4850
update_target = name + ".update"

‎python/uv/private/toolchains_hub.bzl

Copy file name to clipboard
+65Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright 2025 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""A macro used from the uv_toolchain hub repo."""
16+
17+
load(":toolchain_types.bzl", "UV_TOOLCHAIN_TYPE")
18+
19+
def toolchains_hub(
20+
*,
21+
name,
22+
toolchains,
23+
implementations,
24+
target_compatible_with,
25+
target_settings):
26+
"""Define the toolchains so that the lexicographical order registration is deterministic.
27+
28+
TODO @aignas 2025-03-09: see if this can be reused in the python toolchains.
29+
30+
Args:
31+
name: The prefix to all of the targets, which goes after a numeric prefix.
32+
toolchains: The toolchain names for the targets defined by this macro.
33+
The earlier occurring items take precedence over the later items if
34+
they match the target platform and target settings.
35+
implementations: The name to label mapping.
36+
target_compatible_with: The name to target_compatible_with list mapping.
37+
target_settings: The name to target_settings list mapping.
38+
"""
39+
if len(toolchains) != len(implementations):
40+
fail("Each name must have an implementation")
41+
42+
# We are defining the toolchains so that the order of toolchain matching is
43+
# the same as the order of the toolchains, because:
44+
# * the toolchains are matched by target settings and target_compatible_with
45+
# * the first toolchain satisfying the above wins
46+
#
47+
# this means we need to register the toolchains prefixed with a number of
48+
# format 00xy, where x and y are some digits and the leading zeros to
49+
# ensure lexicographical sorting.
50+
#
51+
# Add 1 so that there is always a leading zero
52+
prefix_len = len(str(len(toolchains))) + 1
53+
prefix = "0" * (prefix_len - 1)
54+
55+
for i, toolchain in enumerate(toolchains):
56+
# prefix with a prefix and then truncate the string.
57+
number_prefix = "{}{}".format(prefix, i)[-prefix_len:]
58+
59+
native.toolchain(
60+
name = "{}_{}_{}".format(number_prefix, name, toolchain),
61+
target_compatible_with = target_compatible_with.get(toolchain, []),
62+
target_settings = target_settings.get(toolchain, []),
63+
toolchain = implementations[toolchain],
64+
toolchain_type = UV_TOOLCHAIN_TYPE,
65+
)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.