Skip to content

Commit a79827e

Browse files
committed
comment: address review comments
- Improve the CHANGELOG wording. - Rename `pin` to `lock` and set the load visibility to internal. - Retain the same naming convention of `requirements.update`. - Use `py_binary` with the transitions. - Add a simple validation to the `mrctx.watch` wrapping.
1 parent 2bcb7f8 commit a79827e

File tree

6 files changed

+43
-97
lines changed

6 files changed

+43
-97
lines changed

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ A brief description of the categories of changes:
3737
* Nothing yet
3838

3939
### Fixed
40-
* (bzlmod) get the path to the host python interpreter without calling
41-
`mctx.path` on Labels that have differing contents on different OSes.
42-
* (bzlmod) correctly watch sources when using `pypi_repo_utils`.
40+
* (bzlmod) get the path to the host python interpreter in a way that results in
41+
platform non-dependent hashes in the lock file when the requirement markers need
42+
to be evaluated.
43+
* (bzlmod) correctly watch sources used for evaluating requirement markers for
44+
any changes so that the repository rule or module extensions can be
45+
re-evaluated when the said files change.
4346

4447
## [0.35.0] - 2024-08-15
4548

docs/BUILD.bazel

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
1616
load("@dev_pip//:requirements.bzl", "requirement")
1717
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
1818
load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") # buildifier: disable=bzl-visibility
19-
load("//python/uv/private:pin.bzl", "pin") # buildifier: disable=bzl-visibility
19+
load("//python/uv/private:lock.bzl", "lock") # buildifier: disable=bzl-visibility
2020
load("//sphinxdocs:readthedocs.bzl", "readthedocs_install")
2121
load("//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
2222
load("//sphinxdocs:sphinx_stardoc.bzl", "sphinx_stardoc", "sphinx_stardocs")
@@ -139,9 +139,9 @@ sphinx_build_binary(
139139
],
140140
)
141141

