computation-graph 60__tar.gz → 62__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-60 → computation_graph-62}/PKG-INFO +1 -1
  2. {computation_graph-60 → computation_graph-62}/computation_graph/graph_test.py +43 -2
  3. {computation_graph-60 → computation_graph-62}/computation_graph/run.py +54 -25
  4. {computation_graph-60 → computation_graph-62}/computation_graph.egg-info/PKG-INFO +1 -1
  5. {computation_graph-60 → computation_graph-62}/setup.py +1 -1
  6. {computation_graph-60 → computation_graph-62}/LICENSE.md +0 -0
  7. {computation_graph-60 → computation_graph-62}/README.md +0 -0
  8. {computation_graph-60 → computation_graph-62}/computation_graph/__init__.py +0 -0
  9. {computation_graph-60 → computation_graph-62}/computation_graph/base_types.py +0 -0
  10. {computation_graph-60 → computation_graph-62}/computation_graph/composers/__init__.py +0 -0
  11. {computation_graph-60 → computation_graph-62}/computation_graph/composers/composers_test.py +0 -0
  12. {computation_graph-60 → computation_graph-62}/computation_graph/composers/condition.py +0 -0
  13. {computation_graph-60 → computation_graph-62}/computation_graph/composers/condition_test.py +0 -0
  14. {computation_graph-60 → computation_graph-62}/computation_graph/composers/debug.py +0 -0
  15. {computation_graph-60 → computation_graph-62}/computation_graph/composers/duplication.py +0 -0
  16. {computation_graph-60 → computation_graph-62}/computation_graph/composers/lift.py +0 -0
  17. {computation_graph-60 → computation_graph-62}/computation_graph/composers/logic.py +0 -0
  18. {computation_graph-60 → computation_graph-62}/computation_graph/composers/memory.py +0 -0
  19. {computation_graph-60 → computation_graph-62}/computation_graph/composers/memory_test.py +0 -0
  20. {computation_graph-60 → computation_graph-62}/computation_graph/graph.py +0 -0
  21. {computation_graph-60 → computation_graph-62}/computation_graph/graph_runners.py +0 -0
  22. {computation_graph-60 → computation_graph-62}/computation_graph/legacy.py +0 -0
  23. {computation_graph-60 → computation_graph-62}/computation_graph/signature.py +0 -0
  24. {computation_graph-60 → computation_graph-62}/computation_graph/trace/__init__.py +0 -0
  25. {computation_graph-60 → computation_graph-62}/computation_graph/trace/ascii.py +0 -0
  26. {computation_graph-60 → computation_graph-62}/computation_graph/trace/graphviz.py +0 -0
  27. {computation_graph-60 → computation_graph-62}/computation_graph/trace/graphviz_test.py +0 -0
  28. {computation_graph-60 → computation_graph-62}/computation_graph/trace/mermaid.py +0 -0
  29. {computation_graph-60 → computation_graph-62}/computation_graph/trace/trace_utils.py +0 -0
  30. {computation_graph-60 → computation_graph-62}/computation_graph.egg-info/SOURCES.txt +0 -0
  31. {computation_graph-60 → computation_graph-62}/computation_graph.egg-info/dependency_links.txt +0 -0
  32. {computation_graph-60 → computation_graph-62}/computation_graph.egg-info/requires.txt +0 -0
  33. {computation_graph-60 → computation_graph-62}/computation_graph.egg-info/top_level.txt +0 -0
  34. {computation_graph-60 → computation_graph-62}/pyproject.toml +0 -0
  35. {computation_graph-60 → computation_graph-62}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: computation-graph
3
- Version: 60
3
+ Version: 62
4
4
  Requires-Python: >=3
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE.md
@@ -245,6 +245,26 @@ async def test_raise_handled_from_async():
245
245
  )
246
246
 
247
247
 
248
+ async def test_no_result_for_node_that_raised_handled_exception():
249
+ async def raises(x):
250
+ raise base_types.SkipComputationError
251
+
252
+ def sink(x):
253
+ return x
254
+
255
+ @graph.make_computation_node
256
+ def source():
257
+ return 4
258
+
259
+ res = await run.to_callable_strict(composers.compose_left(source, raises, sink))(
260
+ {}, {}
261
+ )
262
+
263
+ assert res[source] == 4
264
+ assert raises not in res
265
+ assert sink not in res
266
+
267
+
248
268
  def test_raise_unhandled_exception():
249
269
  class MyExceptionError(Exception):
250
270
  ...
@@ -256,6 +276,27 @@ def test_raise_unhandled_exception():
256
276
  graph_runners.nullary_infer_sink(composers.make_first(raises, lambda: 1))
257
277
 
258
278
 
