Skip to content

Commit 4442b12

Browse files
committed
wip
1 parent 1fd9953 commit 4442b12

File tree

3 files changed

+64
-81
lines changed

3 files changed

+64
-81
lines changed

docs/requirements.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ alabaster==1.0.0 \
1010
--hash=sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e \
1111
--hash=sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b
1212
# via sphinx
13-
astroid==3.3.8 \
14-
--hash=sha256:187ccc0c248bfbba564826c26f070494f7bc964fd286b6d9fff4420e55de828c \
15-
--hash=sha256:a88c7994f914a4ea8572fac479459f4955eeccc877be3f2d959a33273b0cf40b
13+
astroid==3.3.9 \
14+
--hash=sha256:622cc8e3048684aa42c820d9d218978021c3c3d174fb03a9f0d615921744f550 \
15+
--hash=sha256:d05bfd0acba96a7bd43e222828b7d9bc1e138aaeb0649707908d3702a9831248
1616
# via sphinx-autodoc2
1717
babel==2.17.0 \
1818
--hash=sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d \
@@ -135,9 +135,9 @@ imagesize==1.4.1 \
135135
--hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \
136136
--hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a
137137
# via sphinx
138-
jinja2==3.1.5 \
139-
--hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \
140-
--hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb
138+
jinja2==3.1.6 \
139+
--hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
140+
--hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
141141
# via
142142
# myst-parser
143143
# readthedocs-sphinx-ext
@@ -306,9 +306,9 @@ snowballstemmer==2.2.0 \
306306
--hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \
307307
--hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a
308308
# via sphinx
309-
sphinx==8.2.1 \
310-
--hash=sha256:b5d2bb3cdf6207fcacde9f92085d2b97667b05b9c346eaec426ca4be8af505e9 \
311-
--hash=sha256:e4b932951b9c18b039f73b72e4e63afe967d90408700ec222b981ac24647c01e
309+
sphinx==8.2.3 \
310+
--hash=sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348 \
311+
--hash=sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3
312312
# via
313313
# rules-python-docs (docs/pyproject.toml)
314314
# myst-parser

python/uv/private/lock.bzl

