Skip to content

Commit 553b609

Browse files
author
ilgarlunin
committed
raw signals fixed. exposing pins on subgraph node. test
1 parent fc1a3f3 commit 553b609

File tree

7 files changed

+112
-37
lines changed

7 files changed

+112
-37
lines changed

PyFlow/Core/GraphBase.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111

1212

1313
class GraphBase(object):
14-
15-
onInputPinCreated = Signal(object)
16-
onInputPinDeleted = Signal(object)
17-
onOutputPinCreated = Signal(object)
18-
onOutputPinDeleted = Signal(object)
19-
2014
def __init__(self, name, *args, **kwargs):
2115
super(GraphBase, self).__init__(*args, **kwargs)
16+
# signals
17+
self.onInputPinCreated = Signal(object)
18+
self.onInputPinDeleted = Signal(object)
19+
self.onOutputPinCreated = Signal(object)
20+
self.onOutputPinDeleted = Signal(object)
21+
2222
self.__name = name
2323
self.nodes = {}
2424
self.connections = {}
@@ -154,7 +154,7 @@ def findPinByName(self, pinName):
154154
return pin
155155

156156
def getInputNode(self):
157-
"""Creates and adds graph inputs node. Note, this works only for graphs which has a parent
157+
"""Creates and adds to graph 'graphInputs' node. Note, this works only for graphs which has a parent
158158
159159
pins on this node will be exposed on subgraph node as input pins
160160
"""
@@ -164,6 +164,17 @@ def getInputNode(self):
164164
self.addNode(node)
165165
return node
166166

167+
def getOutputNode(self):
168+
"""Creates and adds to graph 'graphOutputs' node. Note, this works only for graphs which has a parent
169+
170+
pins on this node will be exposed on subgraph node as output pins
171+
"""
172+
node = None
173+
if GraphTree().getParentGraph(self) is not None:
174+
node = getRawNodeInstance("graphOutputs", "PyflowBase")
175+
self.addNode(node)
176+
return node
177+
167178
def addNode(self, node, jsonTemplate=None):
168179
assert(node is not None), "failed to add node, None is passed"
169180
if node.uid in self.nodes:

PyFlow/Core/GraphTree.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
class GraphTree:
1111
"""Graph tree. Here is all the data
1212
"""
13-
14-
onGraphSwitched = Signal()
15-
1613
def __init__(self, rootGraph=None):
1714
assert(rootGraph is not None)
15+
# signals
16+
self.onGraphSwitched = Signal()
17+
1818
self.__tree = Tree()
1919
self.__tree.create_node(rootGraph.name, rootGraph.name, data=rootGraph)
2020
self.__activeGraph = rootGraph

PyFlow/Core/PinBase.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from blinker import Signal
12
import uuid
23
from copy import deepcopy
34
import weakref
@@ -7,9 +8,15 @@
78

89

910
class PinBase(IPin):
10-
# TODO: remove dataType argument. This is redundant. We use __class__.__name__ wrapped in property
11+
# TODO: remove dataType argument. We should use __class__.__name__
1112
def __init__(self, name, owningNode, dataType, direction, userStructClass=None):
1213
super(PinBase, self).__init__()
14+
# signals
15+
self.onPinConnected = Signal(object)
16+
self.onPinDisconnected = Signal(object)
17+
self.nameChanged = Signal(str)
18+
self.killed = Signal()
19+
1320
self._uid = uuid.uuid4()
1421
self._dataType = None
1522
self._userStructClass = userStructClass
@@ -33,7 +40,7 @@ def __init__(self, name, owningNode, dataType, direction, userStructClass=None):
3340
self.direction = direction
3441
## This flag is for subgraph input nodes, to correctly establish connections
3542
self.actLikeDirection = direction
36-
## For rand int node
43+
## For rand int node and stuff like that
3744
self._alwaysPushDirty = False
3845
## Can be renamed or not (for switch on string node)
3946
self._renamingEnabled = False
@@ -106,8 +113,8 @@ def uid(self, value):
106113
self._uid = value
107114

108115
def setName(self, name):
109-
oldName = self.name
110116
self.name = name.replace(" ", "_")
117+
self.nameChanged.send(self.name)
111118

112119
def getName(self):
113120
return self.owningNode().name + '.' + self.name
@@ -209,17 +216,18 @@ def setUserStruct(self, inStruct):
209216

210217
def kill(self):
211218
self.owningNode().pins.pop(self.uid)
219+
self.killed.send()
212220

213221
def currentData(self):
214222
if self._data is None:
215223
return self._defaultValue
216224
return self._data
217225

218226
def pinConnected(self, other):
219-
pass
227+
self.onPinConnected.send(other)
220228

221229
def pinDisconnected(self, other):
222-
pass
230+
self.onPinDisconnected.send(other)
223231

224232
def setClean(self):
225233
self.dirty = False

PyFlow/Core/Variable.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88

99

1010
class Variable(ISerializable):
11-
12-
nameChanged = Signal()
13-
valueChanged = Signal()
14-
dataTypeChanged = Signal()
15-
accessLevelChanged = Signal()
16-
packageNameChanged = Signal()
17-
uuidChanged = Signal()
18-
killed = Signal()
19-
2011
def __init__(self, value, name, dataType, accessLevel=AccessLevel.public, uid=None):
2112
super(Variable, self).__init__()
2213
assert(isinstance(name, str))
2314
assert(isinstance(dataType, str))
15+
# signals
16+
self.nameChanged = Signal()
17+
self.valueChanged = Signal()
18+
self.dataTypeChanged = Signal()
19+
self.accessLevelChanged = Signal()
20+
self.packageNameChanged = Signal()
21+
self.uuidChanged = Signal()
22+
self.killed = Signal()
23+
2424
self._name = name
2525
self._value = value
2626
self._dataType = dataType

PyFlow/Packages/PyflowBase/Nodes/graphNodes.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
class graphInputs(NodeBase):
88
"""Represents a group of input pins on subgraph node
99
"""
10-
onPinCreated = Signal(object)
11-
1210
def __init__(self, name):
1311
super(graphInputs, self).__init__(name)
12+
self.onPinCreated = Signal(object)
1413

1514
@staticmethod
1615
def pinTypeHints():
@@ -39,8 +38,10 @@ def addOutPin(self):
3938
def postCreate(self, jsonTemplate=None):
4039
super(graphInputs, self).postCreate(jsonTemplate=jsonTemplate)
4140
# recreate dynamically created pins
42-
# before this, connect with owning graph
41+
# connect with owning graph before
4342
self.onPinCreated.connect(self.graph().onInputPinCreated.send)
43+
# add outputs
44+
pass
4445

4546
def compute(self):
4647
# This node is special. Output pins of this node are actually inputs pins in terms of execution and data gathering
@@ -54,10 +55,9 @@ def compute(self):
5455
class graphOutputs(NodeBase):
5556
"""Represents a group of output pins on subgraph node
5657
"""
57-
onPinCreated = Signal(object)
58-
5958
def __init__(self, name):
6059
super(graphOutputs, self).__init__(name)
60+
self.onPinCreated = Signal(object)
6161

6262
@staticmethod
6363
def pinTypeHints():
@@ -75,6 +75,14 @@ def keywords():
7575
def description():
7676
return ''
7777

78+
def postCreate(self, jsonTemplate=None):
79+
super(graphOutputs, self).postCreate(jsonTemplate=jsonTemplate)
80+
# recreate dynamically created pins
81+
# connect with owning graph before
82+
self.onPinCreated.connect(self.graph().onOutputPinCreated.send)
83+
# add outputs
84+
pass
85+
7886
def addInPin(self):
7987
name = str(len(self.outputs))
8088
p = self.addInputPin(name, 'AnyPin')

PyFlow/Packages/PyflowBase/Nodes/subgraph.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class subgraph(NodeBase):
1515
def __init__(self, name):
1616
super(subgraph, self).__init__(name)
1717
self.rawGraph = None
18+
self.__inputsMap = {} # { self.[inputPin].uid: innerPinUid }
19+
self.__outputsMap = {} # { self.[outputPin].uid: innerPinUid }
1820

1921
@staticmethod
2022
def pinTypeHints():
@@ -32,21 +34,45 @@ def keywords():
3234
def description():
3335
return 'Encapsulate a graph inside a node'
3436

35-
def onGraphInputPinCreated(self, inPin):
36-
# add companion pin for inner graphInputs node pin
37-
pass
37+
def onGraphInputPinCreated(self, outPin):
38+
"""Reaction when pin added to graphInputs node
39+
40+
Arguments:
41+
outPin {PinBase} -- output pin on graphInputs node
42+
"""
43+
44+
# add companion pin for graphInputs node's output pin
45+
subgraphInputPin = self.addInputPin(outPin.name,
46+
outPin.dataType,
47+
outPin.defaultValue(),
48+
outPin.call,
49+
outPin.constraint,
50+
outPin.supportedDataTypes())
51+
self.__inputsMap[subgraphInputPin.uid] = outPin.uid
52+
# connect
53+
outPin.nameChanged.connect(subgraphInputPin.setName)
54+
outPin.killed.connect(subgraphInputPin.kill)
3855

3956
def onGraphInputPinDeleted(self, inPin):
4057
# remove companion pin for inner graphInputs node pin
41-
pass
58+
print("onGraphInputPinDeleted", inPin.getName())
4259

43-
def onGraphOutputPinCreated(self, outPin):
44-
# add companion pin for inner graphOutputs node pin
45-
pass
60+
def onGraphOutputPinCreated(self, inPin):
61+
# add companion pin for graphOutputs node's input pin
62+
subgraphOutputPin = self.addOutputPin(inPin.name,
63+
inPin.dataType,
64+
inPin.defaultValue(),
65+
inPin.call,
66+
inPin.constraint,
67+
inPin.supportedDataTypes())
68+
self.__outputsMap[subgraphOutputPin.uid] = inPin.uid
69+
# connect
70+
inPin.nameChanged.connect(subgraphOutputPin.setName)
71+
inPin.killed.connect(subgraphOutputPin.kill)
4672

4773
def onGraphOutputPinDeleted(self, outPin):
4874
# remove companion pin for inner graphOutputs node pin
49-
pass
75+
print("onGraphOutputPinDeleted", outPin.getName())
5076

5177
def postCreate(self, jsonTemplate=None):
5278
self.rawGraph = GraphBase(self.name)

PyFlow/Tests/Test_General.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,29 @@ def test_subgraph(self):
323323

324324
# add input output nodes to expose pins to outer subgraph node
325325
inputs1 = GT.activeGraph().getInputNode()
326+
outputs1 = GT.activeGraph().getOutputNode()
326327
self.assertIsNotNone(inputs1, "failed to create graph inputs node")
328+
self.assertIsNotNone(outputs1, "failed to create graph outputs node")
329+
330+
# create out pin on graphInputs node
331+
# this should expose input pin on subgraph node
332+
outPin = inputs1.addOutPin()
333+
self.assertEqual(len(subgraphNodeInstance.namePinInputsMap), 1, "failed to expose input pin")
334+
self.assertEqual(list(subgraphNodeInstance.inputs.values())[0].name, outPin.name)
335+
336+
# change inner pin name and check it is reflected outside
337+
outPin.setName("first")
338+
self.assertEqual(list(subgraphNodeInstance.inputs.values())[0].name, outPin.name, "name is not synchronized")
339+
340+
# create input pin on graphOutputs node
341+
# this should expose output pin on subgraph node
342+
inPin = outputs1.addInPin()
343+
self.assertEqual(len(subgraphNodeInstance.namePinOutputsMap), 1, "failed to expose input pin")
344+
self.assertEqual(list(subgraphNodeInstance.outputs.values())[0].name, inPin.name)
345+
346+
# change inner pin name and check it is reflected outside
347+
inPin.setName("first")
348+
self.assertEqual(list(subgraphNodeInstance.outputs.values())[0].name, inPin.name, "name is not synchronized")
327349

328350
# add simple calculation
329351

0 commit comments

Comments
 (0)