Example #1
0
def test_array_connections():
    graph = Graph()
    gen = graph.add_component("Generate", GenerateArray)
    dis1 = graph.add_component("Discard1", Discard)
    graph.add_component("Discard2", Discard)

    assert gen.ports['OUT'].get_full_name() == 'Generate.OUT'

    # non-fixed array ports delay element creation
    assert gen.ports.OUT.fixed_size is None
    assert names(gen.outports) == []
    # assert list(gen.ports._ports.keys()) == ['OUT', 'NULL']
    assert type(gen.ports['OUT']) is OutputArray
    assert type(dis1.ports['IN']) is InputPort

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

    # make a connection
    graph.connect("Generate.OUT[1]", "Discard1.IN")
    assert names(gen.outports) == ['OUT[1]']
    assert gen.ports['OUT'][1].is_connected() is True

    # uses first unused index (index 0)
    graph.connect("Generate.OUT", "Discard2.IN")
    assert names(gen.outports) == ['OUT[0]', 'OUT[1]']
    assert gen.ports['OUT'][0].is_connected() is True

    assert type(gen.ports['OUT']) is OutputArray
    assert type(gen.ports['OUT'][0]) is OutputPort
    assert type(dis1.ports['IN']) is InputPort
    # assert gen.ports['OUT'].is_connected() is False
    assert dis1.ports['IN'].is_connected() is True
Example #2
0
def test_static_type_validation():
    """When initializing a port to a static value, the type is immediately
    validated"""
    graph = Graph()

    with pytest.raises(FlowError):
        graph.add_component("Repeat", Repeat, COUNT='foo')
Example #3
0
def test_inport_default():
    graph = Graph()
    graph.add_component("Generate", GenerateTestData)
    dis = graph.add_component("Discard", Discard)
    graph.connect("Generate.OUT", "Discard.IN")
    run_graph(graph)
    assert dis.values == ['000001']
Example #4
0
def test_make_subgraph():
    sub = Graph()
    sub.add_component('Head', Passthru)
    sub.add_component('Tail', Passthru)

    sub.connect('Head.OUT', 'Tail.IN')

    sub.export('Head.IN', 'IN')
    sub.export('Tail.OUT', 'OUT')

    PassNet = make_subgraph(sub, name='PassNet')

    assert len(PassNet.inport_definitions) == 2
    assert len(PassNet.outport_definitions) == 2

    graph = Graph()
    capture = graph.add_component('Capture', Capture)

    graph.add_component('Pass', PassNet)
    graph.initialize(5, 'Pass.IN')
    graph.connect('Pass.OUT', 'Capture.IN')

    run_graph(graph)

    assert capture.value == 5
Example #5
0
def test_stream_initialization():
    graph = Graph()
    # a single packet with a list of ints
    passthru1 = graph.add_component("Pass1", SlowPass, IN=[1, 2, 3],
                                    DELAY=0.1)

    # a stream of int packets
    passthru2 = graph.add_component("Pass2", SlowPass, IN=Stream([1, 2, 3]),
                                    DELAY=0.1)

    assert passthru1.ports.IN._connection._content == [[1, 2, 3]]
    assert passthru2.ports.IN._connection._content == [1, 2, 3]
Example #6
0
def test_required_array_error():
    """if fixed_size is provided and the array port is required, all elements
    must be connected"""
    graph = Graph()
    gen = graph.add_component("Generate", GenerateFixedSizeArray)
    assert gen.ports['OUT'].required is True
    graph.add_component("Discard1", Discard)
    graph.connect("Generate.OUT[0]", "Discard1.IN")
    assert names(gen.outports) == ['OUT[0]', 'OUT[1]']

    gen.init()
    with pytest.raises(FlowError):
        gen.ports.OUT.validate()
Example #7
0
def get_graph(graph_name):
    graph = Graph(name=graph_name)

    gen = graph.add_component('Generate', GenerateTestData)
    gen.metadata['x'] = 5
    gen.metadata['y'] = 5

    passthru = graph.add_component('Pass', Passthru)
    outside = graph.add_component('Outside', Passthru)

    graph.connect('Generate.OUT', 'Pass.IN')
    graph.connect('Outside.OUT', 'Pass.IN')
    graph.initialize(5, 'Generate.COUNT')
    graph.export('Pass.OUT', 'OUTPORT')
    graph.export('Outside.IN', 'INPORT')
    return graph, gen, passthru, outside
