From 34194925d1a7051adcb2bcd1c98c0d5b6ed01b04 Mon Sep 17 00:00:00 2001 From: Romain Dorgueil Date: Sun, 2 Jun 2019 08:53:57 +0200 Subject: [PATCH] New syntax: Forks & merge polishing --- bin/update_apidoc.py | 1 - bonobo/structs/graphs.py | 7 +++++++ docs/guide/graphs.rst | 27 +++++++++++++++++++++++++ tests/structs/test_graphs_new_syntax.py | 20 ++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/bin/update_apidoc.py b/bin/update_apidoc.py index 2677900..b93cddf 100644 --- a/bin/update_apidoc.py +++ b/bin/update_apidoc.py @@ -31,7 +31,6 @@ class Module: return os.path.join(__path__, apidoc_root, *self.name.split(".")) + ".rst" - bonobo = __import__("bonobo") assert bonobo.__version__ diff --git a/bonobo/structs/graphs.py b/bonobo/structs/graphs.py index 8c0a22c..ce43ef6 100644 --- a/bonobo/structs/graphs.py +++ b/bonobo/structs/graphs.py @@ -104,6 +104,13 @@ class Graph: """ return GraphCursor(self, last=self.index_of(ref)) + def orphan(self): + """ + Create a `GraphCursor` attached to nothing. + + """ + return self.get_cursor(None) + def index_of(self, mixed): """ Find the index based on various strategies for a node, probably an input or output of chain. Supported diff --git a/docs/guide/graphs.rst b/docs/guide/graphs.rst index 694ad70..e6a83ba 100644 --- a/docs/guide/graphs.rst +++ b/docs/guide/graphs.rst @@ -396,6 +396,33 @@ You can also create single nodes, and the api provide the same capability on sin graph.add_chain(..., _output="foo") +Orphan nodes / chains +::::::::::::::::::::: + +The default behaviour of `add_chain` (or `get_cursor`) is to connect the first node to the special `BEGIN` token, which +instruct |bonobo| to call the connected node once without parameter to kickstart the data stream. + +This is normally what you want, but there are ways to override it, as you may want to add "orphan" nodes or chains to your graph. + +.. code-block:: python + + import bonobo + + graph = bonobo.Graph() + + # using add_node will naturally add a node as "orphan" + graph.add_node(a) + + # using add_chain with "None" as the input will create an orphan chain + graph.add_chain(a, b, c, _input=None) + + # using the new syntax, you can use either get_cursor(None) or the orphan() shortcut + graph.get_cursor(None) >> a >> b >> c + + # ... using the shortcut ... + graph.orphan() >> a >> b >> c + + Connecting two nodes :::::::::::::::::::: diff --git a/tests/structs/test_graphs_new_syntax.py b/tests/structs/test_graphs_new_syntax.py index 3ceb157..68f0e74 100644 --- a/tests/structs/test_graphs_new_syntax.py +++ b/tests/structs/test_graphs_new_syntax.py @@ -120,3 +120,23 @@ def test_cursor_merge(): assert g.outputs_of(c) == set() assert c1 == c2 + + +def test_cursor_merge_orphan_in_between(): + a, b, c, v, w, x, y = get_pseudo_nodes(*"abcdefg") + g = Graph() + g >> a >> b >> c + assert len(g) == 3 + g.orphan() >> v >> w >> b + assert len(g) == 5 + g.orphan() >> x >> y >> b + assert len(g) == 7 + + assert g.outputs_of(BEGIN) == g.indexes_of(a) + assert g.outputs_of(a) == g.indexes_of(b) + assert g.outputs_of(b) == g.indexes_of(c) + assert g.outputs_of(c) == set() + assert g.outputs_of(v) == g.indexes_of(w) + assert g.outputs_of(w) == g.indexes_of(b) + assert g.outputs_of(x) == g.indexes_of(y) + assert g.outputs_of(y) == g.indexes_of(b)