Esempio n. 1
0
def test_ds2_variables_func_input():
    target = [DS2Variable(name='x1', type='double', out=False),
              DS2Variable(name='x2', type='double', out=False)]

    # Only function as input
    with mock.patch('sasctl.utils.pymas.python.parse_type_hints') as mocked:
        mocked.return_value = OrderedDict([('x1', ('double', False)), ('x2', ('double', False))])
        result = ds2_variables(lambda x: x)     # Input function doesn't matter since response is mocked
        assert 1 == mocked.call_count
    assert result == target
Esempio n. 2
0
def test_ds2_variables_numpy_input():
    np = pytest.importorskip('numpy')


    assert [DS2Variable('var1', 'int', False),
            DS2Variable('var2', 'int', False),
            DS2Variable('var3', 'int', False)] == ds2_variables(np.array([1, 2, 3]))

    assert [DS2Variable('var1', 'double', False),
            DS2Variable('var2', 'double', False)] == ds2_variables(np.array([1., 2.]))
Esempio n. 3
0
def test_from_inline():
    """Create a PyMAS instance from an inline Python function."""
    from sasctl.utils.pymas import from_inline

    result = from_inline(dummy_func)
    assert isinstance(result, PyMAS)

    with mock.patch('sasctl.utils.pymas.core.PyMAS', autospec=True) as mocked:
        _ = from_inline(dummy_func)
        assert 1 == mocked.call_count
        call_args = mocked.call_args[0]
        assert [DS2Variable('x1', 'str', False),
                DS2Variable('x2', 'int', False),
                DS2Variable('out1', 'float', True)] == call_args[1]   # Variables

    with mock.patch('sasctl.utils.pymas.core.PyMAS', autospec=True) as mocked:
        _ = from_inline(dummy_func, input_types=int)
        assert 1 == mocked.call_count
        call_args = mocked.call_args[0]
        assert [DS2Variable('x1', 'int', False),
                DS2Variable('x2', 'int', False),
                DS2Variable('result', 'float', True)] == call_args[1]   # Variables

    with mock.patch('sasctl.utils.pymas.core.PyMAS', autospec=True) as mocked:
        _ = from_inline(dummy_func, input_types=OrderedDict([('a', int), ('b', float)]))
        assert 1 == mocked.call_count
        call_args = mocked.call_args[0]
        assert [DS2Variable('a', 'int', False),
                DS2Variable('b', 'double', False),
                DS2Variable('result', 'float', True)] == call_args[1]   # Variables
Esempio n. 4
0
def test_ds2_variables_dict_input():
    target = [
        DS2Variable(name='x1', type='double', out=False),
        DS2Variable(name='x2', type='double', out=False)
    ]

    # Standard input
    result = ds2_variables(
        OrderedDict([('x1', ('double', False)), ('x2', ('double', False))]))
    assert result == target

    # No return value flag
    result = ds2_variables(OrderedDict([('x1', 'double'), ('x2', 'double')]))
    assert result == target

    assert [
        DS2Variable('a', 'int', False),
        DS2Variable('b', 'char', False),
        DS2Variable('c', 'double', False)
    ] == ds2_variables(OrderedDict([('a', int), ('b', str), ('c', float)]))

    assert [DS2Variable('x', 'str', True)] == ds2_variables(OrderedDict(x=str),
                                                            output_vars=True)

    assert [
        DS2Variable('a', 'int', False),
        DS2Variable('b', 'char', False),
        DS2Variable('x', 'double', True)
    ] == ds2_variables(
        OrderedDict([('a', int), ('b', str), ('x', (float, True))]))
Esempio n. 5
0
def test_ds2_variables_pandas_input():
    pd = pytest.importorskip('pandas')

    target = [DS2Variable('a', 'int', False),
              DS2Variable('b', 'char', False),
              DS2Variable('c', 'double', False)]

    df = pd.DataFrame(dict(a=[1,2,3], b=['1', '2', '3'], c=[1., 2., 3.]))
    df = df[['a', 'b', 'c']]    # Ensure columns are ordered correctly

    assert target == ds2_variables(df)
Esempio n. 6
0
def test_build_wrapper_function():
    def func(a, b):
        pass

    # Actual function inputs & DS2 variables current dont have to match.
    result = build_wrapper_function(func, [DS2Variable('a', 'int', False),
                                           DS2Variable('x', 'float', True)],
                                    array_input=False,
                                    return_msg=False)
    assert isinstance(result, str)
    assert '"Output: x"\n' in result
