Esempio n. 1
0
def test_sub_graph_with_arg_input():
    graph0 = Graph()
    graph0_0 = Graph()

    with pytest.raises(PyungoError) as err:
        graph0.add_node(graph0_0,
                        args=['inp1_1', 'inp1_2'],
                        outputs=['inp2_1'])

    assert "Node with Graph can only accept kwargs input. However, get args = ['inp1_1', 'inp1_2']" in str(
        err.value)
Esempio n. 2
0
def test_sub_graph():
    def f_my_function1(inp1_1, inp1_2):
        return inp1_1 + inp1_2

    def f_my_function2(inp2_1):
        return inp2_1 / 10.

    def f_my_function3(inp3_1, inp3_2):
        return inp3_1 - inp3_2

    graph0 = Graph()
    graph0_0 = Graph()
    graph0_1 = Graph()
    graph0_1_0 = Graph()

    # inp2_1 = 1.5, inp3_2 = 0.15, out=0.1785
    graph0.add_node(graph0_0, kwargs=['inp1_1', 'inp1_2'], outputs=['inp2_1'])
    graph0.add_node(f_my_function2, inputs=['inp2_1'], outputs=['inp3_2'])
    graph0.add_node(graph0_1,
                    kwargs=[('inp1', 'inp1_1'), ('inp2', 'inp3_2')],
                    outputs=['out'])

    graph0_0.add_node(f_my_function1,
                      inputs=['inp1_1', 'inp1_2'],
                      outputs=['inp2_1'])
    graph0_0.add_node(f_my_function2, inputs=['inp2_1'], outputs=['inp3_2'])
    graph0_0.add_node(f_my_function3,
                      inputs=[('inp3_1', 'inp1_1'), 'inp3_2'],
                      outputs=['out'])

    # inp2_1 = 0.215, inp3_2 = 0.0215, out = 0.1785
    graph0_1_0.add_node(f_my_function1,
                        inputs=['inp1_1', 'inp1_2'],
                        outputs=['inp2_1'])
    graph0_1_0.add_node(f_my_function2, inputs=['inp2_1'], outputs=['inp3_2'])
    graph0_1_0.add_node(f_my_function3,
                        inputs=[('inp3_1', 'inp1_1'), 'inp3_2'],
                        outputs=['out'])

    # out1 = 0.2, out2 = 0.015, out=0.1785
    graph0_1.add_node(f_my_function2, inputs=['inp1'], outputs=['out1'])
    graph0_1.add_node(f_my_function2, inputs=['inp2'], outputs=['out2'])
    graph0_1.add_node(graph0_1_0,
                      kwargs=[('inp1_1', 'out1'), ('inp1_2', 'out2')],
                      outputs=['out3'])

    for _ in range(2):
        res = graph0(inp1_1=2, inp1_2=3)
        assert 0.1785 == pytest.approx(res)
        assert graph0.data['out'] == res
        assert graph0_0.data['out'] == 1.5
        assert graph0_1.data['out3'] == pytest.approx(0.1785)
        assert graph0_1_0.data['out'] == pytest.approx(0.1785)
Esempio n. 3
0
def test_schema():
    from jsonschema import ValidationError

    schema = {
        "type": "object",
        "properties": {
            "a": {
                "type": "number"
            },
            "b": {
                "type": "number"
            }
        }
    }

    graph = Graph(schema=schema)

    @graph.register(inputs=['a', 'b'], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    with pytest.raises(ValidationError) as err:
        graph.calculate(data={'a': 1, 'b': '2'})

    msg = "'2' is not of type 'number'"
    assert msg in str(err.value)

    res = graph.calculate(data={'a': 1, 'b': 2})
    assert res == 3
Esempio n. 4
0
def test_not_slim_graph():
    import numpy as np
    graph = Graph(slim=False)

    @graph.register(inputs=['a', 'b'], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    @graph.register(inputs=['d', 'a'], outputs=['e'])
    def f_my_function3(d, a):
        return d - a

    @graph.register(inputs=['c'], outputs=['d'])
    def f_my_function2(c):
        return c / 10.

    for _ in range(2):
        data = {'a': np.ones((2, 2)) * 2., 'b': np.ones((2, 2)) * 3.}
        res = graph.calculate(data)
        assert (res == np.ones((2, 2)) * -1.5).all()
        assert (graph.data['e'] == np.ones((2, 2)) * -1.5).all()
        assert id(graph.ordered_nodes[0]._outputs[0].value) != id(
            graph.ordered_nodes[1]._inputs[0].value)
        assert id(graph.ordered_nodes[1]._outputs[0].value) != id(
            graph.ordered_nodes[2]._inputs[0].value)
        assert id(data['a']) != id(graph.ordered_nodes[0]._inputs[0].value)
        assert id(data['b']) != id(graph.ordered_nodes[0]._inputs[1].value)
Esempio n. 5
0
def test_build_with_map_feed_with_name():
    graph = Graph()

    @graph.register(inputs=[('foo', 'a')],
                    kwargs=[('inp1_2', 'b')],
                    outputs=['c'])
    def f_my_function1(inp1_1, inp1_2):
        return inp1_1 + inp1_2

    @graph.register(args=[Input(name='foo', map='d')],
                    kwargs=[Input(name='inp3_2', map='a')],
                    outputs=['e'])
    def f_my_function3(inp3_1, inp3_2):
        return inp3_1 - inp3_2

    @graph.register(inputs=[('foo', 'c')], outputs=['d'])
    def f_my_function2(inp2_1):
        return inp2_1 / 10.

    res = graph.calculate(data={'a': 2, 'b': 3})
    assert res == -1.5
    assert graph.data['e'] == -1.5

    # make sure it is independent
    res = graph.calculate(data={'a': 2, 'b': 3})
    assert res == -1.5
    assert graph.data['e'] == -1.5
Esempio n. 6
0
def test_passing_data_to_node_definition():
    graph = Graph()

    @graph.register(inputs=['a', {'b': 2}], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    res = graph.calculate(data={'a': 5})
    assert res == 7
Esempio n. 7
0
def test_opt_inputs_wont_cause_redundant_input():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], outputs=['c'])
    def f_my_function(a, b=2):
        return a + b

    res = graph.calculate(data={'a': 6})
    assert res == 8
Esempio n. 8
0
def test_input_type_tuple():
    graph = Graph()

    @graph.register(inputs=[('inp_1', 'a'), ('b', 'b')], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    res = graph.calculate(data={'a': 2, 'b': 3})

    assert res == 5
Esempio n. 9
0
def test_args_kwargs():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], args=['c'], kwargs=['d'], outputs=['e'])
    def f_my_function(a, b, *args, **kwargs):
        return a + b + args[0] + kwargs['d']

    res = graph.calculate(data={'a': 2, 'b': 3, 'c': 4, 'd': 5})

    assert res == 14
    assert graph.data['e'] == 14
