@@ -30,18 +30,18 @@ def _impl(ctx):
30
30
# TODO @aignas 2025-03-02: create an executable file here that is using a
31
31
# python and uv toolchains.
32
32
33
- if ctx .files .src_outs :
33
+ if ctx .files .maybe_out :
34
34
args .add_all ([
35
35
"--src-out" ,
36
- ctx .files .src_outs [0 ].path ,
36
+ ctx .files .maybe_out [0 ].path ,
37
37
])
38
38
args .add ("--output-file" , ctx .outputs .out )
39
39
args .add_all (ctx .files .srcs )
40
40
41
41
ctx .actions .run (
42
42
executable = ctx .executable .cmd ,
43
43
mnemonic = "RulesPythonLock" ,
44
- inputs = ctx .files .srcs + ctx .files .src_outs ,
44
+ inputs = ctx .files .srcs + ctx .files .maybe_out ,
45
45
outputs = [
46
46
ctx .outputs .out ,
47
47
],
@@ -65,31 +65,12 @@ _lock = rule(
65
65
cfg = "target" ,
66
66
),
67
67
"env" : attr .string_dict (),
68
+ "maybe_out" : attr .label (allow_single_file = True ),
68
69
"out" : attr .output (mandatory = True ),
69
- "src_outs" : attr .label_list (mandatory = True , allow_files = True ),
70
70
"srcs" : attr .label_list (mandatory = True , allow_files = True ),
71
71
},
72
72
)
73
73
74
- def _glob (path ):
75
- """A small function to return a list of existing outputs.
76
-
77
- If the file referenced by the input argument exists, then it will return
78
- it, otherwise it will return an empty list. This is useful to for programs
79
- like pip-compile which behave differently if the output file exists and
80
- update the output file in place.
81
-
82
- The API of the function ensures that path is not a glob itself.
83
-
84
- Args:
85
- path: {type}`str` the file name.
86
- """
87
- for p in native .glob ([path ], allow_empty = True ):
88
- if path == p :
89
- return [p ]
90
-
91
- return []
92
-
93
74
def lock (* , name , srcs , out , args = [], ** kwargs ):
94
75
"""Pin the requirements based on the src files.
95
76
@@ -125,13 +106,13 @@ def lock(*, name, srcs, out, args = [], **kwargs):
125
106
args += user_args
126
107
127
108
run_args = []
128
- existing_outputs = _glob (out )
129
- if existing_outputs :
109
+ maybe_out = _maybe_path (out )
110
+ if maybe_out :
130
111
# This means that the output file already exists and it should be used
131
112
# to create a new file. This will be taken care by the locker tool.
132
113
#
133
114
# TODO @aignas 2025-03-02: similarly to sphinx rule, expand the output to short_path
134
- run_args += ["--output-file" , "$(rootpath {})" .format (existing_outputs [ 0 ] )]
115
+ run_args += ["--output-file" , "$(rootpath {})" .format (maybe_out )]
135
116
else :
136
117
# TODO @aignas 2025-03-02: pass the output as a string
137
118
run_out = "{}/{}" .format (pkg , out )
@@ -159,7 +140,7 @@ def lock(*, name, srcs, out, args = [], **kwargs):
159
140
srcs = [locker_target + ".py" ],
160
141
data = [
161
142
"//python/uv:current_toolchain" ,
162
- ] + srcs + existing_outputs ,
143
+ ] + srcs + ([ maybe_out ] if maybe_out else []) ,
163
144
args = run_args ,
164
145
tags = ["manual" ],
165
146
deps = ["//python/runfiles" ],
@@ -171,7 +152,7 @@ def lock(*, name, srcs, out, args = [], **kwargs):
171
152
# Check if the output file already exists, if yes, first copy it to the
172
153
# output file location in order to make `uv` not change the requirements if
173
154
# we are just running the command.
174
- src_outs = existing_outputs ,
155
+ maybe_out = maybe_out ,
175
156
out = out + ".new" ,
176
157
tags = [
177
158
"local" ,
@@ -183,11 +164,11 @@ def lock(*, name, srcs, out, args = [], **kwargs):
183
164
cmd = locker_target ,
184
165
)
185
166
186
- if existing_outputs :
167
+ if maybe_out :
187
168
diff_test (
188
169
name = name + "_test" ,
189
170
file1 = out + ".new" ,
190
- file2 = existing_outputs [ 0 ] ,
171
+ file2 = maybe_out ,
191
172
tags = ["manual" ],
192
173
)
193
174
@@ -212,3 +193,22 @@ def lock(*, name, srcs, out, args = [], **kwargs):
212
193
tags = ["manual" ],
213
194
** kwargs
214
195
)
196
+
197
+ def _maybe_path (path ):
198
+ """A small function to return a list of existing outputs.
199
+
200
+ If the file referenced by the input argument exists, then it will return
201
+ it, otherwise it will return an empty list. This is useful to for programs
202
+ like pip-compile which behave differently if the output file exists and
203
+ update the output file in place.
204
+
205
+ The API of the function ensures that path is not a glob itself.
206
+
207
+ Args:
208
+ path: {type}`str` the file name.
209
+ """
210
+ for p in native .glob ([path ], allow_empty = True ):
211
+ if path == p :
212
+ return p
213
+
214
+ return None
0 commit comments