def test_graph_topological_sort(): g = Graph() g.add_chain( sentinel.a1, sentinel.a2, sentinel.a3, _input=None, _output=None, ) assert g.topologically_sorted_indexes == (0, 1, 2) assert g[0] == sentinel.a1 assert g[1] == sentinel.a2 assert g[2] == sentinel.a3 g.add_chain( sentinel.b1, sentinel.b2, _output=sentinel.a2, ) assert g.topologically_sorted_indexes[-2:] == (1, 2) assert g.topologically_sorted_indexes.index(3) < g.topologically_sorted_indexes.index(4) assert g[3] == sentinel.b1 assert g[4] == sentinel.b2
def test_simple_execution_context(): graph = Graph() graph.add_chain(*chain) context = GraphExecutionContext(graph) assert len(context.nodes) == len(chain) assert not len(context.plugins) for i, node in enumerate(chain): assert context[i].wrapped is node assert not context.alive assert not context.started assert not context.stopped context.write(BEGIN, (), END) assert not context.alive assert not context.started assert not context.stopped context.start() assert context.alive assert context.started assert not context.stopped context.stop() assert not context.alive assert context.started assert context.stopped
def test_simple_execution_context(): graph = Graph() graph.add_chain(*chain) ctx = GraphExecutionContext(graph) assert len(ctx.nodes) == len(chain) assert not len(ctx.plugins) for i, node in enumerate(chain): assert ctx[i].wrapped is node assert not ctx.alive assert not ctx.started assert not ctx.stopped ctx.recv(BEGIN, Bag(), END) assert not ctx.alive assert not ctx.started assert not ctx.stopped ctx.start() assert ctx.alive assert ctx.started assert not ctx.stopped ctx.stop() assert not ctx.alive assert ctx.started assert ctx.stopped
def test_execution(): graph = Graph() graph.add_chain(*chain) strategy = NaiveStrategy() ctx = strategy.execute(graph) assert ctx.results == [1, 4, 9, 16, 25, 36, 49, 64, 81]
def test_graph_add_chain(): g = Graph() assert len(g.nodes) == 0 g.add_chain(identity, identity, identity) assert len(g.nodes) == 3 assert len(g.outputs_of(BEGIN)) == 1
def test_graph_add_component(): g = Graph() assert len(g.nodes) == 0 g.add_node(identity) assert len(g.nodes) == 1 g.add_node(identity) assert len(g.nodes) == 2
def test_empty_execution_context(): graph = Graph() ctx = GraphExecutionContext(graph) assert not len(ctx.nodes) assert not len(ctx.plugins) assert not ctx.alive
def test_copy(): g1 = Graph() g2 = g1.copy() assert g1 is not g2 assert len(g1) == 0 assert len(g2) == 0 g1.add_chain([]) assert len(g1) == 1 assert len(g2) == 0 g2.add_chain([], identity) assert len(g1) == 1 assert len(g2) == 2
def test_graph_topological_sort(): g = Graph() g.add_chain( sentinel.a1, sentinel.a2, sentinel.a3, _input=None, _output=None, ) assert g.topologically_sorted_indexes == (0, 1, 2) assert g[0] == sentinel.a1 assert g[1] == sentinel.a2 assert g[2] == sentinel.a3 g.add_chain( sentinel.b1, sentinel.b2, _output=sentinel.a2, ) assert g.topologically_sorted_indexes[-2:] == (1, 2) assert g.topologically_sorted_indexes.index( 3) < g.topologically_sorted_indexes.index(4) assert g[3] == sentinel.b1 assert g[4] == sentinel.b2
def test_graph_outputs_of(): g = Graph() # default graph only node assert len(g.outputs_of(BEGIN)) == 0 # unexisting node with pytest.raises(KeyError): g.outputs_of(0) # create node assert len(g.outputs_of(0, create=True)) == 0 assert len(g.outputs_of(0)) == 0
def run(graph, *chain, strategy=None, plugins=None, services=None): """ Main entry point of bonobo. It takes a graph and creates all the necessary plumbery around to execute it. The only necessary argument is a :class:`Graph` instance, containing the logic you actually want to execute. By default, this graph will be executed using the "threadpool" strategy: each graph node will be wrapped in a thread, and executed in a loop until there is no more input to this node. You can provide plugins factory objects in the plugins list, this function will add the necessary plugins for interactive console execution and jupyter notebook execution if it detects correctly that it runs in this context. You'll probably want to provide a services dictionary mapping service names to service instances. :param Graph graph: The :class:`Graph` to execute. :param str strategy: The :class:`bonobo.strategies.base.Strategy` to use. :param list plugins: The list of plugins to enhance execution. :param dict services: The implementations of services this graph will use. :return bonobo.execution.graph.GraphExecutionContext: """ if len(chain): warnings.warn( 'DEPRECATED. You should pass a Graph instance instead of a chain.') from bonobo import Graph graph = Graph(graph, *chain) strategy = create_strategy(strategy) plugins = plugins or [] if _is_interactive_console(): from bonobo.ext.console import ConsoleOutputPlugin if ConsoleOutputPlugin not in plugins: plugins.append(ConsoleOutputPlugin) if _is_jupyter_notebook(): from bonobo.ext.jupyter import JupyterOutputPlugin if JupyterOutputPlugin not in plugins: plugins.append(JupyterOutputPlugin) return strategy.execute(graph, plugins=plugins, services=services)