Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 44 additions & 39 deletions notebooks/deepdive.ipynb

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions pyiron_workflow/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,8 @@ class SignalChannel(Channel, ABC):

Inputs hold a callback function to call, and outputs call each of their connections.

Signal channels support `>` as syntactic sugar for their connections, i.e.
`some_output > some_input` is equivalent to `some_input.connect(some_output)`.
Signal channels support `>>` as syntactic sugar for their connections, i.e.
`some_output >> some_input` is equivalent to `some_input.connect(some_output)`.
(This is also interoperable with `Node` objects, cf. the `Node` docs.)
"""

Expand Down Expand Up @@ -599,9 +599,9 @@ def __str__(self):
f"{[f'{c.node.label}.{c.label}' for c in self.connections]}"
)

def __gt__(self, other: InputSignal | Node):
def __rshift__(self, other: InputSignal | Node):
other._connect_output_signal(self)
return True
return other

def _connect_accumulating_input_signal(self, signal: AccumulatingInputSignal):
self.connect(signal)
7 changes: 3 additions & 4 deletions pyiron_workflow/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,9 @@ class Function(Node):
>>>
>>> adder = adder_node()
>>> alpha = AlphabetModThree(i=adder.outputs.sum)
>>> adder > alpha # Ignore the `True`, this is just because we need it to chain
True

>>>
>>> _ = adder >> alpha
>>> # We catch and ignore output -- it's needed for chaining, but screws up
>>> # doctests -- you don't normally need to catch it like this!
>>> out = adder.run(x=1)
>>> print(alpha.outputs.letter)
b
Expand Down
8 changes: 4 additions & 4 deletions pyiron_workflow/macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Macro(Composite):
... macro.one = macro.create.SingleValue(add_one)
... macro.two = macro.create.SingleValue(add_one, macro.one)
... macro.three = macro.create.SingleValue(add_one, macro.two)
... macro.one > macro.two > macro.three
... macro.one >> macro.two >> macro.three
... macro.starting_nodes = [macro.one]

In this case we had _no need_ to specify the execution order and starting nodes
Expand Down Expand Up @@ -138,9 +138,9 @@ class Macro(Composite):
signals, but beyond that the code doesn't hold our hands.
Let's use this and then observe how the `a` sub-node no longer gets run:
>>> m.starting_nodes = [m.b] # At least one starting node
>>> m.b > m.c # At least one run signal (ignore `True`, it's for chaining)
True

>>> _ = m.b >> m.c # At least one run signal
>>> # We catch and ignore output -- it's needed for chaining, but screws up
>>> # doctests -- you don't normally need to catch it like this!
>>> m(a__x=1000, b__x=2000, c__x=3000)
{'a__result': 2, 'b__result': 2001, 'c__result': 3001}

Expand Down
2 changes: 1 addition & 1 deletion pyiron_workflow/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def make_loop(macro):
for out_n, out_c, in_n, in_c in internal_connection_map:
macro.nodes[in_n].inputs[in_c] = macro.nodes[out_n].outputs[out_c]

switch.signals.output.true > body_node > condition_node > switch
switch.signals.output.true >> body_node >> condition_node >> switch
macro.starting_nodes = [body_node]

macro.inputs_map = {} if inputs_map is None else inputs_map
Expand Down
6 changes: 3 additions & 3 deletions pyiron_workflow/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -735,12 +735,12 @@ def __str__(self):
def _connect_output_signal(self, signal: OutputSignal):
self.signals.input.run.connect(signal)

def __gt__(self, other: InputSignal | Node):
def __rshift__(self, other: InputSignal | Node):
"""
Allows users to connect run and ran signals like: `first_node > second_node`.
Allows users to connect run and ran signals like: `first_node >> second_node`.
"""
other._connect_output_signal(self.signals.output.ran)
return True
return other

def _connect_accumulating_input_signal(self, signal: AccumulatingInputSignal):
self.signals.output.ran.connect(signal)
Expand Down
2 changes: 1 addition & 1 deletion pyiron_workflow/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def _set_run_connections_according_to_linear_dag(nodes: dict[str, Node]) -> list

for i, label in enumerate(execution_order[:-1]):
next_node = execution_order[i + 1]
nodes[label] > nodes[next_node]
nodes[label] >> nodes[next_node]

return [nodes[execution_order[0]]]

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_parallel_speedup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def make_workflow(label):
t = 2.5

wf = make_workflow("serial")
wf.a > wf.b > wf.c > wf.d
wf.a >> wf.b >> wf.c >> wf.d
wf.starting_nodes = [wf.a]
t0 = perf_counter()
wf()
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def sqrt(value=0):
wf.sqrt = sqrt()
wf.sqrt.inputs.value = wf.rand

wf.gt_switch.signals.output.false > wf.rand > wf.gt_switch # Loop on false
wf.gt_switch.signals.output.true > wf.sqrt # On true break to sqrt node
wf.gt_switch.signals.output.false >> wf.rand >> wf.gt_switch # Loop on false
wf.gt_switch.signals.output.true >> wf.sqrt # On true break to sqrt node
wf.starting_nodes = [wf.rand]

wf.run()
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def test_connections(self):

with self.subTest("Test syntactic sugar"):
self.out.disconnect_all()
self.out > self.inp
self.out >> self.inp
self.assertIn(self.out, self.inp.connections)

def test_calls(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ def test_run(self):
self.comp.create.SingleValue(plus_one, label="n1", x=0)
self.comp.create.SingleValue(plus_one, label="n2", x=self.comp.n1)
self.comp.create.SingleValue(plus_one, label="n3", x=42)
self.comp.n1 > self.comp.n2
self.comp.n1 >> self.comp.n2
self.comp.starting_nodes = [self.comp.n1]

self.comp.run()
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def test_instantiation(self):
node.outputs.y,
msg="Should be able to make a connection at initialization"
)
node > node2
node >> node2
node.run()
self.assertEqual(4, node2.outputs.y.value, msg="Initialize from connection")

Expand Down Expand Up @@ -318,7 +318,7 @@ def test_copy_connections(self):
upstream = Function(plus_one)
to_copy = Function(plus_one, x=upstream.outputs.y)
downstream = Function(plus_one, x=to_copy.outputs.y)
upstream > to_copy > downstream
upstream >> to_copy >> downstream

wrong_io = Function(
returns_multiple, x=upstream.outputs.y, y=upstream.outputs.y
Expand Down Expand Up @@ -549,7 +549,7 @@ def test_easy_output_connection(self):
"output and another node's input by passing themselves"
)

svn > regular
svn >> regular
svn.run()
self.assertEqual(
regular.outputs.y.value, 3,
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@ def do_nothing():
signals.output.ran = OutputSignal("ran", node)
signals.output.bar = OutputSignal("bar", node)

signals.output.ran > signals.input.run
signals.output.ran > signals.input.foo
signals.output.bar > signals.input.run
signals.output.bar > signals.input.foo
signals.output.ran >> signals.input.run
signals.output.ran >> signals.input.foo
signals.output.bar >> signals.input.run
signals.output.bar >> signals.input.foo

self.signals = signals

Expand Down
12 changes: 6 additions & 6 deletions tests/unit/test_macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ def test_execution_automation(self):

def fully_defined(macro):
add_three_macro(macro)
macro.one > macro.two > macro.three
macro.one >> macro.two >> macro.three
macro.starting_nodes = [macro.one]

def only_order(macro):
add_three_macro(macro)
macro.two > macro.three
macro.two >> macro.three

def only_starting(macro):
add_three_macro(macro)
Expand Down Expand Up @@ -198,7 +198,7 @@ def nested_macro(macro):
add_one,
x=macro.c.outputs.three__result,
)
macro.a > macro.b > macro.c > macro.d
macro.a >> macro.b >> macro.c >> macro.d
macro.starting_nodes = [macro.a]
# This definition of the execution graph is not strictly necessary in this
# simple DAG case; we just do it to make sure nesting definied/automatic
Expand All @@ -211,7 +211,7 @@ def nested_macro(macro):
def test_with_executor(self):
macro = Macro(add_three_macro)
downstream = SingleValue(add_one, x=macro.outputs.three__result)
macro > downstream # Manually specify since we'll run the macro but look
macro >> downstream # Manually specify since we'll run the macro but look
# at the downstream output, and none of this is happening in a workflow

original_one = macro.one
Expand Down Expand Up @@ -314,7 +314,7 @@ def cyclic_macro(macro):
macro.one = SingleValue(add_one)
macro.two = SingleValue(add_one, x=macro.one)
macro.one.inputs.x = macro.two
macro.one > macro.two
macro.one >> macro.two
macro.starting_nodes = [macro.one]
# We need to manually specify execution since the data flow is cyclic

Expand Down Expand Up @@ -395,7 +395,7 @@ def fail_at_zero(x):
n1 = SingleValue(fail_at_zero, x=0)
n2 = SingleValue(add_one, x=n1, label="n1")
n_not_used = SingleValue(add_one)
n_not_used > n2 # Just here to make sure it gets restored
n_not_used >> n2 # Just here to make sure it gets restored

with self.assertRaises(
ZeroDivisionError,
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def test_force_local_execution(self):
self.n2.executor_shutdown()

def test_emit_ran_signal(self):
self.n1 > self.n2 > self.n3 # Chained connection declaration
self.n1 >> self.n2 >> self.n3 # Chained connection declaration

self.n1.run(emit_ran_signal=False)
self.assertFalse(
Expand All @@ -213,7 +213,7 @@ def test_emit_ran_signal(self):

def test_execute(self):
self.n1.outputs.y = 0 # Prime the upstream data source for fetching
self.n2 > self.n3
self.n2 >> self.n3
self.assertEqual(
self.n2.run(fetch_input=False, emit_ran_signal=False, x=10) + 1,
self.n2.execute(x=11),
Expand All @@ -234,7 +234,7 @@ def test_execute(self):
self.n2.execute()

def test_pull(self):
self.n2 > self.n3
self.n2 >> self.n3
self.n1.inputs.x = 0
by_run = self.n2.run(
run_data_tree=True,
Expand All @@ -256,7 +256,7 @@ def test_pull(self):
def test___call__(self):
# __call__ is just a pull that punches through macro walls, so we'll need to
# test it again over in macro to really make sure it's working
self.n2 > self.n3
self.n2 >> self.n3
self.n1.inputs.x = 0
by_run = self.n2.run(
run_data_tree=True,
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,9 @@ def matches_expectations(results):

user = make_workflow()
user.automate_execution = False
user.n1l > user.n1r > user.n2l
user.n1r > user.n2m
user.n1r > user.n2r
user.n1l >> user.n1r >> user.n2l
user.n1r >> user.n2m
user.n1r >> user.n2r
user.starting_nodes = [user.n1l]
self.assertTrue(
matches_expectations(user()),
Expand Down