computation-graph 68__tar.gz → 69__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.
- {computation_graph-68 → computation_graph-69}/PKG-INFO +1 -1
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/__init__.py +29 -37
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/duplication.py +2 -2
- {computation_graph-68 → computation_graph-69}/computation_graph/graph.py +31 -39
- {computation_graph-68 → computation_graph-69}/computation_graph/graph_runners.py +2 -2
- {computation_graph-68 → computation_graph-69}/computation_graph/run.py +6 -4
- {computation_graph-68 → computation_graph-69}/computation_graph/signature.py +36 -1
- {computation_graph-68 → computation_graph-69}/computation_graph.egg-info/PKG-INFO +1 -1
- {computation_graph-68 → computation_graph-69}/setup.py +1 -1
- {computation_graph-68 → computation_graph-69}/LICENSE.md +0 -0
- {computation_graph-68 → computation_graph-69}/README.md +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/__init__.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/base_types.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/composers_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/condition.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/condition_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/debug.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/lift.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/lift_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/logic.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/memory.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/composers/memory_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/graph_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/infer_sink.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/infer_sink_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/legacy.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/trace/__init__.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/trace/ascii.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/trace/graphviz.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/trace/graphviz_test.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/trace/mermaid.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph/trace/trace_utils.py +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph.egg-info/SOURCES.txt +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph.egg-info/dependency_links.txt +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph.egg-info/requires.txt +0 -0
- {computation_graph-68 → computation_graph-69}/computation_graph.egg-info/top_level.txt +0 -0
- {computation_graph-68 → computation_graph-69}/pyproject.toml +0 -0
- {computation_graph-68 → computation_graph-69}/setup.cfg +0 -0
|
@@ -286,44 +286,36 @@ def _infer_composition_edges(
|
|
|
286
286
|
unbound_signature = graph.unbound_signature(
|
|
287
287
|
graph.get_incoming_edges_for_node(destination.edges)
|
|
288
288
|
)
|
|
289
|
+
source_nodes = (
|
|
290
|
+
graph.get_all_nodes(source.edges)
|
|
291
|
+
if isinstance(source, GraphType)
|
|
292
|
+
else frozenset()
|
|
293
|
+
)
|
|
294
|
+
skip_cycle_check = isinstance(source, base_types.ComputationNode)
|
|
295
|
+
new_edges = set()
|
|
296
|
+
# The connectable-node set is order-independent (result is a frozenset), so we
|
|
297
|
+
# can iterate the cached node set instead of rescanning the edges.
|
|
298
|
+
for node in graph.get_all_nodes(destination.edges):
|
|
299
|
+
node_signature = unbound_signature(node)
|
|
300
|
+
if not (
|
|
301
|
+
key in node_signature.kwargs
|
|
302
|
+
or (key is None and signature.is_unary(node_signature))
|
|
303
|
+
):
|
|
304
|
+
continue
|
|
305
|
+
# Do not add edges to nodes from source that are already present in destination (cycle).
|
|
306
|
+
if not skip_cycle_check and node in source_nodes:
|
|
307
|
+
continue
|
|
308
|
+
new_edges.add(
|
|
309
|
+
try_connect(destination=node, unbound_destination_signature=node_signature)
|
|
310
|
+
)
|
|
311
|
+
if not new_edges:
|
|
312
|
+
raise AssertionError(
|
|
313
|
+
f"Cannot compose, destination signature does not contain key '{key}'"
|
|
314
|
+
)
|
|
289
315
|
return graph.merge_graphs(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
gamla.sync.mapcat(graph.get_edge_nodes),
|
|
294
|
-
gamla.unique,
|
|
295
|
-
gamla.sync.filter(
|
|
296
|
-
gamla.sync.compose_left(
|
|
297
|
-
unbound_signature,
|
|
298
|
-
lambda sig: key in sig.kwargs
|
|
299
|
-
or (key is None and signature.is_unary(sig)),
|
|
300
|
-
)
|
|
301
|
-
),
|
|
302
|
-
# Do not add edges to nodes from source that are already present in destination (cycle).
|
|
303
|
-
gamla.sync.filter(
|
|
304
|
-
lambda node: isinstance(source, base_types.ComputationNode)
|
|
305
|
-
or node
|
|
306
|
-
not in graph.get_all_nodes(
|
|
307
|
-
source.edges if isinstance(source, GraphType) else source
|
|
308
|
-
)
|
|
309
|
-
),
|
|
310
|
-
gamla.sync.map(
|
|
311
|
-
lambda destination_node: try_connect(
|
|
312
|
-
destination=destination_node,
|
|
313
|
-
unbound_destination_signature=unbound_signature(destination_node),
|
|
314
|
-
)
|
|
315
|
-
),
|
|
316
|
-
frozenset,
|
|
317
|
-
gamla.sync.check(
|
|
318
|
-
gamla.identity,
|
|
319
|
-
AssertionError(
|
|
320
|
-
f"Cannot compose, destination signature does not contain key '{key}'"
|
|
321
|
-
),
|
|
322
|
-
),
|
|
323
|
-
# Sink is a placeholder here; `merge_graphs` below sets the real sink
|
|
324
|
-
# via `sink_node_or_graph`.
|
|
325
|
-
lambda edges: GraphType(edges, None), # type: ignore[arg-type]
|
|
326
|
-
),
|
|
316
|
+
# Sink is a placeholder here; `merge_graphs` below sets the real sink
|
|
317
|
+
# via `sink_node_or_graph`.
|
|
318
|
+
GraphType(frozenset(new_edges), None), # type: ignore[arg-type]
|
|
327
319
|
_get_edges_from_node_or_graph(source),
|
|
328
320
|
destination,
|
|
329
321
|
sink_node_or_graph=_determine_sink(source, destination, is_future),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import dataclasses
|
|
3
2
|
import functools
|
|
3
|
+
import inspect
|
|
4
4
|
from typing import Dict
|
|
5
5
|
|
|
6
6
|
import gamla
|
|
@@ -10,7 +10,7 @@ from computation_graph.composers import debug
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def duplicate_function(func):
|
|
13
|
-
if
|
|
13
|
+
if inspect.iscoroutinefunction(func):
|
|
14
14
|
|
|
15
15
|
@functools.wraps(func)
|
|
16
16
|
async def inner(*args, **kwargs):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import functools
|
|
3
|
-
from typing import Callable, Dict, FrozenSet, Optional, Tuple
|
|
3
|
+
from typing import Callable, Dict, FrozenSet, Iterable, Optional, Tuple
|
|
4
4
|
|
|
5
5
|
import gamla
|
|
6
6
|
from gamla.optimized import sync as opt_gamla
|
|
@@ -64,11 +64,17 @@ def make_computation_node(
|
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
_EMPTY_EDGE_SET: FrozenSet[base_types.ComputationEdge] = frozenset()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_incoming_edges_for_node(
|
|
71
|
+
edges: Iterable[base_types.ComputationEdge],
|
|
72
|
+
) -> Callable[[base_types.ComputationNode], FrozenSet[base_types.ComputationEdge]]:
|
|
73
|
+
grouped: Dict[base_types.ComputationNode, list] = {}
|
|
74
|
+
for edge in edges:
|
|
75
|
+
grouped.setdefault(edge.destination, []).append(edge)
|
|
76
|
+
node_to_edges = {node: frozenset(group) for node, group in grouped.items()}
|
|
77
|
+
return lambda node: node_to_edges.get(node, _EMPTY_EDGE_SET)
|
|
72
78
|
|
|
73
79
|
|
|
74
80
|
get_terminals = opt_gamla.compose_left(
|
|
@@ -95,30 +101,24 @@ def make_terminal(name: str, func: Callable) -> base_types.ComputationNode:
|
|
|
95
101
|
)
|
|
96
102
|
|
|
97
103
|
|
|
98
|
-
_keep_not_in_bound_kwargs = opt_gamla.compose_left(
|
|
99
|
-
opt_gamla.map(base_types.edge_key),
|
|
100
|
-
gamla.filter(gamla.identity),
|
|
101
|
-
frozenset,
|
|
102
|
-
gamla.contains,
|
|
103
|
-
gamla.remove,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
104
|
@gamla.curry
|
|
108
105
|
def unbound_signature(
|
|
109
106
|
node_to_incoming_edges, node: base_types.ComputationNode
|
|
110
107
|
) -> base_types.NodeSignature:
|
|
111
108
|
"""Computes the new signature of unbound variables after considering internal edges."""
|
|
112
109
|
incoming_edges = node_to_incoming_edges(node)
|
|
113
|
-
|
|
110
|
+
bound_keys = {edge.key for edge in incoming_edges if edge.key}
|
|
111
|
+
node_signature = node.signature
|
|
114
112
|
return base_types.NodeSignature(
|
|
115
|
-
is_kwargs=
|
|
116
|
-
and "**kwargs"
|
|
117
|
-
and signature.is_unary(
|
|
118
|
-
is_args=
|
|
113
|
+
is_kwargs=node_signature.is_kwargs
|
|
114
|
+
and all(edge.key != "**kwargs" for edge in incoming_edges)
|
|
115
|
+
and signature.is_unary(node_signature),
|
|
116
|
+
is_args=node_signature.is_args
|
|
119
117
|
and not any(edge.args for edge in incoming_edges),
|
|
120
|
-
kwargs=tuple(
|
|
121
|
-
optional_kwargs=tuple(
|
|
118
|
+
kwargs=tuple(k for k in node_signature.kwargs if k not in bound_keys),
|
|
119
|
+
optional_kwargs=tuple(
|
|
120
|
+
k for k in node_signature.optional_kwargs if k not in bound_keys
|
|
121
|
+
),
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
|
|
@@ -361,28 +361,20 @@ def merge_graphs(
|
|
|
361
361
|
isinstance(x, base_types.GraphType) for x in graphs
|
|
362
362
|
), f"{graphs} not a graph"
|
|
363
363
|
assert (
|
|
364
|
-
not base_types.
|
|
364
|
+
not isinstance(sink_node_or_graph, base_types.GraphType)
|
|
365
|
+
or not sink_node_or_graph.edges
|
|
365
366
|
or sink_node_or_graph in graphs
|
|
366
367
|
), "sink graph must be one of the graphs being merged"
|
|
367
368
|
|
|
368
|
-
new_g =
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
tuple,
|
|
372
|
-
gamla.pair_right(
|
|
373
|
-
gamla.just(
|
|
374
|
-
sink_node_or_graph.sink
|
|
375
|
-
if isinstance(sink_node_or_graph, base_types.GraphType)
|
|
376
|
-
else sink_node_or_graph
|
|
377
|
-
)
|
|
369
|
+
new_g = base_types.GraphType(
|
|
370
|
+
base_types.merge_edges(
|
|
371
|
+
*(g.edges for g in graphs if g != base_types.EMPTY_GRAPH)
|
|
378
372
|
),
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
gamla.identity,
|
|
373
|
+
(
|
|
374
|
+
sink_node_or_graph.sink
|
|
375
|
+
if isinstance(sink_node_or_graph, base_types.GraphType)
|
|
376
|
+
else sink_node_or_graph
|
|
384
377
|
),
|
|
385
|
-
gamla.star(base_types.GraphType),
|
|
386
378
|
)
|
|
387
379
|
|
|
388
380
|
if base_types.is_debug_mode():
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import inspect
|
|
2
2
|
from typing import Callable, Union
|
|
3
3
|
|
|
4
4
|
import gamla
|
|
@@ -77,7 +77,7 @@ def unary_with_state_and_expectations(
|
|
|
77
77
|
def variadic_with_state_and_expectations(g, sink):
|
|
78
78
|
f = run.to_callable_strict(g)
|
|
79
79
|
|
|
80
|
-
if
|
|
80
|
+
if inspect.iscoroutinefunction(f):
|
|
81
81
|
|
|
82
82
|
async def inner(turns):
|
|
83
83
|
prev = {}
|
|
@@ -109,7 +109,7 @@ _is_graph_async = opt_gamla.compose_left(
|
|
|
109
109
|
opt_gamla.mapcat(lambda edge: (edge.source, *edge.args)),
|
|
110
110
|
opt_gamla.remove(gamla.equals(None)),
|
|
111
111
|
opt_gamla.map(base_types.node_implementation),
|
|
112
|
-
gamla.anymap(
|
|
112
|
+
gamla.anymap(inspect.iscoroutinefunction),
|
|
113
113
|
)
|
|
114
114
|
|
|
115
115
|
|
|
@@ -452,7 +452,7 @@ def _make_get_node_executor(
|
|
|
452
452
|
return result
|
|
453
453
|
|
|
454
454
|
all_nodes = graph.get_all_nodes(edges)
|
|
455
|
-
async_nodes = {n for n in all_nodes if
|
|
455
|
+
async_nodes = {n for n in all_nodes if inspect.iscoroutinefunction(n.func)}
|
|
456
456
|
sync = all_nodes - async_nodes
|
|
457
457
|
tf = graph.traverse_forward(edges)
|
|
458
458
|
downstream_from_async = set(gamla.graph_traverse_many(async_nodes, tf))
|
|
@@ -572,7 +572,9 @@ to_callable = to_callable_with_side_effect(gamla.just(gamla.just(None)))
|
|
|
572
572
|
|
|
573
573
|
|
|
574
574
|
def _node_is_properly_composed(
|
|
575
|
-
node_to_incoming_edges:
|
|
575
|
+
node_to_incoming_edges: Callable[
|
|
576
|
+
[base_types.ComputationNode], FrozenSet[base_types.ComputationEdge]
|
|
577
|
+
]
|
|
576
578
|
) -> Callable[[base_types.ComputationNode], bool]:
|
|
577
579
|
return gamla.compose_left(
|
|
578
580
|
graph.unbound_signature(node_to_incoming_edges),
|
|
@@ -581,7 +583,7 @@ def _node_is_properly_composed(
|
|
|
581
583
|
)
|
|
582
584
|
|
|
583
585
|
|
|
584
|
-
def _assert_composition_is_valid(g: base_types.
|
|
586
|
+
def _assert_composition_is_valid(g: typing.Iterable[base_types.ComputationEdge]):
|
|
585
587
|
return opt_gamla.pipe(
|
|
586
588
|
g,
|
|
587
589
|
graph.get_all_nodes,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import inspect
|
|
3
|
+
import types
|
|
3
4
|
from types import MappingProxyType
|
|
4
5
|
from typing import Callable, FrozenSet
|
|
5
6
|
|
|
@@ -39,7 +40,7 @@ _func_parameters = gamla.compose_left(
|
|
|
39
40
|
)
|
|
40
41
|
|
|
41
42
|
|
|
42
|
-
def
|
|
43
|
+
def _from_callable_via_inspect(func: Callable) -> base_types.NodeSignature:
|
|
43
44
|
function_parameters = _func_parameters(func)
|
|
44
45
|
return base_types.NodeSignature(
|
|
45
46
|
is_args=gamla.anymap(parameter_is_star)(function_parameters),
|
|
@@ -60,6 +61,40 @@ def from_callable(func: Callable) -> base_types.NodeSignature:
|
|
|
60
61
|
)
|
|
61
62
|
|
|
62
63
|
|
|
64
|
+
def _as_plain_function(func: Callable):
|
|
65
|
+
"""The `inspect.signature`-equivalent target when it is a plain function whose
|
|
66
|
+
signature is fully described by its code object, else None (wrappers with
|
|
67
|
+
`__signature__`, partials, methods, builtins and classes need `inspect`)."""
|
|
68
|
+
unwrapped = inspect.unwrap(func, stop=lambda f: hasattr(f, "__signature__"))
|
|
69
|
+
if not isinstance(unwrapped, types.FunctionType) or hasattr(
|
|
70
|
+
unwrapped, "__signature__"
|
|
71
|
+
):
|
|
72
|
+
return None
|
|
73
|
+
return unwrapped
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def from_callable(func: Callable) -> base_types.NodeSignature:
|
|
77
|
+
plain_function = _as_plain_function(func)
|
|
78
|
+
if plain_function is None:
|
|
79
|
+
return _from_callable_via_inspect(func)
|
|
80
|
+
code = plain_function.__code__
|
|
81
|
+
positional = code.co_varnames[: code.co_argcount]
|
|
82
|
+
keyword_only = code.co_varnames[
|
|
83
|
+
code.co_argcount : code.co_argcount + code.co_kwonlyargcount
|
|
84
|
+
]
|
|
85
|
+
defaults = plain_function.__defaults__ or ()
|
|
86
|
+
keyword_defaults = plain_function.__kwdefaults__ or {}
|
|
87
|
+
return base_types.NodeSignature(
|
|
88
|
+
is_args=bool(code.co_flags & inspect.CO_VARARGS),
|
|
89
|
+
is_kwargs=bool(code.co_flags & inspect.CO_VARKEYWORDS),
|
|
90
|
+
kwargs=positional + keyword_only,
|
|
91
|
+
optional_kwargs=(
|
|
92
|
+
positional[len(positional) - len(defaults) :]
|
|
93
|
+
+ tuple(name for name in keyword_only if name in keyword_defaults)
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
63
98
|
def parameters(signature: base_types.NodeSignature) -> FrozenSet[str]:
|
|
64
99
|
return frozenset(
|
|
65
100
|
{
|
|
@@ -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="
|
|
10
|
+
version="69",
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{computation_graph-68 → computation_graph-69}/computation_graph.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|