Example #8
0
def test_add_component():
    graph = Graph()
    gen = graph.add_component("generate", GenerateTestData, COUNT=10)
    assert type(gen.ports.COUNT) is InputPort
    assert gen.ports.COUNT.is_initialized()
    assert gen.ports.COUNT._connection._content == [10]
    assert type(gen.ports.COUNT._connection._content) is list

    with pytest.raises(FlowError):
        # component already exists
        graph.add_component("generate", GenerateTestData)

    def foo(): pass

    with pytest.raises(TypeError):
        graph.add_component("not_component", foo)
Example #9
0
def test_get_spec():
    sub = Graph()
    sub.add_component('Head', Passthru)
    sub.add_component('Tail', Passthru)

    sub.connect('Head.OUT', 'Tail.IN')

    sub.export('Head.IN', 'IN')
    sub.export('Tail.OUT', 'OUT')

    PassNet = make_subgraph(sub, name='PassNet')
    spec = PassNet.get_spec()

    assert spec['name'] == 'abc/PassNet'
    assert len(spec['inPorts']) == 2
    assert len(spec['outPorts']) == 2
Example #10
0
def test_network_apply_with_outputs():
    graph = Graph()
    graph.add_component('Add1', Add)
    graph.add_component('Add2', Add)
    graph.add_component('Kick', Kick)

    graph.connect('Add1.OUT', 'Add2.IN1')

    graph.export('Add1.IN1', 'IN1')
    graph.export('Add1.IN2', 'IN2')
    graph.export('Add2.IN2', 'IN3')
    graph.export('Add2.OUT', 'OUT')
    graph.export('Kick.OUT', 'Kick_OUT')

    outputs = run_graph(graph, {'IN1': 1, 'IN2': 3, 'IN3': 6}, ['OUT'])

    assert outputs == {'OUT': 10}
Example #11
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)
Example #12
0
def test_network_serialization(serialized_graph):
    graph = Graph()

    counter = graph.add_component('Counter1', Counter)
    counter.metadata.update({
        'x': 20.0,
        'y': 300.5
    })
    graph.add_component('Pass', PassthruNet)
    graph.add_component('Discard1', Discard)
    graph.add_component('Generate', GenerateArray)
    graph.add_component("Merge", Group)
    graph.connect('Counter1.OUT', 'Pass.IN')
    graph.connect('Pass.OUT', 'Discard1.IN')
    graph.connect("Generate.OUT[0]", "Merge.IN[1]")
    graph.connect("Generate.OUT[1]", "Merge.IN[2]")

    graph.initialize(5, "Counter1.IN")

    assert len(graph.get_components().keys()) == 5

    definition = graph.to_dict()

    # Order of connections array shouldn't matter
    definition['connections'] = sorted(definition['connections'], key=str)

    assert definition == serialized_graph
Example #13
0
def test_network_export():
    graph = Graph()
    passthru = graph.add_component("Pass", SlowPass, DELAY=0.1)

    graph.export('Pass.OUT', 'OUT')
    graph.export('Pass.IN', 'IN')

    assert len(graph.inports.keys()) == 1
    assert len(graph.outports.keys()) == 1
Example #14
0
def test_optional_fixed_size_array_error():
    """if an array port specifies fixed_size, all elements must be
    connected if the array port is required"""
    graph = Graph()
    gen = graph.add_component("Generate", GenerateFixedSizeArray)
    assert gen.ports['OUT'].required is True
    gen.init()
    with pytest.raises(FlowError):
        gen.ports.OUT.validate()
Example #15
0
def test_network_apply():
    graph = Graph()
    graph.add_component('Add1', Add)
    graph.add_component('Add2', Add)

    graph.connect('Add1.OUT', 'Add2.IN1')

    graph.export('Add1.IN1', 'IN1')
    graph.export('Add1.IN2', 'IN2')
    graph.export('Add2.IN2', 'IN3')
    graph.export('Add2.OUT', 'OUT')

    outputs = run_graph(graph, {
        'IN1': 1,
        'IN2': 3,
        'IN3': 6
    }, capture_results=True)

    assert outputs['OUT'] == 10
