computation-graph 57__tar.gz → 59__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-57 → computation_graph-59}/PKG-INFO +1 -1
  2. {computation_graph-57 → computation_graph-59}/computation_graph/graph_test.py +37 -0
  3. {computation_graph-57 → computation_graph-59}/computation_graph/run.py +48 -52
  4. {computation_graph-57 → computation_graph-59}/computation_graph.egg-info/PKG-INFO +1 -1
  5. {computation_graph-57 → computation_graph-59}/setup.py +1 -1
  6. {computation_graph-57 → computation_graph-59}/LICENSE.md +0 -0
  7. {computation_graph-57 → computation_graph-59}/README.md +0 -0
  8. {computation_graph-57 → computation_graph-59}/computation_graph/__init__.py +0 -0
  9. {computation_graph-57 → computation_graph-59}/computation_graph/base_types.py +0 -0
  10. {computation_graph-57 → computation_graph-59}/computation_graph/composers/__init__.py +0 -0
  11. {computation_graph-57 → computation_graph-59}/computation_graph/composers/composers_test.py +0 -0
  12. {computation_graph-57 → computation_graph-59}/computation_graph/composers/condition.py +0 -0
  13. {computation_graph-57 → computation_graph-59}/computation_graph/composers/condition_test.py +0 -0
  14. {computation_graph-57 → computation_graph-59}/computation_graph/composers/debug.py +0 -0
  15. {computation_graph-57 → computation_graph-59}/computation_graph/composers/duplication.py +0 -0
  16. {computation_graph-57 → computation_graph-59}/computation_graph/composers/lift.py +0 -0
  17. {computation_graph-57 → computation_graph-59}/computation_graph/composers/logic.py +0 -0
  18. {computation_graph-57 → computation_graph-59}/computation_graph/composers/memory.py +0 -0
  19. {computation_graph-57 → computation_graph-59}/computation_graph/composers/memory_test.py +0 -0
  20. {computation_graph-57 → computation_graph-59}/computation_graph/graph.py +0 -0
  21. {computation_graph-57 → computation_graph-59}/computation_graph/graph_runners.py +0 -0
  22. {computation_graph-57 → computation_graph-59}/computation_graph/legacy.py +0 -0
  23. {computation_graph-57 → computation_graph-59}/computation_graph/signature.py +0 -0
  24. {computation_graph-57 → computation_graph-59}/computation_graph/trace/__init__.py +0 -0
  25. {computation_graph-57 → computation_graph-59}/computation_graph/trace/ascii.py +0 -0
  26. {computation_graph-57 → computation_graph-59}/computation_graph/trace/graphviz.py +0 -0
  27. {computation_graph-57 → computation_graph-59}/computation_graph/trace/graphviz_test.py +0 -0
  28. {computation_graph-57 → computation_graph-59}/computation_graph/trace/mermaid.py +0 -0
  29. {computation_graph-57 → computation_graph-59}/computation_graph/trace/trace_utils.py +0 -0
  30. {computation_graph-57 → computation_graph-59}/computation_graph.egg-info/SOURCES.txt +0 -0
  31. {computation_graph-57 → computation_graph-59}/computation_graph.egg-info/dependency_links.txt +0 -0
  32. {computation_graph-57 → computation_graph-59}/computation_graph.egg-info/requires.txt +0 -0
  33. {computation_graph-57 → computation_graph-59}/computation_graph.egg-info/top_level.txt +0 -0
  34. {computation_graph-57 → computation_graph-59}/pyproject.toml +0 -0
  35. {computation_graph-57 → computation_graph-59}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: computation-graph
3
- Version: 57
3
+ Version: 59
4
4
  Requires-Python: >=3
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE.md
@@ -233,6 +233,43 @@ def test_first():
233
233
  )
234
234
 
235
235
 
236
+ def test_raise_unhandled_exception():
237
+ class MyExceptionError(Exception):
238
+ ...
239
+
240
+ def raises():
241
+ raise MyExceptionError("BAD")
242
+
243
+ with pytest.raises(MyExceptionError, match="BAD"):
244
+ graph_runners.nullary_infer_sink(composers.make_first(raises, lambda: 1))
245
+
246
+
247
+ async def test_raise_exception_in_sync_after_async():
248
+ def raises(x):
249
+ raise TypeError("BAD")
250
+
251
+ async def async_source():
252
+ return 4
253
+
254
+ with pytest.raises(TypeError, match="BAD"):
255
+ await run.to_callable_strict(
256
+ composers.compose_left(async_source, raises, lambda x: 1)
257
+ )({}, {})
258
+
259
+
260
+ async def test_raise_exception_in_async_after_sync():
261
+ async def raises(x):
262
+ raise TypeError("BAD")
263
+
264
+ def source():
265
+ return 4
266
+
267
+ with pytest.raises(TypeError, match="BAD"):
268
+ await run.to_callable_strict(
269
+ composers.compose_left(source, raises, lambda x: 1)
270
+ )({}, {})
271
+
272
+
236
273
  def test_first_all_unactionable():
237
274
  def raises():
238
275
  raise base_types.SkipComputationError
@@ -71,7 +71,13 @@ _toposort_nodes: Callable[
71
71
  opt_gamla.compose_left(opt_gamla.map(base_types.edge_destination), set)
72
72
  ),
73
73
  _transpose_graph,
