computation-graph 51__tar.gz → 53__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {computation-graph-51 → computation-graph-53}/PKG-INFO +1 -1
  2. {computation-graph-51 → computation-graph-53}/computation_graph/base_types.py +1 -1
  3. {computation-graph-51 → computation-graph-53}/computation_graph/composers/duplication.py +39 -2
  4. {computation-graph-51 → computation-graph-53}/computation_graph/graph.py +21 -2
  5. {computation-graph-51 → computation-graph-53}/computation_graph/graph_test.py +104 -2
  6. {computation-graph-51 → computation-graph-53}/computation_graph/run.py +9 -3
  7. {computation-graph-51 → computation-graph-53}/computation_graph.egg-info/PKG-INFO +1 -1
  8. {computation-graph-51 → computation-graph-53}/setup.py +1 -1
  9. {computation-graph-51 → computation-graph-53}/LICENSE.md +0 -0
  10. {computation-graph-51 → computation-graph-53}/README.md +0 -0
  11. {computation-graph-51 → computation-graph-53}/computation_graph/__init__.py +0 -0
  12. {computation-graph-51 → computation-graph-53}/computation_graph/composers/__init__.py +0 -0
  13. {computation-graph-51 → computation-graph-53}/computation_graph/composers/composers_test.py +0 -0
  14. {computation-graph-51 → computation-graph-53}/computation_graph/composers/condition.py +0 -0
  15. {computation-graph-51 → computation-graph-53}/computation_graph/composers/condition_test.py +0 -0
  16. {computation-graph-51 → computation-graph-53}/computation_graph/composers/debug.py +0 -0
  17. {computation-graph-51 → computation-graph-53}/computation_graph/composers/lift.py +0 -0
  18. {computation-graph-51 → computation-graph-53}/computation_graph/composers/logic.py +0 -0
  19. {computation-graph-51 → computation-graph-53}/computation_graph/composers/memory.py +0 -0
  20. {computation-graph-51 → computation-graph-53}/computation_graph/composers/memory_test.py +0 -0
  21. {computation-graph-51 → computation-graph-53}/computation_graph/graph_runners.py +0 -0
  22. {computation-graph-51 → computation-graph-53}/computation_graph/legacy.py +0 -0
  23. {computation-graph-51 → computation-graph-53}/computation_graph/signature.py +0 -0
  24. {computation-graph-51 → computation-graph-53}/computation_graph/trace/__init__.py +0 -0
  25. {computation-graph-51 → computation-graph-53}/computation_graph/trace/ascii.py +0 -0
  26. {computation-graph-51 → computation-graph-53}/computation_graph/trace/graphviz.py +0 -0
  27. {computation-graph-51 → computation-graph-53}/computation_graph/trace/graphviz_test.py +0 -0
  28. {computation-graph-51 → computation-graph-53}/computation_graph/trace/mermaid.py +0 -0
  29. {computation-graph-51 → computation-graph-53}/computation_graph/trace/trace_utils.py +0 -0
  30. {computation-graph-51 → computation-graph-53}/computation_graph.egg-info/SOURCES.txt +0 -0
  31. {computation-graph-51 → computation-graph-53}/computation_graph.egg-info/dependency_links.txt +0 -0
  32. {computation-graph-51 → computation-graph-53}/computation_graph.egg-info/requires.txt +0 -0
  33. {computation-graph-51 → computation-graph-53}/computation_graph.egg-info/top_level.txt +0 -0
  34. {computation-graph-51 → computation-graph-53}/pyproject.toml +0 -0
  35. {computation-graph-51 → computation-graph-53}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: computation-graph
