コード例 #1
0
    def _build_network(self):
        # the graph is a class attribute, so we have to make a deep copy to
        # avoid side-effects
        graph = self.subgraph.copy()
        for (name, internal_port) in graph.inports.items():
            subcomp = graph.add_component('_' + name, SubIn)
            graph.initialize(self.ports[name], subcomp.ports.PROXIED)
            graph.connect(subcomp.ports.OUT, internal_port)

        for (name, internal_port) in graph.outports.items():
            subcomp = graph.add_component('_' + name, SubOut)
            graph.initialize(self.ports[name], subcomp.ports.PROXIED)
            graph.connect(internal_port, subcomp.ports.IN)

        # don't do deadlock testing in sub graphs - you need to consider
        # the whole graph!
        network = Network(graph, deadlock_test_interval=None)
        # set the network parent. this allows runners within the network to
        # walk up the network parents to the root
        network.parent_network = self._runner.parent_network
        return network
コード例 #2
0
ファイル: test_subnet.py プロジェクト: nrusch/rill
def test_name():
    root = Graph(name='root')
    passnet = root.add_component("Subnet", PassthruNet)
    child = passnet.subgraph.component("Pass")

    assert passnet._runner is None
    assert passnet.get_parents() == []
    assert passnet.get_full_name() == 'Subnet'

    assert child._runner is None
    assert child.get_parents() == []
    assert child.get_full_name() == 'Pass'

    # a component's full name is not available until all of the graphs' and
    # sub-graphs' runners have been initialized.
    # this is the result of two conflicting requirements:
    #  - graphs should not be modified during execution.  in other words,
    #    there should be no side-effects.  this means that a graph cannot have
    #    a parent graph attribute, we must track that relationship elsewhere.
    #  - delay building runners until absolutely necessary.  this means that
    #    a component, which *can* have a parent, is not available until the
    #    graph is executed.
    # we might want to revisit this if it becomes a nuisance.
    net = Network(root)
    net._build_runners()
    assert passnet._runner is not None
    assert passnet.get_parents() == [root]

    # building the network does a deep copy of the graph and its components
    snet = passnet._build_network()
    assert snet.graph is not passnet.subgraph
    assert child is passnet.subgraph.component('Pass')
    child_copy = snet.graph.component('Pass')
    assert child is not child_copy
    assert type(child) is type(child_copy)

    snet._build_runners()
    assert child_copy._runner is not None
    assert snet.parent_network is not None
    assert child_copy.get_full_name() == 'root.Subnet.Pass'
コード例 #3
0
def test_basic_connections():
    graph = Graph()
    count = graph.add_component("Count", Counter)
    dis = graph.add_component("Discard1", Discard)
    graph.add_component("Discard2", Discard)

    # ports are stored in the order they are declared
    assert names(count.outports) == ['OUT', 'COUNT']
    # assert list(count.ports._ports.keys()) == ['OUT', 'COUNT', 'NULL']

    # nothing is connected yet
    assert count.ports['OUT'].is_connected() is False
    assert dis.ports['IN'].is_connected() is False

    with pytest.raises(FlowError):
        # non-existent port
        graph.connect("Count.FOO", "Discard1.IN")

    with pytest.raises(FlowError):
        # non-existent Component
        graph.connect("Foo.FOO", "Discard1.IN")

    # make a connection
    graph.connect("Count.OUT", "Discard1.IN")

    # outports can have more than one connection
    graph.connect("Count.OUT", "Discard2.IN")

    with pytest.raises(FlowError):
        # connected ports cannot be initialized
        graph.initialize(1, "Discard1.IN")

    assert type(count.ports['OUT']) is OutputPort
    assert type(dis.ports['IN']) is InputPort
    assert count.ports['OUT'].is_connected() is True
    assert dis.ports['IN'].is_connected() is True

    # FIXME: move this to a different test
    net = Network(graph)
    net.reset()
    net._build_runners()
    net._open_ports()
    assert count.ports['OUT'].component is count
    assert isinstance(count.ports['OUT'].sender, ComponentRunner)
    assert dis.ports['IN'].component is dis
    assert isinstance(dis.ports['IN'].receiver, ComponentRunner)