74
- lambda g: toposort.toposort_flatten(g, sort=False),
74
+ toposort.toposort,
75
+ # Make async functions come first in each layer so they'll start running before all the sync functions
76
+ opt_gamla.maptuple(
77
+ gamla.sort_by(lambda n: 0 if inspect.iscoroutinefunction(n.func) else 1)
78
+ ),
79
+ gamla.concat,
80
+ tuple,
75
81
  )
76
82
 
77
83
 
@@ -96,7 +102,7 @@ def _profile(node, time_started: float):
96
102
  )
97
103
 
98
104
 
99
- _group_by_is_async_result = opt_gamla.groupby(lambda k_v: inspect.isawaitable(k_v[1]))
105
+ _group_by_is_future = opt_gamla.groupby(lambda k_v: asyncio.isfuture(k_v[1]))
100
106
 
101
107
 
102
108
  _is_graph_async = opt_gamla.compose_left(
@@ -204,7 +210,7 @@ def _to_callable_with_side_effect_for_single_and_multiple(
204
210
  edges, handled_exceptions, single_node_side_effect
205
211
  )
206
212
 
207
- topological_layers = opt_gamla.pipe(
213
+ topological_sorted_nodes = opt_gamla.pipe(
208
214
  edges,
209
215
  _toposort_nodes,
210
216
  gamla.remove(gamla.contains(placeholder_to_future_source)),
@@ -220,46 +226,37 @@ def _to_callable_with_side_effect_for_single_and_multiple(
220
226
  if is_async:
221
227
 
222
228
  async def final_runner(sources_to_values):
223
- d = gamla.pipe(
224
- topological_layers,
225
- _run_graph(
226
- translate_source_to_placeholder(sources_to_values),
227
- handled_exceptions,
228
- ),
229
- dict,
229
+ node_to_task_or_result = _run_graph(
230
+ translate_source_to_placeholder(sources_to_values),
231
+ handled_exceptions,
232
+ topological_sorted_nodes,
230
233
  )
231
- results_by_is_async = _group_by_is_async_result(d.items())
234
+ results_by_is_async = _group_by_is_future(node_to_task_or_result.items())
232
235
  async_results = tuple(zip(*results_by_is_async.get(True, ())))
233
236
  sync_results = dict(results_by_is_async.get(False, ()))
234
- return all_node_side_effects_on_edges(
235
- sync_results
236
- | (
237
- {
238
- k: v
239
- for (k, v) in zip(
240
- async_results[0],
241
- await asyncio.gather(
242
- *async_results[1], return_exceptions=True
243
- ),
244
- )
245
- if not isinstance(v, Exception)
246
- }
247
- if async_results
248
- else {}
249
- )
250
- )
237
+
238
+ all_results = sync_results
239
+ if async_results:
240
+ for (node, node_result) in zip(
241
+ async_results[0],
242
+ await asyncio.gather(*async_results[1], return_exceptions=True),
243
+ ):
244
+ e = node_to_task_or_result[node].exception()
245
+ if e:
246
+ raise e from e
247
+ all_results[node] = node_result
248
+
249
+ return all_node_side_effects_on_edges(all_results)
251
250
 
252
251
  else:
253
252
 
254
253
  def final_runner(sources_to_values):
255
- return gamla.pipe(
256
- topological_layers,
254
+ return all_node_side_effects_on_edges(
257
255
  _run_graph(
258
256
  translate_source_to_placeholder(sources_to_values),
259
257
  handled_exceptions,
260
- ),
261
- dict,
262
- all_node_side_effects_on_edges,
258
+ topological_sorted_nodes,
259
+ )
263
260
  )
264
261
 
265
262
  return (_async_graph_reducer if is_async else _graph_reducer)(final_runner)
@@ -500,25 +497,24 @@ def _make_get_node_executor(
500
497
  return get_executor
501
498
 
502
499
 
503
- def _run_graph(inputs: dict, handled_exceptions):
504
- def run_graph(
505
- nodes: tuple[tuple[base_types.ComputationNode, _NodeExecutor]]
506
- ) -> _NodeToResults:
507
- accumulated_results = inputs.copy()
508
- for node_executor in nodes:
509
- try:
510
- accumulated_results[node_executor[0]] = node_executor[1](
511
- accumulated_results, node_executor[0]
512
- )
513
- except (
514
- _DepNotFoundError,
515
- base_types.SkipComputationError,
516
- *handled_exceptions,
517
- ):
518
- pass
519
- return accumulated_results
520
-
521
- return run_graph
500
+ def _run_graph(
501
+ inputs: dict,
502
+ handled_exceptions,
503
+ topological_sorted_nodes: tuple[tuple[base_types.ComputationNode, _NodeExecutor]],
504
+ ) -> _NodeToResults:
505
+ accumulated_results = inputs.copy()
506
+ for node_executor in topological_sorted_nodes:
507
+ try:
508
+ accumulated_results[node_executor[0]] = node_executor[1](
509
+ accumulated_results, node_executor[0]
510
+ )
511
+ except (
512
+ _DepNotFoundError,
513
+ base_types.SkipComputationError,
514
+ *handled_exceptions,
515
+ ):
516
+ pass
517
+ return accumulated_results
522
518
 
523
519
 
524
520
  def _graph_reducer(graph_callable):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: computation-graph
3
- Version: 57
3
+ Version: 59
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="57",
10
+ version="59",
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