Example #16
0
def test_set_connection_metadata():
    graph = Graph()
    gen = graph.add_component("generate", GenerateTestData, COUNT=10)
    dis = graph.add_component("dis", Discard)
    graph.connect("generate.OUT", "dis.IN", metadata={'route': 4})

    outport = graph.get_component_port(('generate', 'OUT'), kind='out')
    inport = graph.get_component_port(('dis', 'IN'), kind='in')

    metadata = inport._connection.metadata.get(outport)
    assert metadata == {'route': 4}

    graph.set_edge_metadata(outport, inport, metadata={
        'label': 'test',
        'route': None
    })

    metadata = inport._connection.metadata.get(outport)
    assert metadata == {'label': 'test'}
Example #17
0
def test_fixed_array_connections():
    graph = Graph()
    gen = graph.add_component("Generate", GenerateFixedSizeArray)
    dis1 = graph.add_component("Discard1", Discard)
    graph.add_component("Discard2", Discard)

    assert gen.ports['OUT'].get_full_name() == 'Generate.OUT'

    # fixed array ports create their ports immediately
    assert gen.ports.OUT.fixed_size == 2
    assert names(gen.outports) == ['OUT[0]', 'OUT[1]']
    # assert list(gen.ports._ports.keys()) == ['OUT', 'NULL']
    assert type(gen.ports['OUT']) is OutputArray
    assert type(dis1.ports['IN']) is InputPort

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

    # make a connection
    graph.connect("Generate.OUT[1]", "Discard1.IN")
    assert names(gen.outports) == ['OUT[0]', 'OUT[1]']
    assert gen.ports['OUT'][1].is_connected() is True

    # uses first unconnected index (index 0)
    graph.connect("Generate.OUT", "Discard2.IN")
    assert gen.ports['OUT'][0].is_connected() is True

    # outports can only have more than one connection
    graph.connect("Generate.OUT[1]", "Discard2.IN")

    with pytest.raises(FlowError):
        # cannot connect outside the fixed range
        graph.connect("Generate.OUT[2]", "Discard2.IN")

    assert type(gen.ports['OUT']) is OutputArray
    assert type(gen.ports['OUT'][0]) is OutputPort
    assert type(dis1.ports['IN']) is InputPort
    # assert gen.ports['OUT'].is_connected() is False
    assert dis1.ports['IN'].is_connected() is True
Example #18
0
def test_component_with_inheritance():
    @inport('IN')
    @outport('OUT')
    class A(Component):
        def execute(self):
            pass

    @inport('OPT', type=int)
    class B(A):
        pass

    assert names(B.port_definitions().values(), include_null=True) == [
        IN_NULL, 'IN', 'OPT', OUT_NULL, 'OUT']

    graph = Graph()
    b = graph.add_component('b', B)
    assert names(b.ports, include_null=True) == [
        IN_NULL, 'IN', 'OPT', OUT_NULL, 'OUT']
Example #19
0
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'
Example #20
0
def test_export_serialization():
    graph = Graph()

    graph.add_component('Head', SlowPass, DELAY=0.01)
    graph.add_component('Tail', SlowPass, DELAY=0.01)

    graph.connect('Head.OUT', 'Tail.IN')

    graph.export('Head.IN', 'IN')
    graph.export('Tail.OUT', 'OUT')

    definition = graph.to_dict()
    expected = {
        'processes': {
            'Head': {
                'component': 'rill.components.timing/SlowPass',
                'metadata': {}
            },
            'Tail': {
                'component': 'rill.components.timing/SlowPass',
                'metadata': {}
            }
        },
        'connections': [
            {
                'src': {'data': 0.01},
                'tgt': {
                    'process': 'Head',
                    'port': 'DELAY'
                }
            },
            {
                'src': {'data': 0.01},
                'tgt': {
                    'process': 'Tail',
                    'port': 'DELAY'
                }
            },
            {
                'src': {
                    'process': 'Head',
                    'port': 'OUT'
                },
                'tgt': {
                    'process': 'Tail',
                    'port': 'IN'
                }
            }
        ],
        'inports': {
            'IN': {
                'process': 'Head',
                'port': 'IN',
                'metadata': {}
            }
        },
        'outports': {
            'OUT': {
                'process': 'Tail',
                'port': 'OUT',
                'metadata': {}
            }
        }
    }

    # Order of connections array shouldn't matter
    definition['connections'] = sorted(definition['connections'], key=str)
    expected['connections'] = sorted(expected['connections'], key=str)

    assert definition == expected
Example #21
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()

Example #22
0
def test_required_port_error():
    graph = Graph()
    graph.add_component("Generate", GenerateFixedSizeArray)
    graph.add_component("Discard1", Discard)
    with pytest.raises(FlowError):
        graph.validate()