@@ -30,18 +30,18 @@ def _impl(ctx):
3030 # TODO @aignas 2025-03-02: create an executable file here that is using a
3131 # python and uv toolchains.
3232
33- if ctx .files .src_outs :
33+ if ctx .files .maybe_out :
3434 args .add_all ([
3535 "--src-out" ,
36- ctx .files .src_outs [0 ].path ,
36+ ctx .files .maybe_out [0 ].path ,
3737 ])
3838 args .add ("--output-file" , ctx .outputs .out )
3939 args .add_all (ctx .files .srcs )
4040
4141 ctx .actions .run (
4242 executable = ctx .executable .cmd ,
4343 mnemonic = "RulesPythonLock" ,
44- inputs = ctx .files .srcs + ctx .files .src_outs ,
44+ inputs = ctx .files .srcs + ctx .files .maybe_out ,
4545 outputs = [
4646 ctx .outputs .out ,
4747 ],
@@ -59,19 +59,15 @@ _lock = rule(
5959 """ ,
6060 attrs = {
6161 "args" : attr .string_list (),
62- "cmd" : attr .label (
63- mandatory = True ,
64- executable = True ,
65- cfg = "target" ,
66- ),
62+ "cmd" : attr .label (mandatory = True , executable = True , cfg = "target" ),
6763 "env" : attr .string_dict (),
64+ "maybe_out" : attr .label (mandatory = False , allow_single_file = True ),
6865 "out" : attr .output (mandatory = True ),
69- "src_outs" : attr .label_list (mandatory = True , allow_files = True ),
7066 "srcs" : attr .label_list (mandatory = True , allow_files = True ),
7167 },
7268)
7369
74- def _glob (path ):
70+ def _maybe_file (path ):
7571 """A small function to return a list of existing outputs.
7672
7773 If the file referenced by the input argument exists, then it will return
@@ -86,9 +82,9 @@ def _glob(path):
8682 """
8783 for p in native .glob ([path ], allow_empty = True ):
8884 if path == p :
89- return [ p ]
85+ return p
9086
91- return []
87+ return None
9288
9389def lock (* , name , srcs , out , args = [], ** kwargs ):
9490 """Pin the requirements based on the src files.
@@ -125,13 +121,13 @@ def lock(*, name, srcs, out, args = [], **kwargs):
125121 args += user_args
126122
127123 run_args = []
128- existing_outputs = _glob (out )
129- if existing_outputs :
124+ maybe_out = _maybe_file (out )
125+ if maybe_out :
130126 # This means that the output file already exists and it should be used
131127 # to create a new file. This will be taken care by the locker tool.
132128 #
133129 # 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 ] )]
130+ run_args += ["--output-file" , "$(rootpath {})" .format (maybe_out )]
135131 else :
136132 # TODO @aignas 2025-03-02: pass the output as a string
137133 run_out = "{}/{}" .format (pkg , out )
@@ -159,7 +155,7 @@ def lock(*, name, srcs, out, args = [], **kwargs):
159155 srcs = [locker_target + ".py" ],
160156 data = [
161157 "//python/uv:current_toolchain" ,
162- ] + srcs + existing_outputs ,
158+ ] + srcs + ([ maybe_out ] if maybe_out else []) ,
163159 args = run_args ,
164160 tags = ["manual" ],
165161 deps = ["//python/runfiles" ],
@@ -171,7 +167,7 @@ def lock(*, name, srcs, out, args = [], **kwargs):
171167 # Check if the output file already exists, if yes, first copy it to the
172168 # output file location in order to make `uv` not change the requirements if
173169 # we are just running the command.
174- src_outs = existing_outputs ,
170+ maybe_out = maybe_out ,
175171 out = out + ".new" ,
176172 tags = [
177173 "local" ,
@@ -183,11 +179,11 @@ def lock(*, name, srcs, out, args = [], **kwargs):
183179 cmd = locker_target ,
184180 )
185181
186- if existing_outputs :
182+ if maybe_out :
187183 diff_test (
188184 name = name + "_test" ,
189185 file1 = out + ".new" ,
190- file2 = existing_outputs [ 0 ] ,
186+ file2 = maybe_out ,
191187 tags = ["manual" ],
192188 )
193189
0 commit comments