142-
# Run bazel run //docs:requirements_update
143-
pin(
144-
name = "requirements_update",
142+
# Run bazel run //docs:requirements.update
143+
lock(
144+
name = "requirements",
145145
srcs = ["pyproject.toml"],
146146
out = "requirements.txt",
147147
upgrade = True,

examples/BUILD.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
# limitations under the License.
1414

1515
# The following is experimental API and currently not intended for use outside this example.
16-
load("@rules_python//python/uv/private:pin.bzl", "pin") # buildifier: disable=bzl-visibility
16+
load("@rules_python//python/uv/private:lock.bzl", "lock") # buildifier: disable=bzl-visibility
1717

1818
licenses(["notice"]) # Apache 2.0
1919

20-
pin(
21-
name = "bzlmod_requirements_3_9_update",
20+
lock(
21+
name = "bzlmod_requirements_3_9",
2222
srcs = ["bzlmod/requirements.in"],
2323
out = "bzlmod/requirements_lock_3_9.txt",
2424
python_version = "3.9.19",

examples/bzlmod/requirements_lock_3_9.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# This file was autogenerated by uv via the following command:
2-
# bazel run //examples:bzlmod_requirements_3_9_update
2+
# bazel run //examples:bzlmod_requirements_3_9.update
33
--index-url https://pypi.org/simple
44
--extra-index-url https://pypi.org/simple/
55

python/private/repo_utils.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,12 +404,18 @@ def _get_platforms_cpu_name(mrctx):
404404
# TODO: Remove after Bazel 6 support dropped
405405
def _watch(mrctx, *args, **kwargs):
406406
"""Calls mrctx.watch, if available."""
407+
if not args and not kwargs:
408+
fail("'watch' needs at least a single argument.")
409+
407410
if hasattr(mrctx, "watch"):
408411
mrctx.watch(*args, **kwargs)
409412

410413
# TODO: Remove after Bazel 6 support dropped
411414
def _watch_tree(mrctx, *args, **kwargs):
412415
"""Calls mrctx.watch_tree, if available."""
416+
if not args and not kwargs:
417+
fail("'watch_tree' needs at least a single argument.")
418+
413419
if hasattr(mrctx, "watch_tree"):
414420
mrctx.watch_tree(*args, **kwargs)
415421

python/uv/private/pin.bzl renamed to python/uv/private/lock.bzl

Lines changed: 23 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,19 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"""A simple macro to pin the requirements.
15+
"""A simple macro to lock the requirements.
1616
"""
1717

1818
load("@bazel_skylib//rules:write_file.bzl", "write_file")
1919
load("//python:py_binary.bzl", "py_binary")
20+
load("//python/config_settings:transition.bzl", transition_py_binary = "py_binary")
2021
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
2122

22-
_REQUIREMENTS_TARGET_COMPATIBLE_WITH = select({
23-
"@platforms//os:linux": [],
24-
"@platforms//os:macos": [],
25-
"//conditions:default": ["@platforms//:incompatible"],
26-
}) if BZLMOD_ENABLED else ["@platforms//:incompatible"]
23+
visibility(["//..."])
2724

28-
def pin(*, name, srcs, out, upgrade = False, universal = True, python_version = None):
25+
_REQUIREMENTS_TARGET_COMPATIBLE_WITH = [] if BZLMOD_ENABLED else ["@platforms//:incompatible"]
26+
27+
def lock(*, name, srcs, out, upgrade = False, universal = True, python_version = None):
2928
"""Pin the requirements based on the src files.
3029
3130
Args:
@@ -44,24 +43,23 @@ def pin(*, name, srcs, out, upgrade = False, universal = True, python_version =
4443
- Supports transitions out of the box.
4544
"""
4645
pkg = native.package_name()
47-
_out = "_" + out
46+
update_target = name + ".update"
4847

4948
args = [
50-
"--custom-compile-command='bazel run //{}:{}'".format(pkg, name),
49+
"--custom-compile-command='bazel run //{}:{}'".format(pkg, update_target),
5150
"--generate-hashes",
5251
"--emit-index-url",
5352
"--no-strip-extras",
5453
"--python=$(PYTHON3)",
5554
] + [
5655
"$(location {})".format(src)
5756
for src in srcs
58-
] + [
59-
"--output-file=$(location {})".format(_out),
6057
]
6158
if upgrade:
6259
args.append("--upgrade")
6360
if universal:
6461
args.append("--universal")
62+
args.append("--output-file=$@")
6563
cmd = "$(UV_BIN) pip compile " + " ".join(args)
6664

6765
# Check if the output file already exists, if yes, first copy it to the
@@ -72,9 +70,9 @@ def pin(*, name, srcs, out, upgrade = False, universal = True, python_version =
7270
srcs.append(out)
7371

7472
native.genrule(
75-
name = name + ".uv.out",
73+
name = name,
7674
srcs = srcs,
77-
outs = [_out],
75+
outs = [out + ".new"],
7876
cmd_bash = cmd,
7977
tags = [
8078
"local",
@@ -88,97 +86,36 @@ def pin(*, name, srcs, out, upgrade = False, universal = True, python_version =
8886
],
8987
)
9088
if python_version:
91-
transitioned_name = "{}.uv.out.{}".format(name, python_version)
92-
_versioned(
93-
name = transitioned_name,
94-
src = _out,
95-
python_version = python_version,
96-
tags = ["manual"],
97-
)
98-
_out = transitioned_name
89+
py_binary_rule = lambda *args, **kwargs: transition_py_binary(python_version = python_version, *args, **kwargs)
90+
else:
91+
py_binary_rule = py_binary
9992

10093
# Write a script that can be used for updating the in-tree version of the
10194
# requirements file
10295
write_file(
103-
name = name + ".gen",
104-
out = name + ".gen.py",
96+
name = name + ".update_gen",
97+
out = update_target + ".py",
10598
content = [
10699
"from os import environ",
107100
"from pathlib import Path",
108101
"from sys import stderr",
109102
"",
110103
'src = Path(environ["REQUIREMENTS_FILE"])',
104+
'assert src.exists(), f"the {src} file does not exist"',
111105
'dst = Path(environ["BUILD_WORKSPACE_DIRECTORY"]) / "{}" / "{}"'.format(pkg, out),
112106
'print(f"Writing requirements contents\\n from {src.absolute()}\\n to {dst.absolute()}", file=stderr)',
113107
"dst.write_text(src.read_text())",
114108
'print("Success!", file=stderr)',
115109
],
116-
target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
117110
)
118111

119-
py_binary(
120-
name = name,
121-
srcs = [name + ".gen.py"],
122-
main = name + ".gen.py",
123-
data = [_out],
112+
py_binary_rule(
113+
name = update_target,
114+
srcs = [update_target + ".py"],
115+
main = update_target + ".py",
116+
data = [name],
124117
env = {
125-
"REQUIREMENTS_FILE": "$(location {})".format(_out),
118+
"REQUIREMENTS_FILE": "$(rootpath {})".format(name),
126119
},
127120
tags = ["manual"],
128-
target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
129121
)
130-
131-
def _transition_python_version_impl(_, attr):
132-
return {"//python/config_settings:python_version": str(attr.python_version)}
133-
134-
_transition_python_version = transition(
135-
implementation = _transition_python_version_impl,
136-
inputs = [],
137-
outputs = ["//python/config_settings:python_version"],
138-
)
139-
140-
def _impl(ctx):
141-
target = ctx.attr.src
142-
143-
default_info = target[0][DefaultInfo]
144-
files = default_info.files
145-
original_executable = default_info.files_to_run.executable
146-
runfiles = default_info.default_runfiles
147-
148-
new_executable = ctx.actions.declare_file(ctx.attr.name)
149-
150-
ctx.actions.symlink(
151-
output = new_executable,
152-
target_file = original_executable,
153-
is_executable = True,
154-
)
155-
156-
files = depset(direct = [new_executable], transitive = [files])
157-
runfiles = runfiles.merge(ctx.runfiles([new_executable]))
158-
159-
return [
160-
DefaultInfo(
161-
files = files,
162-
runfiles = runfiles,
163-
executable = new_executable,
164-
),
165-
]
166-
167-
_versioned = rule(
168-
implementation = _impl,
169-
attrs = {
170-
"python_version": attr.string(
171-
mandatory = True,
172-
),
173-
"src": attr.label(
174-
allow_single_file = True,
175-
executable = False,
176-
mandatory = True,
177-
cfg = _transition_python_version,
178-
),
179-
"_allowlist_function_transition": attr.label(
180-
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
181-
),
182-
},
183-
executable = True,
184-
)

0 commit comments

Comments
 (0)