コード例 #4
0
def runtwice(grph, *pairs):
    """Run a network twice to ensure that it shuts down properly"""
    network = Network(grph)
    with gevent.Timeout(2):
        network.go()
        for real, ref in pairs:
            assert real.values == ref
            real.values = []
        network.go()
        for real, ref in pairs:
            assert real.values == ref
コード例 #5
0
    def start(self, graph_id, done_callback):
        """
        Execute a graph.
        """
        self.logger.debug('Graph {}: Starting execution'.format(graph_id))

        graph = self.get_graph(graph_id)

        network = Network(graph)
        executor = gevent.Greenlet(network.go)
        # FIXME: should we delete the executor from self._executors on finish?
        # this has an impact on the result returned from get_status().  Leaving
        # it means that after completion it will be started:True, running:False
        # until stop() is triggered, at which point it will be started:False,
        # running:False
        executor.link(lambda g: done_callback())
        self._executors[graph_id] = (executor, network)
        executor.start()
コード例 #6
0
def test_pickle(graph):
    graph.add_component("Generate", GenerateTestData, COUNT=5)
    passthru = graph.add_component("Pass", SlowPass, DELAY=0.1)
    count = graph.add_component("Counter", Counter)
    dis1 = graph.add_component("Discard1", Discard)
    dis2 = graph.add_component("Discard2", Discard)

    graph.connect("Generate.OUT", "Pass.IN")
    graph.connect("Pass.OUT", "Counter.IN")
    graph.connect("Counter.COUNT", "Discard1.IN")
    graph.connect("Counter.OUT", "Discard2.IN")

    net = Network(graph)
    netrunner = gevent.spawn(net.go)
    try:
        with gevent.Timeout(.35) as timeout:
            gevent.wait([netrunner])
    except gevent.Timeout:
        print(count.execute)

    assert count.count == 4
    assert dis2.values == ['000005', '000004', '000003', '000002']

    import pickle
    # dump before terminating to get the runner statuses
    data = pickle.dumps(net)
    # FIXME: do we need to auto-terminate inside wait_for_all if there is an error?
    net.terminate()
    net.wait_for_all()
    # gevent.wait([netrunner])  # this causes more packets to be sent. no good.
    net2 = pickle.loads(data)
    assert net2.graph.component('Counter').count == 4
    assert net2.graph.component('Discard2').values == [
        '000005', '000004', '000003', '000002'
    ]
    net2.go(resume=True)
    assert net2.graph.component('Counter').count == 5
    assert net2.graph.component('Discard2').values == [
        '000005', '000004', '000003', '000002', '000001'
    ]
コード例 #7
0
            if line:
                line += " "
            line += word
    if line:
        # remainder
        OUT.send(line)

@component
@outport("OUT", type=str)
@inport("IN", type=str)
def LineToWords(IN, OUT):
    for line in IN.iter_contents():
        words = line.split()
        for word in words:
            OUT.send(word)


net = Graph()
net.add_component("LineToWords", LineToWords, IN="HeLLo Goodbye World")
net.add_component("StartsWith", StartsWith, TEST='G')
net.add_component("WordsToLine", WordsToLine)
dis = net.add_component("Output", Output)

net.connect("LineToWords.OUT", "StartsWith.IN")
net.connect("StartsWith.REJ", "WordsToLine.IN")
net.connect("WordsToLine.OUT", "Output.IN")

net =Network(net)
net.go()

コード例 #8
0
import ast
from rill.engine.network import Graph, Network
from rill.components.hello_world import LineToWords, StartsWith, WordsToLine, Output

graph_file = open('example_serialized.txt')
graph_str = graph_file.read()
graph_file.close()
graph_from_file = ast.literal_eval(graph_str)

graph = Graph.from_dict(graph_from_file)
net = Network(graph)
net.go()