Esempio n. 7
0
def test_ds2_int():
    # Input variable
    var = DS2Variable('myvar', 'int', False)
    assert 'integer' == var.type
    assert False == var.is_array
    assert 'dcl integer myvar;' == var.as_declaration()
    assert 'integer myvar' == var.as_parameter()
    assert "rc = py.setInt('myvar', myvar);" == var.pymas_statement()

    # Output variable
    var = DS2Variable('myvar', 'integer', True)
    assert 'integer' == var.type
    assert False == var.is_array
    assert 'dcl integer myvar;' == var.as_declaration()
    assert 'in_out integer myvar' == var.as_parameter()
    assert "myvar = py.getInt('myvar');" == var.pymas_statement()
Esempio n. 8
0
def test_ds2_char():
    # Input variable
    var = DS2Variable('myvar', 'str', False)
    assert 'char' == var.type
    assert False == var.is_array
    assert 'dcl char myvar;' == var.as_declaration()
    assert 'char myvar' == var.as_parameter()
    assert "rc = py.setString('myvar', myvar);" == var.pymas_statement()

    # Output variable
    var = DS2Variable('myvar', 'string', True)
    assert 'char' == var.type
    assert False == var.is_array
    assert 'dcl char myvar;' == var.as_declaration()
    assert 'in_out char myvar' == var.as_parameter()
    assert "myvar = py.getString('myvar');" == var.pymas_statement()
Esempio n. 9
0
def test_ds2_double():
    # Input variable
    var = DS2Variable('myvar', 'float', False)
    assert 'double' == var.type
    assert False == var.is_array
    assert 'dcl double myvar;' == var.as_declaration()
    assert 'double myvar' == var.as_parameter()
    assert "rc = py.setDouble('myvar', myvar);" == var.pymas_statement()

    # Output variable
    var = DS2Variable('myvar', 'double', True)
    assert 'double' == var.type
    assert False == var.is_array
    assert 'dcl double myvar;' == var.as_declaration()
    assert 'in_out double myvar' == var.as_parameter()
    assert "myvar = py.getDouble('myvar');" == var.pymas_statement()
Esempio n. 10
0
def test_from_pickle_with_func():
    """Create a PyMAS instance from a pickled object."""

    import pickle
    from sasctl.utils.pymas import from_pickle

    data = pickle.dumps(dummy_func)

    with mock.patch('sasctl.utils.pymas.core.PyMAS', autospec=True) as mocked:
        result = from_pickle(data)
        assert 1 == mocked.call_count
        call_args = mocked.call_args[0]
        assert [DS2Variable('x1', 'str', False),
                DS2Variable('x2', 'int', False),
                DS2Variable('out1', 'float', True)] == call_args[1]   # Variables

    assert isinstance(result, PyMAS)
Esempio n. 11
0
def test_ds2_base_method():
    """Test DS2 code generation for a simple DS2 method."""
    from sasctl.utils.pymas.ds2 import DS2BaseMethod, DS2Variable

    # Generate a empty method
    target = """
method testmethod(
    double a,
    double b,
    in_out double c,
    in_out double d
    );

end;
"""
    method = DS2BaseMethod('testmethod',
                           [
                               DS2Variable('a', 'double', False),
                               DS2Variable('b', 'double', False),
                               DS2Variable('c', 'double', True),
                               DS2Variable('d', 'double', True)
                           ])

    result = method.code()
    assert target.lstrip('\n') == result
    assert '\t' not in result


    # Generate a method with an arbitrary body
    target = """
method testmethod(
    double a,
    double b,
    in_out double c,
    in_out double d
    );

    if parrot.is_dead:
        return
end;
"""
    method = DS2BaseMethod('testmethod',
                           [
                               DS2Variable('a', 'double', False),
                               DS2Variable('b', 'double', False),
                               DS2Variable('c', 'double', True),
                               DS2Variable('d', 'double', True)
                           ],
                           [
                               'if parrot.is_dead:',
                               '    return'
                           ])

    result = method.code()
    assert target.lstrip('\n') == result
    assert '\t' not in result
Esempio n. 12
0
def test_wrapper_renamed():
    """Check wrap_predict_method output with custom name."""

    target = """
def renamed_wrapper(a, b):
    "Output: c, msg"
    result = None
    msg = None
    try:
        global _compile_error
        if _compile_error is not None:
            raise _compile_error
        import numpy as np
        import pandas as pd

        if a is None: a = np.nan
        if b is None: b = np.nan
        input_array = np.array([a, b]).reshape((1, -1))
        columns = ["a", "b"]
        input_df = pd.DataFrame(data=input_array, columns=columns)
        result = dummy_func(input_df)
        result = tuple(result.ravel()) if hasattr(result, "ravel") else tuple(result)
        if len(result) == 0:
            result = tuple(None for i in range(1))
        elif "numpy" in str(type(result[0])):
            result = tuple(np.asscalar(i) for i in result)
    except Exception as e:
        from traceback import format_exc
        msg = str(e) + format_exc()
        if result is None:
            result = tuple(None for i in range(1))
    return result + (msg, )
        """.rstrip()

    code = build_wrapper_function(dummy_func, [
        DS2Variable('a', float, False),
        DS2Variable('b', float, False),
        DS2Variable('c', float, True)
    ],
                                  array_input=True,
                                  name='renamed_wrapper')

    assert code == target
