def test_default_arg_inserted():
    default_arg_inserted = textwrap.dedent("""\
    name: example
    import: [stdlib]
    body:
    - typedef:
        params: [edge1=default, open_teq, closed_teq]
        name: valve
        edges:
          edge1:
            nodes: [0, 1]
        states:
          open:
            edge1: open_teq
          closed:
            edge1: closed_teq
    - component:
        name: vent_valve
        type: valve
        params:
          open_teq: 1
          closed_teq: closed
    """)

    pack = top.Package([top.File(default_arg_inserted, 's')])
    assert 'default' in pack.component_dict['example'][0]['edges']
def test_invalid_graph_missing_states():
    missing_states = textwrap.dedent("""\
    name: example
    import: [stdlib]
    body:
    - component:
        name: fill_valve
        edges:
          edge1:
            nodes: [0, 1]
        states:
          open:
            edge1: 6
          closed:
            edge1: closed
    - graph:
        name: main
        nodes:
          A:
            fixed_pressure: 500
            components:
              - [fill_valve, 0]

          B:
            components:
              - [fill_valve, 1]
    """)
    missing_states_file = top.File(missing_states, 's')
    with pytest.raises(exceptions.BadInputError) as err:
        top.Package([missing_states_file])
    assert "missing component" in str(err)
def test_files_unchanged():
    file = top.File(utils.example_path)

    top.Package([file])

    assert len(file.typedefs) == 2
    assert len(file.components) == 6
    assert len(file.graphs) == 2
def test_package_shortcuts():
    file = top.File(utils.example_path)
    namespace = file.namespace

    pack = top.Package([file])
    for component in pack.component_dict[namespace]:
        assert 'states' in component
        for edges in component['states'].values():
            for teq in edges.values():
                assert 'fwd' in teq and 'back' in teq
def test_invalid_nested_import():
    nested_import = textwrap.dedent("""\
    name: example
    import: [stdlib]
    body:
    - component:
        name: vent_valve
        type: stdlib.NEST.hole
        params:
          edge_name: fav_edge
          open_teq: 5
    """)
    nested_import_file = top.File(nested_import, input_type='s')
    with pytest.raises(NotImplementedError) as err:
        top.Package([nested_import_file])
    assert "nested imports" in str(err)
def test_package_storage():
    file = top.File(utils.example_path)

    pack = top.Package([file])

    namespace = file.namespace
    assert len(pack.typedefs) == 2
    assert 'example' in pack.typedefs and 'stdlib' in pack.typedefs

    assert len(pack.component_dict[namespace]) == 6
    assert len(pack.component_dict['stdlib']) == 0
    assert len(pack.components()) == 6

    assert len(pack.typedefs[namespace]) == 2
    assert len(pack.typedefs['stdlib']) == 1

    assert len(pack.graph_dict[namespace]) == 2
    assert len(pack.graph_dict['stdlib']) == 0
    assert len(pack.graphs()) == 2
    def __init__(self, files, input_type='f', import_paths=None):
        """
        Initialize a parser from one or more PDL files.

        A Parser contains a Package; most of its functionality lies in restructuring the data
        contained in its Package into output suitable for loading a plumbing engine.

        Parameters
        ----------

        files: iterable
            files is the iterable (usually a list) of one or more paths of the PDL files we
            want parsed. Alternatively, it can also be a list of strings that are each a valid
            PDL file. Alternatively, a single string or file path is also acceptable.

        input_type: char
            input_type indicates whether the argument provided to "files" is
            a list of file paths (f) or a list of strings (s).

        """
        self.import_paths = copy.deepcopy(import_paths)
        if import_paths is None:
            self.import_paths = utils.default_paths

        file_list = []

        # if a single element, put into list for processing
        if isinstance(files, str):
            files = [files]

        for file in files:
            file_list.append(top.File(file, input_type))
        self.package = top.Package(file_list, self.import_paths)

        self.components = {}
        self.mapping = {}
        self.initial_pressures = {}
        self.initial_states = {}

        self.parse_components()
        self.parse_graphs()
def test_invalid_bad_import_type():
    # typedef not found errors having to do with imported files will only be caught at the package
    # level, not at the file one. We can look at changing this if we change the implementation of
    # how importable files are stored.
    bad_type = "NONEXISTENT_TYPE"
    bad_imported_type = textwrap.dedent(f"""\
    name: example
    import: [stdlib]
    body:
    - component:
        name: vent_valve
        type: stdlib.{bad_type}
        params:
          edge_name: fav_edge
          open_teq: 5
          closed_teq: closed
    """)
    bad_imported_type_file = top.File(bad_imported_type, input_type='s')
    with pytest.raises(exceptions.BadInputError) as err:
        top.Package([bad_imported_type_file])
    assert "invalid component" in str(err)
def test_invalid_import():
    bad_import = "NONEXISTENT"
    invalid_import = textwrap.dedent(f"""\
    name: example
    import: [stdlib, {bad_import}]
    body:
    - typedef:
        params: [edge1, open_teq, closed_teq]
        name: valve
        edges:
          edge1:
            nodes: [0, 1]
        states:
          open:
            edge1: open_teq
          closed:
            edge1: closed_teq
    """)
    invalid_import_file = top.File(invalid_import, input_type='s')
    with pytest.raises(exceptions.BadInputError) as err:
        top.Package([invalid_import_file])
    assert "invalid import" in str(err)
def test_package_typedefs():
    file = top.File(utils.example_path)
    namespace = file.namespace

    pack = top.Package([file])

    var_open = 'open_teq'
    var_closed = 'closed_teq'
    var_name = 'edge_name'

    for component in pack.component_dict[namespace]:
        # ensure typedef fulfillment occurred
        assert 'type' not in component and 'params' not in component
        assert 'edges' in component

        # ensure variables were replaced
        if component['name'] == 'vent_valve':
            assert var_name not in list(component['edges'].keys())
            assert var_open not in component['states']['open']
            assert var_closed not in component['states']['closed']

        if component['name'] == 'hole':
            assert var_name not in list(component['edges'].keys())
            assert var_open not in component['states']['open']
def test_duplicate_names():
    file_1 = textwrap.dedent("""\
    name: name1
    body:
    - component:
        name: fill_valve
        edges:
          edge1:
            nodes: [0, 1]
        states:
          open:
            edge1: 6
          closed:
            edge1: closed
    """)

    file_2 = textwrap.dedent("""\
    name: name2
    body:
    - component:
        name: fill_valve
        edges:
          edge1:
            nodes: [0, 1]
        states:
          open:
            edge1: 6
          closed:
            edge1: closed
    """)
    duplicate_pack = top.Package(
        [top.File(file_1, 's'), top.File(file_2, 's')])
    assert duplicate_pack.component_dict["name1"][0][
        'name'] == "name1.fill_valve"
    assert duplicate_pack.component_dict["name2"][0][
        'name'] == "name2.fill_valve"
def test_import_modification():
    file = top.File(utils.example_path)

    pack = top.Package([file])

    assert len(pack.importable_files) != 0
def test_invalid_empty_package():
    with pytest.raises(exceptions.BadInputError) as err:
        top.Package([])
    assert "no Files" in str(err)