Skip to content

Commit 5639c0c

Browse files
committed
cleanup
1 parent 4189af4 commit 5639c0c

File tree

1 file changed

+179
-96
lines changed

1 file changed

+179
-96
lines changed

python/private/builders.bzl

Lines changed: 179 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,134 @@ def _DepsetBuilder_build(self):
9696
kwargs["order"] = self._order[0]
9797
return depset(direct = self.direct, transitive = self.transitive, **kwargs)
9898

99+
def _Optional(*initial):
100+
"""A wrapper for a re-assignable value that may or may not be set.
101+
102+
This allows structs to have attributes that aren't inherently mutable
103+
and must be re-assigned to have their value updated.
104+
105+
Args:
106+
*initial: A single vararg to be the initial value, or no args
107+
to leave it unset.
108+
109+
Returns:
110+
{type}`Optional`
111+
"""
112+
if len(initial) > 1:
113+
fail("Only zero or one positional arg allowed")
114+
115+
# buildifier: disable=uninitialized
116+
self = struct(
117+
_value = list(initial),
118+
present = lambda *a, **k: _Optional_present(self, *a, **k),
119+
set = lambda *a, **k: _Optional_set(self, *a, **k),
120+
get = lambda *a, **k: _Optional_get(self, *a, **k),
121+
)
122+
return self
123+
124+
def _Optional_set(self, value):
125+
"""Sets the value of the optional.
126+
127+
Args:
128+
value: the value to set.
129+
"""
130+
if len(self._value) == 0:
131+
self._value.append(value)
132+
else:
133+
self._value[0] = value
134+
135+
def _Optional_get(self):
136+
"""Gets the value of the optional, or error.
137+
138+
Returns:
139+
The stored value, or error if not set.
140+
"""
141+
if not len(self._value):
142+
fail("Value not present")
143+
return self._value[0]
144+
145+
def _Optional_present(self):
146+
"""Tells if a value is present.
147+
148+
Returns:
149+
{type}`bool` True if the value is set, False if not.
150+
"""
151+
return len(self._value) > 0
152+
153+
def _RuleBuilder(implementation = None, **kwargs):
154+
"""Builder for creating rules.
155+
156+
Args:
157+
implementation: {type}`callable` The rule implementation function.
158+
**kwargs: The same as the `rule()` function, but using builders
159+
for the non-mutable Bazel objects.
160+
"""
161+
162+
# buildifier: disable=uninitialized
163+
self = struct(
164+
attrs = dict(kwargs.pop("attrs", None) or {}),
165+
cfg = kwargs.pop("cfg", None) or _TransitionBuilder(),
166+
exec_groups = dict(kwargs.pop("exec_groups", None) or {}),
167+
executable = _Optional(),
168+
fragments = list(kwargs.pop("fragments", None) or []),
169+
implementation = _Optional(implementation),
170+
extra_kwargs = kwargs,
171+
provides = list(kwargs.pop("provides", None) or []),
172+
test = _Optional(),
173+
toolchains = list(kwargs.pop("toolchains", None) or []),
174+
build = lambda *a, **k: _RuleBuilder_build(self, *a, **k),
175+
to_kwargs = lambda *a, **k: _RuleBuilder_to_kwargs(self, *a, **k),
176+
)
177+
if "test" in kwargs:
178+
self.test.set(kwargs.pop("test"))
179+
if "executable" in kwargs:
180+
self.executable.set(kwargs.pop("executable"))
181+
return self
182+
183+
def _RuleBuilder_build(self, debug = ""):
184+
"""Builds a `rule` object
185+
186+
Args:
187+
debug: {type}`str` If set, prints the args used to create the rule.
188+
189+
Returns:
190+
{type}`rule`
191+
"""
192+
kwargs = self.to_kwargs()
193+
if debug:
194+
lines = ["=" * 80, "rule kwargs: {}:".format(debug)]
195+
for k, v in sorted(kwargs.items()):
196+
lines.append(" {}={}".format(k, v))
197+
print("\n".join(lines)) # buildifier: disable=print
198+
return rule(**kwargs)
199+
200+
def _RuleBuilder_to_kwargs(self):
201+
"""Builds the arguments for calling `rule()`.
202+
203+
Returns:
204+
{type}`dict`
205+
"""
206+
kwargs = {}
207+
if self.executable.present():
208+
kwargs["executable"] = self.executable.get()
209+
if self.test.present():
210+
kwargs["test"] = self.test.get()
211+
212+
kwargs.update(
213+
implementation = self.implementation.get(),
214+
cfg = self.cfg.build() if self.cfg.implementation.present() else None,
215+
attrs = {
216+
k: (v.build() if hasattr(v, "build") else v)
217+
for k, v in self.attrs.items()
218+
},
219+
exec_groups = self.exec_groups,
220+
fragments = self.fragments,
221+
provides = self.provides,
222+
toolchains = self.toolchains,
223+
)
224+
kwargs.update(self.extra_kwargs)
225+
return kwargs
226+
99227
def _RunfilesBuilder():
100228
"""Creates a `RunfilesBuilder`.
101229
@@ -177,41 +305,59 @@ def _RunfilesBuilder_build(self, ctx, **kwargs):
177305
**kwargs
178306
).merge_all(self.runfiles)
179307

180-
# Skylib's types module doesn't have is_file, so roll our own
181-
def _is_file(value):
182-
return type(value) == "File"
308+
def _SetBuilder(initial = None):
309+
"""Builder for list of unique values.
183310
184-
def _is_runfiles(value):
185-
return type(value) == "runfiles"
311+
Args:
312+
initial: {type}`list | None` The initial values.
186313
187-
def _Optional(*initial):
188-
if len(initial) > 1:
189-
fail("only one positional arg allowed")
314+
Returns:
315+
{type}`SetBuilder`
316+
"""
317+
initial = {} if not initial else {v: None for v in initial}
190318

191319
# buildifier: disable=uninitialized
192320
self = struct(
193-
_value = list(initial),
194-
present = lambda *a, **k: _Optional_present(self, *a, **k),
195-
set = lambda *a, **k: _Optional_set(self, *a, **k),
196-
get = lambda *a, **k: _Optional_get(self, *a, **k),
321+
# TODO - Switch this to use set() builtin when available
322+
# https://bazel.build/rules/lib/core/set
323+
_values = initial,
324+
update = lambda *a, **k: _SetBuilder_update(self, *a, **k),
325+
build = lambda *a, **k: _SetBuilder_build(self, *a, **k),
197326
)
198327
return self
199328

200-
def _Optional_set(self, v):
201-
if len(self._value) == 0:
202-
self._value.append(v)
203-
else:
204-
self._value[0] = v
329+
def _SetBuilder_build(self):
330+
"""Builds the values into a list
205331
206-
def _Optional_get(self):
207-
if not len(self._value):
208-
fail("Value not present")
209-
return self._value[0]
332+
Returns:
333+
{type}`list`
334+
"""
335+
return self._values.keys()
210336

211-
def _Optional_present(self):
212-
return len(self._value) > 0
337+
def _SetBuilder_update(self, *others):
338+
"""Adds values to the builder.
339+
340+
Args:
341+
*others: {type}`list` values to add to the set.
342+
"""
343+
for other in others:
344+
for value in other:
345+
if value not in self._values:
346+
self._values[value] = None
213347

214348
def _TransitionBuilder(implementation = None, inputs = None, outputs = None, **kwargs):
349+
"""Builder for transition objects.
350+
351+
Args:
352+
implementation: {type}`callable` the transition implementation function.
353+
inputs: {type}`list[str]` the inputs for the transition.
354+
outputs: {type}`list[str]` the outputs of the transition.
355+
**kwargs: Extra keyword args to use when building.
356+
357+
Returns:
358+
{type}`TransitionBuilder`
359+
"""
360+
215361
# buildifier: disable=uninitialized
216362
self = struct(
217363
implementation = _Optional(implementation),
@@ -231,87 +377,24 @@ def _TransitionBuilder(implementation = None, inputs = None, outputs = None, **k
231377
return self
232378

233379
def _TransitionBuilder_build(self):
380+
"""Creates a transition from the builder.
381+
382+
Returns:
383+
{type}`transition`
384+
"""
234385
return transition(
235386
implementation = self.implementation.get(),
236387
inputs = self.inputs.build(),
237388
outputs = self.outputs.build(),
238389
**self.extra_kwargs
239390
)
240391

241-
def _SetBuilder(initial = None):
242-
initial = {} if not initial else {v: None for v in initial}
243-
244-
# buildifier: disable=uninitialized
245-
self = struct(
246-
# TODO - Switch this to use set() builtin when available
247-
# https://bazel.build/rules/lib/core/set
248-
_values = initial,
249-
update = lambda *a, **k: _SetBuilder_update(self, *a, **k),
250-
build = lambda *a, **k: _SetBuilder_build(self, *a, **k),
251-
)
252-
return self
253-
254-
def _SetBuilder_build(self):
255-
return self._values.keys()
256-
257-
def _SetBuilder_update(self, *others):
258-
for other in others:
259-
for value in other:
260-
if value not in self._values:
261-
self._values[value] = None
262-
263-
def _RuleBuilder(implementation = None, **kwargs):
264-
# buildifier: disable=uninitialized
265-
self = struct(
266-
attrs = dict(kwargs.pop("attrs", None) or {}),
267-
cfg = kwargs.pop("cfg", None) or _TransitionBuilder(),
268-
exec_groups = dict(kwargs.pop("exec_groups", None) or {}),
269-
executable = _Optional(),
270-
fragments = list(kwargs.pop("fragments", None) or []),
271-
implementation = _Optional(implementation),
272-
extra_kwargs = kwargs,
273-
provides = list(kwargs.pop("provides", None) or []),
274-
test = _Optional(),
275-
toolchains = list(kwargs.pop("toolchains", None) or []),
276-
build = lambda *a, **k: _RuleBuilder_build(self, *a, **k),
277-
to_kwargs = lambda *a, **k: _RuleBuilder_to_kwargs(self, *a, **k),
278-
)
279-
if "test" in kwargs:
280-
self.test.set(kwargs.pop("test"))
281-
if "executable" in kwargs:
282-
self.executable.set(kwargs.pop("executable"))
283-
return self
284-
285-
def _RuleBuilder_build(self, debug = ""):
286-
kwargs = self.to_kwargs()
287-
if debug:
288-
lines = ["=" * 80, "rule kwargs: {}:".format(debug)]
289-
for k, v in sorted(kwargs.items()):
290-
lines.append(" {}={}".format(k, v))
291-
print("\n".join(lines)) # buildifier: disable=print
292-
return rule(**kwargs)
293-
294-
def _RuleBuilder_to_kwargs(self):
295-
kwargs = {}
296-
if self.executable.present():
297-
kwargs["executable"] = self.executable.get()
298-
if self.test.present():
299-
kwargs["test"] = self.test.get()
392+
# Skylib's types module doesn't have is_file, so roll our own
393+
def _is_file(value):
394+
return type(value) == "File"
300395

301-
kwargs.update(
302-
implementation = self.implementation.get(),
303-
cfg = self.cfg.build(),
304-
attrs = {
305-
k: (v.build() if hasattr(v, "build") else v)
306-
for k, v in self.attrs.items()
307-
},
308-
exec_groups = self.exec_groups,
309-
fragments = self.fragments,
310-
provides = self.provides,
311-
toolchains = self.toolchains,
312-
)
313-
kwargs.update(self.extra_kwargs)
314-
return kwargs
396+
def _is_runfiles(value):
397+
return type(value) == "runfiles"
315398

316399
builders = struct(
317400
DepsetBuilder = _DepsetBuilder,

0 commit comments

Comments
 (0)