Esempio n. 13
0
def test_from_pickle_with_class():
    """Create a PyMAS instance from a pickled object."""

    import pickle
    from sasctl.utils.pymas import from_pickle

    data = pickle.dumps(DummyClass())

    with pytest.raises(ValueError):
        result = from_pickle(data)  # No function specified

    with mock.patch('sasctl.utils.pymas.core.PyMAS', autospec=True) as mocked:
        result = from_pickle(data, 'func')
        assert 1 == mocked.call_count
        call_args = mocked.call_args[0]
        assert [DS2Variable('x1', 'str', False),
                DS2Variable('x2', 'int', False),
                DS2Variable('out1', 'float', True)] == call_args[1]   # Variables

    assert isinstance(result, PyMAS)
Esempio n. 14
0
def test_ds2_package():
    """Test code generation for a package with PyMAS."""
    from sasctl.utils.pymas.ds2 import DS2Package, DS2Variable

    target = """
package _pyscore / overwrite=yes;
    dcl package pymas py;
    dcl package logger logr('App.tk.MAS');
    dcl varchar(67108864) character set utf8 pycode;
    dcl int revision;

    method score(
        double a,
        double b,
        in_out double c,
        in_out double d,
        in_out integer rc
        );
    
        if null(py) then do;
            py = _new_ pymas();
            rc = py.useModule('pyscore', 1);
            if rc then do;
                rc = py.appendSrcLine('def domath(a, b):');
                rc = py.appendSrcLine('    "Output: c, d"');
                rc = py.appendSrcLine('    c = a * b');
                rc = py.appendSrcLine('    d = a / b');
                rc = py.appendSrcLine('    return c, d');
                pycode = py.getSource();
                revision = py.publish(pycode, 'pyscore');
                if revision lt 1 then do;
                    logr.log('e', 'py.publish() failed.');
                    rc = -1;
                    return;
                end;
            end;
            rc = py.useMethod('domath');
            if rc then return;
        end;
        rc = py.setDouble('a', a);    if rc then return;
        rc = py.setDouble('b', b);    if rc then return;
        rc = py.execute();    if rc then return;
        c = py.getDouble('c');
        d = py.getDouble('d');
    end;
    
endpackage;
"""

    source = """
def domath(a, b):
    "Output: c, d"
    c = a * b
    d = a / b
    return c, d
"""

    with mock.patch('uuid.uuid4') as mocked:
        mocked.return_value.hex.upper.return_value = 'pyscore'
        package = DS2Package(
            [
                DS2Variable('a', 'double', False),
                DS2Variable('b', 'double', False),
                DS2Variable('c', 'double', True),
                DS2Variable('d', 'double', True),
            ],
            source.strip('\n'),
            target='domath',
            return_message=False)

    result = package.code()
    assert target.lstrip('\n') == result
    assert '\t' not in result
Esempio n. 15
0
def test_ds2_pymas_method():
    """Test DS2 code generation for a method that uses PyMAS."""
    from sasctl.utils.pymas.ds2 import DS2PyMASMethod, DS2Variable

    source = """
def domath(a, b):
    "Output: c, d"
    c = a * b
    d = a / b
    return c, d
"""

    target = """
method score(
    double a,
    double b,
    in_out double c,
    in_out double d,
    in_out integer rc
    );

    if null(py) then do;
        py = _new_ pymas();
        rc = py.useModule('mypymodule', 1);
        if rc then do;
            rc = py.appendSrcLine('def domath(a, b):');
            rc = py.appendSrcLine('    "Output: c, d"');
            rc = py.appendSrcLine('    c = a * b');
            rc = py.appendSrcLine('    d = a / b');
            rc = py.appendSrcLine('    return c, d');
            pycode = py.getSource();
            revision = py.publish(pycode, 'mypymodule');
            if revision lt 1 then do;
                logr.log('e', 'py.publish() failed.');
                rc = -1;
                return;
            end;
        end;
        rc = py.useMethod('domath');
        if rc then return;
    end;
    rc = py.setDouble('a', a);    if rc then return;
    rc = py.setDouble('b', b);    if rc then return;
    rc = py.execute();    if rc then return;
    c = py.getDouble('c');
    d = py.getDouble('d');
end;
"""
    method = DS2PyMASMethod('mypymodule',[
        DS2Variable('a', 'double', False),
        DS2Variable('b', 'double', False),
        DS2Variable('c', 'double', True),
        DS2Variable('d', 'double', True)
    ],
        source.strip('\n'),
        return_code=True,
        return_message=False,
        target='domath')

    result = method.code()
    assert target.lstrip('\n') == result
    assert '\t' not in result