Lines changed: 53 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"""
1717

1818
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
19-
load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
2019
load("@bazel_skylib//rules:write_file.bzl", "write_file")
2120
load("//python:py_binary.bzl", "py_binary")
2221
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
@@ -25,17 +24,6 @@ visibility(["//..."])
2524

2625
_REQUIREMENTS_TARGET_COMPATIBLE_WITH = [] if BZLMOD_ENABLED else ["@platforms//:incompatible"]
2726

28-
_RunLockInfo = provider(
29-
doc = "Information for running the underlying Sphinx command directly",
30-
fields = {
31-
"cmd": """
32-
:type: Target
33-
34-
The locker binary to run.
35-
""",
36-
},
37-
)
38-
3927
def _impl(ctx):
4028
args = ctx.actions.args()
4129

@@ -47,15 +35,12 @@ def _impl(ctx):
4735
ctx.files.src_outs[0].path,
4836
])
4937
args.add("--output-file", ctx.outputs.out)
50-
51-
# TODO @aignas 2025-03-02: add the following deps to _RunLockInfo
52-
srcs = ctx.files.srcs + ctx.files.src_outs
5338
args.add_all(ctx.files.srcs)
5439

5540
ctx.actions.run(
5641
executable = ctx.executable.cmd,
5742
mnemonic = "RulesPythonLock",
58-
inputs = srcs,
43+
inputs = ctx.files.srcs + ctx.files.src_outs,
5944
outputs = [
6045
ctx.outputs.out,
6146
],
@@ -67,10 +52,7 @@ def _impl(ctx):
6752
env = ctx.attr.env,
6853
)
6954

70-
return [
71-
DefaultInfo(files = depset([ctx.outputs.out])),
72-
_RunLockInfo(cmd = ctx.executable.cmd),
73-
]
55+
return [DefaultInfo(files = depset([ctx.outputs.out]))]
7456

7557
_lock = rule(
7658
implementation = _impl,
@@ -79,7 +61,7 @@ _lock = rule(
7961
attrs = {
8062
"args": attr.string_list(),
8163
"cmd": attr.label(
82-
default = "//python/uv/private:pip_compile",
64+
mandatory = True,
8365
executable = True,
8466
cfg = "target",
8567
),
@@ -90,6 +72,25 @@ _lock = rule(
9072
},
9173
)
9274

75+
def _glob(path):
76+
"""A small function to return a list of existing outputs.
77+
78+
If the file referenced by the input argument exists, then it will return
79+
it, otherwise it will return an empty list. This is useful to for programs
80+
like pip-compile which behave differently if the output file exists and
81+
update the output file in place.
82+
83+
The API of the function ensures that path is not a glob itself.
84+
85+
Args:
86+
path: {type}`str` the file name.
87+
"""
88+
for p in native.glob([path], allow_empty = True):
89+
if path == p:
90+
return [p]
91+
92+
return []
93+
9394
def lock(*, name, srcs, out, args = [], **kwargs):
9495
"""Pin the requirements based on the src files.
9596
@@ -108,17 +109,11 @@ def lock(*, name, srcs, out, args = [], **kwargs):
108109
**kwargs: Extra kwargs passed to the {obj}`py_binary` rule.
109110
"""
110111
pkg = native.package_name()
111-
update_target = name + ".update"
112-
113-
user_args = args
114-
115-
existing_outputs = []
116-
for path in native.glob([out], allow_empty = True):
117-
if path == out:
118-
existing_outputs = [out]
119-
break
112+
update_target = "{}.update".format(name)
113+
locker_target = "{}.run".format(name)
120114

121115
# TODO @aignas 2025-03-02: move the following args to a template expansion action
116+
user_args = args
122117
args = [
123118
# FIXME @aignas 2025-03-02: this acts differently in native_binary and the rule
124119
"--custom-compile-command='bazel run //{}:{}'".format(pkg, update_target),
@@ -129,10 +124,30 @@ def lock(*, name, srcs, out, args = [], **kwargs):
129124
"--no-cache",
130125
]
131126
args += user_args
127+
run_args = []
128+
129+
existing_outputs = _glob(out)
130+
if existing_outputs:
131+
# This means that the output file already exists and it should be used
132+
# to create a new file. This will be taken care by the locker tool.
133+
#
134+
# TODO @aignas 2025-03-02: similarly to sphinx rule, expand the output to short_path
135+
run_args += ["--output-file", "$(rootpath {})".format(existing_outputs[0])]
136+
else:
137+
# TODO @aignas 2025-03-02: pass the output as a string
138+
run_out = "{}/{}".format(pkg, out)
139+
run_args += ["--output-file", run_out]
140+
141+
# args just get passed as is
142+
run_args += [
143+
# TODO @aignas 2025-03-02: get the full source location for these
144+
"$(rootpath {})".format(s)
145+
for s in srcs
146+
]
132147

133148
expand_template(
134-
name = name + "_locker_src",
135-
out = name + "_locker.py",
149+
name = locker_target + "_gen",
150+
out = locker_target + ".py",
136151
template = "//python/uv/private:pip_compile.py",
137152
substitutions = {
138153
" args = []": " args = " + repr(args),
@@ -141,11 +156,12 @@ def lock(*, name, srcs, out, args = [], **kwargs):
141156
)
142157

143158
py_binary(
144-
name = name + "_locker",
145-
srcs = [name + "_locker.py"],
159+
name = locker_target,
160+
srcs = [locker_target + ".py"],
146161
data = [
147162
"//python/uv:current_toolchain",
148-
],
163+
] + srcs + existing_outputs,
164+
args = run_args,
149165
tags = ["manual"],
150166
deps = ["//python/runfiles"],
151167
)
@@ -165,45 +181,13 @@ def lock(*, name, srcs, out, args = [], **kwargs):
165181
],
166182
args = args,
167183
target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
168-
cmd = name + "_locker",
169-
)
170-
171-
run_args = []
172-
if existing_outputs:
173-
# This means that the output file already exists and it should be used
174-
# to create a new file. This will be taken care by the locker tool.
175-
#
176-
# TODO @aignas 2025-03-02: similarly to sphinx rule, expand the output to short_path
177-
run_args += ["--output-file", "$(location {})".format(existing_outputs[0])]
178-
else:
179-
# TODO @aignas 2025-03-02: pass the output as a string
180-
run_out = "{}/{}".format(pkg, out)
181-
run_args += ["--output-file", run_out]
182-
183-
# args just get passed as is
184-
run_args += args + [
185-
# TODO @aignas 2025-03-02: get the full source location for these
186-
"$(location {})".format(s)
187-
for s in srcs
188-
]
189-
190-
native_binary(
191-
# this is expand_template using the stuff from the provider from the _lock rule
192-
name = name + ".run",
193-
args = run_args, # the main difference is the expansion of args here
194-
data = srcs + existing_outputs, # This only depends on inputs to the _lock
195-
src = "//python/uv/private:pip_compile",
196-
tags = [
197-
"local",
198-
"manual",
199-
"no-cache",
200-
],
184+
cmd = locker_target,
201185
)
202186

203187
# Write a script that can be used for updating the in-tree version of the
204188
# requirements file
205189
write_file(
206-
name = name + ".update_gen",
190+
name = update_target + "_gen",
207191
out = update_target + ".py",
208192
content = [
209193
"from os import environ",

python/uv/private/pip_compile.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ def _run() -> None:
3232
else:
3333
out = sys_args[1]
3434

35-
srcs = sys_args[2:]
36-
3735
# this is set under bazel run
3836
workspace = env.get("BUILD_WORKSPACE_DIRECTORY")
3937
if workspace:
@@ -44,8 +42,9 @@ def _run() -> None:
4442
import shutil
4543

4644
shutil.copy(src, dst)
45+
sys_args[1] = str(dst)
4746

48-
uv_args = ["pip", "compile"] + args + srcs + ["--output-file", str(dst)]
47+
uv_args = ["pip", "compile"] + args + sys_args
4948

5049
if sys.platform == "win32":
5150
import subprocess

0 commit comments

Comments
 (0)