3
- Version: 51
3
+ Version: 53
4
4
  Requires-Python: >=3
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE.md
@@ -152,7 +152,7 @@ assert_no_unwanted_ambiguity = gamla.side_effect(
152
152
 
153
153
  @gamla.side_effect
154
154
  def _assert_no_unwanted_ambiguity_when_debug_set(graph):
155
- if os.getenv(COMPUTATION_GRAPH_DEBUG_ENV_KEY):
155
+ if os.getenv(COMPUTATION_GRAPH_DEBUG_ENV_KEY) is not None:
156
156
  assert_no_unwanted_ambiguity(graph)
157
157
 
158
158
 
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import functools
3
3
  import inspect
4
+ from typing import Dict
4
5
 
5
6
  import gamla
6
7
 
@@ -20,6 +21,7 @@ def duplicate_function(func):
20
21
  def inner(*args, **kwargs):
21
22
  return func(*args, **kwargs)
22
23
 
24
+ inner.__name__ = f"duplicate of {inner.__name__}"
23
25
  return inner
24
26
 
25
27
 
@@ -42,8 +44,8 @@ _duplicate_node = gamla.compose_left(
42
44
  graph.make_computation_node,
43
45
  )
44
46
 
47
+
45
48
  _node_to_duplicated_node = gamla.compose_left(
46
- graph.get_all_nodes,
47
49
  gamla.remove(base_types.node_is_terminal),
48
50
  gamla.map(gamla.pair_right(_duplicate_node)),
49
51
  dict,
@@ -51,7 +53,7 @@ _node_to_duplicated_node = gamla.compose_left(
51
53
  )
52
54
 
53
55
  duplicate_graph = gamla.compose_left(
54
- gamla.pair_with(_node_to_duplicated_node),
56
+ gamla.pair_with(gamla.compose_left(graph.get_all_nodes, _node_to_duplicated_node)),
55
57
  gamla.star(
56
58
  lambda get_duplicated_node, graph: gamla.pipe(
57
59
  graph,
@@ -68,3 +70,38 @@ duplicate_graph = gamla.compose_left(
68
70
  duplicate_function_or_graph = gamla.ternary(
69
71
  gamla.is_instance(tuple), duplicate_graph, duplicate_function
70
72
  )
73
+
74
+
75
+ def safe_replace_sources(
76
+ source_to_replacement_dict: Dict[
77
+ base_types.CallableOrNode, base_types.CallableOrNodeOrGraph
78
+ ],
79
+ cg: base_types.GraphType,
80
+ ) -> base_types.GraphType:
81
+ source_to_replacement_dict = gamla.keymap(graph.make_computation_node)(
82
+ source_to_replacement_dict
83
+ )
84
+ reachable_to_duplicate_map = gamla.pipe(
85
+ gamla.graph_traverse_many(
86
+ source_to_replacement_dict.keys(), graph.traverse_forward(cg)
87
+ ),
88
+ gamla.remove(gamla.contains(source_to_replacement_dict.keys())),
89
+ _node_to_duplicated_node,
90
+ )
91
+ get_node_replacement = gamla.compose_left(
92
+ gamla.lazyjuxt(
93
+ gamla.dict_to_getter_with_default(None)(source_to_replacement_dict),
94
+ reachable_to_duplicate_map,
95
+ gamla.identity,
96
+ ),
97
+ gamla.find(gamla.identity),
98
+ )
99
+
100
+ def update_edge(e: base_types.ComputationEdge) -> base_types.GraphType:
101
+ dest = base_types.edge_destination(e)
102
+ g = graph.replace_node(dest, get_node_replacement(dest))((e,))
103
+ for source in base_types.edge_sources(e):
104
+ g = graph.replace_source(source, get_node_replacement(source), g)
105
+ return g
106
+
107
+ return gamla.reduce(lambda updated_cg, e: updated_cg + update_edge(e), (), cg)
@@ -1,5 +1,5 @@
1
1
  import dataclasses
2
- from typing import Callable, FrozenSet
2
+ from typing import Callable, FrozenSet, Tuple
3
3
 
4
4
  import gamla
5
5
  from gamla.optimized import sync as opt_gamla
@@ -148,6 +148,25 @@ def _replace_source_in_edges(
148
148
  )
149
149
 
150
150
 
151
+ traverse_forward: Callable[
152
+ [base_types.GraphType],
153
+ Callable[[base_types.CallableOrNode], Tuple[base_types.ComputationNode, ...]],
154
+ ] = gamla.compose_left(
155
+ gamla.mapcat(
156
+ gamla.compose_left(
157
+ gamla.juxt(base_types.edge_sources, base_types.edge_destination),
158
+ gamla.explode(0),
159
+ )
160
+ ),
161
+ gamla.groupby_many_reduce(
162
+ gamla.compose_left(gamla.head, gamla.wrap_tuple),
163
+ lambda destinations, e: (*(destinations if destinations else ()), e[1]),
164
+ ),
165
+ gamla.dict_to_getter_with_default(()),
166
+ gamla.before(make_computation_node),
167
+ )
168
+
169
+
151
170
  @gamla.curry
152
171
  def replace_source(
153
172
  original: base_types.CallableOrNode,
@@ -158,7 +177,7 @@ def replace_source(
158
177
  return current_graph
159
178
 
160
179
  if gamla.is_instance(base_types.CallableOrNode)(replacement):
161
- return _replace_source_in_edges(original, replacement)(current_graph)
180
+ return _replace_source_in_edges(original, replacement)(current_graph) # type: ignore
162
181
 
163
182
  if base_types.is_computation_graph(replacement):
164
183
  return gamla.pipe(
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ from typing import Dict
2
3
 
3
4
  import gamla
4
5
  import pytest
@@ -445,7 +446,9 @@ def test_double_star_signature_considered_unary():
445
446
  )
446
447
 
447
448
 
448
- def test_type_safety_messages(caplog):
449
+ def test_type_safety_messages(caplog, monkeypatch):
450
+ monkeypatch.setenv(base_types.COMPUTATION_GRAPH_DEBUG_ENV_KEY, "j")
451
+
449
452
  def f(x) -> int: # Bad typing!
450
453
  return "hello " + x
451
454
 
@@ -456,7 +459,9 @@ def test_type_safety_messages(caplog):
456
459
  assert "TypeError" in caplog.text
457
460
 
458
461
 
459
- def test_type_safety_messages_no_overtrigger(caplog):
462
+ def test_type_safety_messages_no_overtrigger(caplog, monkeypatch):
463
+ monkeypatch.setenv(base_types.COMPUTATION_GRAPH_DEBUG_ENV_KEY, "h")
464
+
460
465
  def f(x) -> str:
461
466
  return "hello " + x
462
467
 
@@ -798,3 +803,100 @@ def test_ambig_edges_assertion_in_merge_graphs_active_only_when_env_var_is_activ
798
803
  composers.compose_left_unary(lambda: 1, a),
799
804
  composers.compose_left_unary(lambda: 1, a),
800
805
  )
806
+
807
+
808
+ def a():
809
+ pass
810
+
811
+
812
+ def b(x):
813
+ pass
814
+
815
+
816
+ def c(x):
817
+ pass
818
+
819
+
820
+ def d(x, y):
821
+ pass
822
+
823
+
824
+ def kuky():
825
+ pass
826
+
827
+
828
+ def kuku():
829
+ pass
830
+
831
+
832
+ t = graph.make_terminal("t", lambda x: x)
833
+
834
+ g = (
835
+ composers.compose_left(a, c)
836
+ + composers.compose_left(c, d, key="x")
837
+ + composers.compose_left(b, d, key="y")
838
+ + composers.compose_left_future(d, b, "x", "bla")
839
+ + composers.compose_left(a, t)
840
+ )
841
+
842
+
843
+ @pytest.mark.parametrize(
844
+ "to_replace,expected_edges_strs",
845
+ [
846
+ pytest.param(
847
+ {a: kuky},
848
+ {
849
+ "kuky----x---->duplicate of c",
850
+ "kuky----x---->t",
851
+ "duplicate of c----x---->duplicate of d",
852
+ "when_memory_unavailable----x---->duplicate of b",
853
+ "duplicate of d....x....>duplicate of b",
854
+ "duplicate of b----y---->duplicate of d",
855
+ },
856
+ id="replace source node",
857
+ ),
858
+ pytest.param(
859
+ {c: kuky},
860
+ {
861
+ "a----x---->kuky",
862
+ "a----x---->t",
863
+ "kuky----x---->duplicate of d",
864
+ "when_memory_unavailable----x---->duplicate of b",
865
+ "duplicate of d....x....>duplicate of b",
866
+ "duplicate of b----y---->duplicate of d",
867
+ },
868
+ id="replace node not in cycle",
869
+ ),
870
+ pytest.param(
871
+ {b: kuky},
872
+ {
873
+ "a----x---->c",
874
+ "a----x---->t",
875
+ "c----x---->duplicate of d",
876
+ "when_memory_unavailable----x---->kuky",
877
+ "duplicate of d....x....>kuky",
878
+ "kuky----y---->duplicate of d",
879
+ },
880
+ id="replace node in cycle",
881
+ ),
882
+ pytest.param(
883
+ {a: kuku, b: kuky},
884
+ {
885
+ "duplicate of c----x---->duplicate of d",
886
+ "duplicate of d....x....>kuky",
887
+ "kuku----x---->duplicate of c",
888
+ "kuku----x---->t",
889
+ "kuky----y---->duplicate of d",
890
+ "when_memory_unavailable----x---->kuky",
891
+ },
892
+ id="replace multiple nodes - duplicate reachables once",
893
+ ),
894
+ ],
895
+ )
896
+ def test_safe_replace_node(
897
+ to_replace: Dict[base_types.CallableOrNode, base_types.CallableOrNodeOrGraph],
898
+ expected_edges_strs: str,
899
+ ):
900
+ assert expected_edges_strs == {
901
+ str(e) for e in duplication.safe_replace_sources(to_replace, g)
902
+ }
@@ -3,6 +3,7 @@ import dataclasses
3
3
  import functools
4
4
  import itertools
5
5
  import logging
6
+ import os
6
7
  import time
7
8
  import typing
8
9
  from typing import Any, Callable, Dict, FrozenSet, Set, Tuple, Type
@@ -41,7 +42,7 @@ def _transpose_graph(
41
42
 
42
43
 
43
44
  _toposort_nodes: Callable[
44
- [base_types.GraphType], Tuple[FrozenSet[base_types.ComputationNode], ...],
45
+ [base_types.GraphType], Tuple[FrozenSet[base_types.ComputationNode], ...]
45
46
  ] = opt_gamla.compose_left(
46
47
  opt_gamla.groupby_many(base_types.edge_sources),
47
48
  opt_gamla.valmap(
@@ -76,7 +77,6 @@ def _profile(node, time_started: float):
76
77
  def _make_get_node_input_and_apply(
77
78
  is_async: bool, side_effect: _SingleNodeSideEffect
78
79
  ) -> Callable[..., base_types.Result]:
79
-
80
80
  if is_async:
81
81
 
82
82
  @opt_async_gamla.star
@@ -149,6 +149,12 @@ def _to_callable_with_side_effect_for_single_and_multiple(
149
149
  edges: base_types.GraphType,
150
150
  handled_exceptions: Tuple[Type[Exception], ...],
151
151
  ) -> Callable[[_NodeToResults, _NodeToResults], _NodeToResults]:
152
+ single_node_side_effect = (
153
+ (lambda node, result: result)
154
+ if os.getenv(base_types.COMPUTATION_GRAPH_DEBUG_ENV_KEY) is None
155
+ else single_node_side_effect
156
+ )
157
+
152
158
  future_sources = _graph_to_future_sources(edges)
153
159
  future_source_to_placeholder = _map_future_source_to_placeholder(future_sources)
154
160
  edges = gamla.pipe(
@@ -247,7 +253,7 @@ def _node_incoming_edges_to_input_spec(
247
253
 
248
254
  def _edges_to_accumulated_results_to_node_to_first_possible_input(
249
255
  edges,
250
- ) -> Callable[[_NodeToResults], _NodeToComputationInput,]:
256
+ ) -> Callable[[_NodeToResults], _NodeToComputationInput]:
251
257
  node_to_incoming_edges = graph.get_incoming_edges_for_node(edges)
252
258
  node_to_computation_input_spec_options: Callable[
253
259
  [base_types.ComputationNode], Tuple[_ComputaionInputSpec]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: computation-graph
3
- Version: 51
3
+ Version: 53
4
4
  Requires-Python: >=3
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE.md
@@ -7,7 +7,7 @@ with open("README.md", "r") as fh:
7
7
  setuptools.setup(
8
8
  name="computation-graph",
9
9
  python_requires=">=3",
10
- version="51",
10
+ version="53",
11
11
  long_description=_LONG_DESCRIPTION,
12
12
  long_description_content_type="text/markdown",
13
13
  packages=setuptools.find_namespace_packages(),
File without changes
File without changes