Esempio n. 10
0
def test_not_str_name():
    graph = Graph()

    with pytest.raises(PyungoError) as err:

        @graph.register(inputs=[(23, 'a')], outputs=['c'])
        def f_my_function(a, b):
            return a + b

    assert "IO name must be str, however get name = 23 with type <class 'int'>" in str(
        err.value)
Esempio n. 11
0
def test_not_str_map():
    graph = Graph()

    with pytest.raises(PyungoError) as err:

        @graph.register(inputs=[Input('a', map=23)], outputs=['c'])
        def f_my_function(a, b):
            return a + b

    assert "IO map must be str, however get map = 23 with type <class 'int'>" in str(
        err.value)
Esempio n. 12
0
def test_optional_inputs_feed_by_input():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], kwargs=['c'], outputs=['d'])
    def f(a, b=2, c=3):
        return a + b + c

    res = graph.calculate(data={'a': 1, 'b': -1, 'c': -2})

    assert res == -2
    assert graph.data['d'] == -2
Esempio n. 13
0
def test_multiple_keys_input_dict():
    graph = Graph()

    with pytest.raises(PyungoError) as err:

        @graph.register(inputs=['a', {'b': 1, 'c': 2}], outputs=['c'])
        def f_my_function(a, b):
            return a + b

    assert "dict inputs should have only one key and cannot be empty" in str(
        err.value)
Esempio n. 14
0
def test_wrong_input_type():
    graph = Graph()

    with pytest.raises(PyungoError) as err:

        @graph.register(inputs=['a', {'b'}], outputs=['c'])
        def f_my_function(a, b):
            return a + b

    assert "inputs need to be of type tuple, Input, str or dict" in str(
        err.value)
Esempio n. 15
0
def test_missing_kwargs():
    graph = Graph()

    @graph.register(inputs=['a'], kwargs=['b'], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    with pytest.raises(PyungoError) as err:
        graph.calculate(data={'a': 6})

    assert "The following inputs are needed: ['b']" in str(err.value)
Esempio n. 16
0
def test_optional_inputs_without_feed():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], kwargs=['c'], outputs=['d'])
    def f(a, b=2, c=3):
        return a + b + c

    res = graph.calculate(data={'a': 1})

    assert res == 6
    assert graph.data['d'] == 6
Esempio n. 17
0
def test_iterable_on_single_output():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], outputs=['c'])
    def f_my_function(a, b):
        return list(range(a)) + [b]

    res = graph.calculate(data={'a': 2, 'b': 3})

    assert res == [0, 1, 3]
    assert graph.data['c'] == [0, 1, 3]
Esempio n. 18
0
def test_input_tuple_too_long():
    graph = Graph()

    with pytest.raises(PyungoError) as err:

        @graph.register(inputs=[('a', 'input', 'too_long'), 'b'],
                        outputs=['c'])
        def f_my_function(a, b):
            return a + b

    assert "Tuple input should like (name, map). However, get ('a', 'input', 'too_long')" in str(
        err.value)
