Skip to content

Commit 4078dd4

Browse files
committed
fix(op): re-introduce op_needs to preseve duplicity in fn-args; ...
doc: explain at last in details Op's dep-attributes.
1 parent 17d71bb commit 4078dd4

File tree

4 files changed

+50
-33
lines changed

4 files changed

+50
-33
lines changed

graphtik/modifiers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,11 @@ class sol_sideffect(sideffect):
361361
FunctionalOperation(name='finalize_prices',
362362
needs=["sol_sideffect('ORDER'<--'Prices'",
363363
"sol_sideffect('ORDER'<--'VAT'"],
364+
op_needs=["sol_sideffect('ORDER'<--'Prices'",
365+
"sol_sideffect('ORDER'<--'VAT'"],
366+
fn_needs=['ORDER'],
364367
provides=["sol_sideffect('ORDER'<--'Totals'"],
365368
op_provides=["sol_sideffect('ORDER'<--'Totals'"],
366-
fn_needs=['ORDER'],
367369
fn_provides=['ORDER'],
368370
fn='finalize_prices')
369371

graphtik/network.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ def _append_operation(self, graph, operation: Operation):
980980
#
981981
needs = []
982982
needs_edges = []
983-
for n in operation.needs:
983+
for n in getattr(operation, "op_needs", operation.needs):
984984
nkw, ekw = {}, {}
985985
if isinstance(n, (optional, vararg, varargs)):
986986
ekw["optional"] = True

graphtik/op.py

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ def strip_sideffecteds(dep):
168168
assert deps is not None
169169

170170
if deps:
171-
op_deps = iset(nn for n in deps for nn in singularize_sol_sideffects(n))
171+
deps = tuple(nn for n in deps for nn in singularize_sol_sideffects(n))
172172
fn_deps = tuple(nn for n in deps for nn in strip_sideffecteds(n))
173-
return op_deps, fn_deps
173+
return deps, fn_deps
174174
else:
175175
return deps, deps
176176