279
+ async def test_raise_unhandled_exception_async():
280
+ class MyExceptionError(Exception):
281
+ ...
282
+
283
+ @composers.compose_left_dict(
284
+ {"x": composers.compose_left_unary(lambda: 1, lambda x: 1)}
285
+ )
286
+ def raises(x):
287
+ raise MyExceptionError("BAD")
288
+
289
+ @composers.compose_left_dict({"x": lambda: 1})
290
+ async def not_awaited(x):
291
+ raise base_types.SkipComputationError("DAB")
292
+
293
+ with pytest.raises(MyExceptionError, match="BAD"):
294
+ await graph_runners.nullary_infer_sink(
295
+ composers.compose_left_dict({"y": raises, "x": not_awaited}, lambda x, y: 1)
296
+ )
297
+ assert len(asyncio.all_tasks()) == 1
298
+
299
+
259
300
  async def test_raise_exception_in_sync_after_async():
260
301
  def raises(x):
261
302
  raise TypeError("BAD")
@@ -684,11 +725,11 @@ def test_compose_future():
684
725
  )(([[{a: 2, b: 2, c: 2}, 9], [{a: 2, b: 2, c: 2}, 25]]))
685
726
 
686
727
 
687
- def test_compose_future_async():
728
+ async def test_compose_future_async():
688
729
  a = graph.make_source()
689
730
  b = graph.make_source()
690
731
  c = graph.make_source()
691
- graph_runners.variadic_with_state_and_expectations(
732
+ await graph_runners.variadic_with_state_and_expectations(
692
733
  base_types.merge_graphs(
693
734
  composers.compose_source_unary(_plus_1_async, c),
694
735
  composers.compose_source_unary(_times_2, b),
@@ -226,32 +226,10 @@ def _to_callable_with_side_effect_for_single_and_multiple(
226
226
  if is_async:
227
227
 
228
228
  async def final_runner(sources_to_values):
229
- node_to_task_or_result = _run_graph(
230
- translate_source_to_placeholder(sources_to_values),
231
- handled_exceptions,
232
- topological_sorted_nodes,
229
+ inputs = translate_source_to_placeholder(sources_to_values)
230
+ all_results = await _run_graph_async(
231
+ inputs, handled_exceptions, topological_sorted_nodes
233
232
  )
234
- results_by_is_async = _group_by_is_future(node_to_task_or_result.items())
235
- async_results = tuple(zip(*results_by_is_async.get(True, ())))
236
- sync_results = dict(results_by_is_async.get(False, ()))
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 and not isinstance(
246
- e,
247
- (
248
- _DepNotFoundError,
249
- base_types.SkipComputationError,
250
- *handled_exceptions,
251
- ),
252
- ):
253
- raise e from e
254
- all_results[node] = node_result
255
233
 
256
234
  return all_node_side_effects_on_edges(all_results)
257
235
 
@@ -504,6 +482,57 @@ def _make_get_node_executor(
504
482
  return get_executor
505
483
 
506
484
 
485
+ async def _run_graph_async(inputs, handled_exceptions, topological_sorted_nodes):
486
+ node_to_task_or_result = inputs.copy()
487
+ unhandled_exception = None
488
+ try:
489
+ for node_executor in topological_sorted_nodes:
490
+ try:
491
+ node_to_task_or_result[node_executor[0]] = node_executor[1](
492
+ node_to_task_or_result, node_executor[0]
493
+ )
494
+ except (
495
+ _DepNotFoundError,
496
+ base_types.SkipComputationError,
497
+ *handled_exceptions,
498
+ ):
499
+ pass
500
+ except Exception as exc:
501
+ unhandled_exception = exc
502
+ finally:
503
+ results_by_is_async = _group_by_is_future(node_to_task_or_result.items())
504
+ async_results = tuple(zip(*results_by_is_async.get(True, ())))
505
+ sync_results = dict(results_by_is_async.get(False, ()))
506
+
507
+ all_results = sync_results
508
+ if async_results:
509
+ for (node, node_result) in zip(
510
+ async_results[0],
511
+ await asyncio.gather(*async_results[1], return_exceptions=True),
512
+ ):
513
+ task_e = node_to_task_or_result[node].exception()
514
+ if not task_e:
515
+ all_results[node] = node_result
516
+ elif not unhandled_exception and not isinstance(
517
+ task_e,
518
+ (
519
+ _DepNotFoundError,
520
+ base_types.SkipComputationError,
521
+ *handled_exceptions,
522
+ ),
523
+ ):
524
+ unhandled_exception = task_e
525
+ if unhandled_exception:
526
+ # this trick avoids cyclic reference and garbage collection issues
527
+ try:
528
+ raise unhandled_exception from unhandled_exception
529
+ except Exception as e:
530
+ del node_to_task_or_result
531
+ del unhandled_exception
532
+ raise e from e
533
+ return all_results
534
+
535
+
507
536
  def _run_graph(
508
537
  inputs: dict,
509
538
  handled_exceptions,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: computation-graph
3
- Version: 60
3
+ Version: 62
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="60",
10
+ version="62",
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