Esempio n. 19
0
def test_Input_type_input():
    graph = Graph()

    @graph.register(inputs=[Input(name='a'),
                            Input(name='inp_1_1', map='b')],
                    outputs=['c'])
    def f_my_function(a, b):
        return a + b

    res = graph.calculate(data={'a': 2, 'b': 3})

    assert res == 5
Esempio n. 20
0
def test_inputs_not_used_with_constant():
    graph = Graph()

    @graph.register(inputs=[{'a': 1}, 'b'], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    with pytest.raises(PyungoError) as err:
        graph.calculate(data={'a': 6, 'b': 4})

    assert "The following inputs are not used by the model: ['a']" in str(
        err.value)
Esempio n. 21
0
def test_map():
    graph = Graph()

    @graph.register(inputs=[Input('a', map='q'),
                            Input('b', map='w')],
                    outputs=[Output('c', map='e')])
    def f_my_function(a, b):
        return a + b

    res = graph.calculate(data={'q': 2, 'w': 3})
    assert res == 5
    assert graph.data['e'] == 5
Esempio n. 22
0
def test_inputs_collision():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], outputs=['c'])
    def f_my_function(a, b):
        return a + b

    with pytest.raises(PyungoError) as err:
        graph.calculate(data={'a': 6, 'b': 4, 'c': 7})

    assert "The following inputs are already used in the model: ['c']" in str(
        err.value)
Esempio n. 23
0
def test_no_explicit_inputs_outputs_bad_return():
    graph = Graph()

    with pytest.raises(PyungoError) as err:

        @graph.register()
        def f(a, b):
            return a + b

    expected = ('Variable name or Tuple of variable '
                'names are expected, got BinOp')
    assert str(err.value) == expected
Esempio n. 24
0
def test_no_explicit_inputs_outputs_simple():
    graph = Graph()

    @graph.register()
    def f(a, b):
        c = a + b
        return c

    res = graph.calculate(data={'a': 1, 'b': 2})

    assert res == 3
    assert graph.data['c'] == 3
Esempio n. 25
0
def test_find_default_by_name_not_map():
    graph = Graph()

    @graph.register(inputs=['a', ('inp2', 'b')],
                    kwargs=[('inp3', 'c')],
                    outputs=['d'])
    def f(inp1, inp2=2, inp3=3):
        return inp1 + inp2 + inp3

    res = graph.calculate(data={'a': 1})

    assert res == 6
    assert graph.data['d'] == 6
Esempio n. 26
0
def test_no_explicit_inputs_outputs_tuple():
    graph = Graph()

    @graph.register()
    def f(a, b, c, d):
        e = a + b
        f = c - d
        return e, f

    res = graph.calculate(data={'a': 1, 'b': 2, 'c': 3, 'd': 4})

    assert res == (3, -1)
    assert graph.data['e'] == 3
    assert graph.data['f'] == -1
Esempio n. 27
0
def test_simple_parallel():
    """ TODO: We could mock and make sure things are called correctly """

    graph = Graph(pool_size=2)

    graph.add_node(par_f_my_function, inputs=['a', 'b'], outputs=['c'])
    graph.add_node(par_f_my_function3, inputs=['d', 'a'], outputs=['e'])
    graph.add_node(par_f_my_function2, inputs=['c'], outputs=['d'])
    graph.add_node(par_f_my_function2, inputs=['c'], outputs=['f'])
    graph.add_node(par_f_my_function2, inputs=['c'], outputs=['g'])

    res = graph.calculate(data={'a': 2, 'b': 3})

    assert res == -1.5
Esempio n. 28
0
def test_multiple_outputs_with_iterable():
    graph = Graph()

    @graph.register(inputs=['a', 'b'], outputs=['c', 'd'])
    def f_my_function(a, b):
        return list(range(a)) + [b], b * 10

    res = graph.calculate(data={'a': 2, 'b': 3})

    assert isinstance(res, tuple) is True
    assert graph.data['c'] == [0, 1, 3]
    assert graph.data['d'] == 30
    assert res[0] == [0, 1, 3]
    assert res[1] == 30
Esempio n. 29
0
def test_diff_input_function_arg_name():
    graph = Graph()

    @graph.register(inputs=['a_diff', 'b_diff'],
                    args=['c_diff'],
                    kwargs=['d'],
                    outputs=['e_diff'])
    def f_my_function(a, b, *args, **kwargs):
        return a + b + args[0] + kwargs['d']

    res = graph.calculate(data={'a_diff': 2, 'b_diff': 3, 'c_diff': 4, 'd': 5})

    assert res == 14
    assert graph.data['e_diff'] == 14
Esempio n. 30
0
def test_contract_outputs():
    from contracts import ContractNotRespected
    graph = Graph()

    @graph.register(inputs=['a', 'b'],
                    outputs=[Output('c', contract='int,>0')])
    def f_my_function(a, b):
        return a + b

    res = graph.calculate(data={'a': 2, 'b': 3})
    assert res == 5
    with pytest.raises(ContractNotRespected) as err:
        res = graph.calculate(data={'a': -4, 'b': 3})
    assert "Condition -1 > 0 not respected" in str(err.value)