@@ -228,23 +228,24 @@ def __init__(
228228
name, needs, provides = reparse_operation_data(name, needs, provides)
229229

230230
needs, _fn_needs = _spread_sideffects(needs)
231-
op_provides, _fn_provides = _spread_sideffects(provides)
231+
provides, _fn_provides = _spread_sideffects(provides)
232+
op_needs = iset(needs)
232233

233234
if aliases:
234235
aliases = as_renames(aliases, "aliases")
235-
if any(1 for src, dst in aliases if dst in op_provides):
236+
if any(1 for src, dst in aliases if dst in provides):
236237
bad = ", ".join(
237-
f"{src} -> {dst}" for src, dst in aliases if dst in op_provides
238+
f"{src} -> {dst}" for src, dst in aliases if dst in provides
238239
)
239240
raise ValueError(
240-
f"The `aliases` ({bad}) clash with existing provides {list(op_provides)}!"
241+
f"The `aliases` ({bad}) clash with existing provides {list(provides)}!"
241242
)
242243

243244
alias_src, alias_dst = list(zip(*aliases))
244-
if not set(alias_src) <= set(op_provides):
245+
if not set(alias_src) <= set(provides):
245246
raise ValueError(
246-
f"The `aliases` for {list(alias_src)} rename {list(iset(alias_src) - op_provides)}"
247-
f", not found in op_provides {list(op_provides)}!"
247+
f"The `aliases` for {list(alias_src)} rename {list(iset(alias_src) - provides)}"
248+
f", not found in provides {list(provides)}!"
248249
)
249250
sfx_aliases = [
250251
f"{src} -> {dst}"
@@ -256,28 +257,39 @@ def __init__(
256257
f"The `aliases` must not contain `sideffects` {sfx_aliases}"
257258
"\n Simply add any extra `sideffects` in the `provides`."
258259
)
259-
provides = op_provides
260-
op_provides = iset(itt.chain(op_provides, alias_dst))
260+
else:
261+
alias_dst = ()
262+
op_provides = iset(itt.chain(provides, alias_dst))
261263

262264
self.fn = fn
263265
#: a name for the operation (e.g. `'conv1'`, `'sum'`, etc..);
264266
#: it will be prefixed by `parents`.
265267
self.name = name
266-
#: The :term:`needs` roughly as given by the user,
267-
#: ready to :term:`prune` the graph
268-
#: (with sideffects & singular sol_sideffects)
268+
269+
#: The :term:`needs` almost as given by the user
270+
#: (which may contain MULTI-sol_sideffects and dupes),
271+
#: roughly morphed into `_fn_provides` + sideffects
272+
#: (dupes preserved, with sideffects & SINGULARIZED sol_sideffects).
273+
#: It is stored for builder functionality to work.
269274
self.needs = needs
275+
#: Value names ready to lay the graph for :term:`pruning`
276+
#: (NO dupes, WITH aliases & sideffects, and SINGULAR sol_sideffects).
277+
self.op_needs = op_needs
270278
#: Value names the underlying function requires
271-
#: (without sideffects, with stripped `sideffected` dependencies).
279+
#: (dupes preserved, without sideffects, with stripped `sideffected` dependencies).
272280
self._fn_needs = _fn_needs
273-
#: The :term:`provides` roughly as given by the user
274-
#: (without aliases, with sideffects & singular sol_sideffects)
281+
282+
#: The :term:`provides` almost as given by the user,
283+
#: (which may contain MULTI-sol_sideffects and dupes),
284+
#: roughly morphed into `_fn_provides` + sideffects
285+
#: (dupes preserved, without aliases, with sideffects & SINGULARIZED sol_sideffects).
286+
#: It is stored for builder functionality to work.
275287
self.provides = provides
276-
#: Value names ready to :term:`prune` the graph
277-
#: (WITH aliases, sideffects & singular sol_sideffects).
288+
#: Value names ready to lay the graph for :term:`pruning`
289+
#: (NO dupes, WITH aliases & sideffects, and SINGULAR sol_sideffects).
278290
self.op_provides = op_provides
279291
#: Value names the underlying function produces
280-
#: (without aliases & sideffects, with stripped `sideffected` dependencies).
292+
#: (dupes preserved, without aliases & sideffects, with stripped `sideffected` dependencies).
281293
self._fn_provides = _fn_provides
282294
#: an optional mapping of `fn_provides` to additional ones, together
283295
#: comprising this operations :term:`op_provides`.
@@ -339,16 +351,16 @@ def __repr__(self):
339351
marshalled = "$" if self.marshalled else ""
340352

341353
if is_debug():
342-
deps = (
343-
f", op_provides={list(self.op_provides)}, "
344-
f"fn_needs={list(self._fn_needs)}, "
345-
f"fn_provides={list(self._fn_provides)}"
354+
debug_needs = (
355+
f", op_needs={list(self.op_needs)}, fn_needs={list(self._fn_needs)}"
346356
)
357+
debug_provides = f", op_provides={list(self.op_provides)}, fn_provides={list(self._fn_provides)}"
347358
else:
348-
deps = ""
359+
debug_needs = debug_provides = ""
349360
return (
350-
f"FunctionalOperation{endured}{resched}{parallel}{marshalled}(name={self.name!r}, needs={needs!r}, "
351-
f"provides={provides!r}{deps},{aliases} fn{returns_dict_marker}={fn_name!r}{nprops})"
361+
f"FunctionalOperation{endured}{resched}{parallel}{marshalled}(name={self.name!r}, "
362+
f"needs={needs!r}{debug_needs}, provides={provides!r}{debug_provides}{aliases}, "
363+
f"fn{returns_dict_marker}={fn_name!r}{nprops})"
352364
)
353365

354366
@property
@@ -362,9 +374,10 @@ def deps(self) -> Mapping[str, Collection]:
362374
return {
363375
k: v if is_debug() else list(v)
364376
for k, v in zip(
365-
"needs fn_needs provides op_provides fn_provides".split(),
377+
"needs op_needs fn_needs provides op_provides fn_provides".split(),
366378
(
367379
self.needs,
380+
self.op_needs,
368381
self._fn_needs,
369382
self.provides,
370383
self.op_provides,
@@ -378,10 +391,12 @@ def withset(self, **kw) -> "FunctionalOperation":
378391
Make a clone with the some values replaced.
379392
380393
"""
394+
## Exclude calculated dep-fields.
395+
#
381396
me = {
382397
k: v
383398
for k, v in vars(self).items()
384-
if not k.startswith("_") and k != "op_provides"
399+
if not k.startswith("_") and not k.startswith("op_")
385400
}
386401
me.update(kw)
387402
return FunctionalOperation(**me)

test/test_op.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ def test_as_renames(inp, exp):
296296
[
297297
(
298298
dict(aliases={"a": 1}),
299-
r"The `aliases` for ['a'] rename ['a'], not found in op_provides []!",
299+
r"The `aliases` for ['a'] rename ['a'], not found in provides []!",
300300
),
301301
(
302302
dict(name="t", provides="a", aliases={"a": 1, "b": 2}),
303-
r"The `aliases` for ['a', 'b'] rename ['b'], not found in op_provides ['a']!",
303+
r"The `aliases` for ['a', 'b'] rename ['b'], not found in provides ['a']!",
304304
),
305305
(
306306
dict(name="t", provides=sideffect("a"), aliases={sideffect("a"): 1}),

0 commit comments

Comments
 (0)