-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnodes.py
More file actions
executable file
·133 lines (98 loc) · 3.68 KB
/
Copy pathnodes.py
File metadata and controls
executable file
·133 lines (98 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from .packer import argspack, test_argpack
from .ident import IDFunc
def as_unit(u, node_class=None, **node_kwargs):
if is_unit(u, node_class):
return u
return (node_class or Unit)(u,**node_kwargs)
def as_units(*items, node_class=None, **node_kwargs):
r = ()
for item in items:
r += (as_unit(item, node_class=node_class, **node_kwargs),)
return r
def is_unit(u, node_class=None):
types = (Unit,)
if node_class is not None:
types += (node_class,)
return isinstance(u, types)
CACHE = {}
class UnsetSentinal:
pass
UNSET = UnsetSentinal()
def get_edge_func():
r = CACHE.get('make_edge')
if r:
return r
from .edges import make_edge
CACHE['make_edge'] = make_edge
return make_edge
class Unit(IDFunc):
merge_node = False
name = None
sentinal = UNSET
def __init__(self, func, **node_kwargs):
self.func = func
self.__dict__.update(node_kwargs)
def __str__(self):
return self.as_str()
def __repr__(self):
return f"<{self.as_str()}>"
def as_str(self):
n = self.get_name()
return f"{self.__class__.__name__}(func={n})"
def get_name(self):
f = self.func
n = self.name or (f.__name__ if hasattr(f, '__name__') else str(f))
return n
def get_outbound_connections(self, graph):
"""Return all outbound connections from this node in the given graph."""
connections = graph.get(self.id(), None)
return connections
def get_inbound_connections(self, graph):
"""Return all inbound connections to this node in the given graph.
Note: The graph stores each edge twice (once by edge ID, once by node A ID),
so we deduplicate by edge ID to return unique connections only.
"""
seen = set()
inbound = []
for edges in graph.values():
for edge in edges:
edge_id = edge.id()
if edge.b.id() == self.id() and edge_id not in seen:
seen.add(edge_id)
inbound.append(edge)
return inbound
def input(self, a, kw):
"""Run the function through the graph, events will propogate into
the event tree.
"""
# Put the result into the event tree.
return self.process(a, kw)
def leaf(self, stepper, akw):
"""The stepper hit the tip of a branch and this node was the leaf
Capture "end" events and return a row result.
In this case the leaf hasn't been processed yet. This is because
"process" is done through a Connection.A call, or a PartialConnection
call.
As such, perform any final processing, such as executing the
process() function, and update the result ready for the next _stash_
event.
To follow the stepper path, return the result with no destination (default)
return connections to continue this path.
def leaf(self, stepper, akw):
rows = (
(None, argspack(akw))
)
return rows
"""
res = argspack(self.process(*akw.a,**akw.kw))
return stepper.end_branch(self, res)
def process(self, *a, **kw):
"""Run the function without the strings.
"""
is_nully = len(a) == 1 and a[0] is self.sentinal
return self.func(*(() if is_nully else a), **kw)
class Nodes(Unit):
def process(self, *a, **kw):
"""Run the function without the strings.
"""
return self.func(*a, **kw)