From 09fbea2aaaab1b148df30915e73874bf9fb42ae7 Mon Sep 17 00:00:00 2001 From: Nicholas Long <1907354+nllong@users.noreply.github.com> Date: Mon, 14 Aug 2023 16:28:53 -0600 Subject: [PATCH] Use `filNam` parameter for TEASER loads and add within parsing to PackageParser (#574) * use filNam for teaser loads * fix types * remove unused exists method --- .cspell/custom-dictionary-workspace.txt | 6 ++ .gitignore | 8 +- .pre-commit-config.yaml | 6 +- .../cooling_indirect.py | 2 +- .../heating_indirect.py | 2 +- .../model_connectors/load_connectors/spawn.py | 2 +- .../load_connectors/teaser.py | 40 ++++----- .../load_connectors/time_series.py | 4 +- .../time_series_mft_ets_coupling.py | 2 +- .../model_connectors/model_base.py | 4 +- .../model_connectors/plants/borefield.py | 2 +- .../model_connectors/plants/chp.py | 2 +- .../model_connectors/plants/cooling_plant.py | 2 +- .../modelica/package_parser.py | 88 ++++++++++++++++++- poetry.lock | 56 ++++++------ pyproject.toml | 3 +- tests/modelica/test_package_parser.py | 26 +++++- 17 files changed, 182 insertions(+), 73 deletions(-) diff --git a/.cspell/custom-dictionary-workspace.txt b/.cspell/custom-dictionary-workspace.txt index 13ea53e81..da5637b4a 100644 --- a/.cspell/custom-dictionary-workspace.txt +++ b/.cspell/custom-dictionary-workspace.txt @@ -1,5 +1,11 @@ # Custom Dictionary Words +autoload +Combi +linecount mfrt +mofile Reparse +setpoint timeseries timestep +urbanopt diff --git a/.gitignore b/.gitignore index 37b5dea67..d74f15906 100644 --- a/.gitignore +++ b/.gitignore @@ -104,8 +104,12 @@ tests/output tests/*/microgrid_output tests/output_ets tests/*/output +tests/modelica/data/packages/*/*.mat +tests/modelica/data/packages/*/*.txt +tests/modelica/data/packages/*/*.c +tests/modelica/data/packages/*/dymosim tests/management/data/sdk_project_scraps/run/baseline_scenario/system_parameter.json -/geojson_modelica_translator/modelica/buildingslibrary/ +geojson_modelica_translator/modelica/buildingslibrary/ not/a/real/** # TODO: this file shoud not be writtent out, but it is... fix this eventually -/geojson_modelica_translator/modelica/ets_cooling_indirect_templated.mo +geojson_modelica_translator/modelica/ets_cooling_indirect_templated.mo diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0dbba5c5d..3a85a6c34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: - id: pretty-format-json args: ['--autofix', '--no-sort-keys'] - repo: https://github.com/pre-commit/mirrors-autopep8 - rev: v2.0.1 + rev: v2.0.2 hooks: - id: autopep8 args: @@ -37,7 +37,7 @@ repos: "--ignore=E501,E402,W503,W504,E731" ] - repo: https://github.com/PyCQA/autoflake - rev: v2.0.0 + rev: v2.2.0 hooks: - id: autoflake args: @@ -49,7 +49,7 @@ repos: "--ignore-init-module-imports" ] - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 args: ["--ignore=E501,E402,W503,W504,E731,F401"] diff --git a/geojson_modelica_translator/model_connectors/energy_transfer_systems/cooling_indirect.py b/geojson_modelica_translator/model_connectors/energy_transfer_systems/cooling_indirect.py index 3bbe2910b..c0de4b51c 100644 --- a/geojson_modelica_translator/model_connectors/energy_transfer_systems/cooling_indirect.py +++ b/geojson_modelica_translator/model_connectors/energy_transfer_systems/cooling_indirect.py @@ -67,4 +67,4 @@ def to_modelica(self, scaffold): ets_package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Substations.{self._model_filename}' + return f'Substations.{self._model_filename}' diff --git a/geojson_modelica_translator/model_connectors/energy_transfer_systems/heating_indirect.py b/geojson_modelica_translator/model_connectors/energy_transfer_systems/heating_indirect.py index f41aab359..e4b53ac48 100644 --- a/geojson_modelica_translator/model_connectors/energy_transfer_systems/heating_indirect.py +++ b/geojson_modelica_translator/model_connectors/energy_transfer_systems/heating_indirect.py @@ -67,4 +67,4 @@ def to_modelica(self, scaffold): ets_package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Substations.{self._model_filename}' + return f'Substations.{self._model_filename}' diff --git a/geojson_modelica_translator/model_connectors/load_connectors/spawn.py b/geojson_modelica_translator/model_connectors/load_connectors/spawn.py index 91889fec1..777f10d9c 100644 --- a/geojson_modelica_translator/model_connectors/load_connectors/spawn.py +++ b/geojson_modelica_translator/model_connectors/load_connectors/spawn.py @@ -241,4 +241,4 @@ def post_process(self, scaffold, keep_original_models=False): package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Loads.{self.building_name}.building' + return f'Loads.{self.building_name}.building' diff --git a/geojson_modelica_translator/model_connectors/load_connectors/teaser.py b/geojson_modelica_translator/model_connectors/load_connectors/teaser.py index 44af9328e..1322bd4b7 100644 --- a/geojson_modelica_translator/model_connectors/load_connectors/teaser.py +++ b/geojson_modelica_translator/model_connectors/load_connectors/teaser.py @@ -122,7 +122,7 @@ def to_modelica(self, scaffold, keep_original_models=False): def fix_gains_file(self, f): """Temporary hack to fix the gains files in TEASER. This method does the following: * makes the dimension of the matrix to 8761,4 - * addes in a timestep for t=0 + * adds in a timestep for t=0 :param f: string, fully qualified path to file :return: None @@ -171,7 +171,6 @@ def post_process(self, scaffold, keep_original_models=False): # This for loop does *a lot* of work to make the models compatible for the project structure. # Need to investigate moving this into a more testable location. # create a list of strings that we need to replace in all the file as we go along - string_replace_list = [] mos_weather_filename = self.system_parameters.get_param("$.weather") # create a new modelica based path for the buildings # TODO: make this work at the toplevel, somehow. b_modelica_path = ModelicaPath(self.building_name, scaffold.loads_path.files_dir, True) @@ -196,13 +195,7 @@ def post_process(self, scaffold, keep_original_models=False): # internal gain files. The next method can be removed once the TEASER development branch is # merged into master/main and released. self.fix_gains_file(f"{b_modelica_path.resources_dir}/{new_file_name}") - - string_replace_list.append( - ( - f"Project/{self.building_name}/{self.building_name}_Models/{os.path.basename(f)}", - f"{scaffold.project_name}/Loads/{b_modelica_path.resources_relative_dir}/{new_file_name}", - ) - ) + self.internal_gains_file = f"{scaffold.project_name}/Loads/{b_modelica_path.resources_relative_dir}/{new_file_name}" # process each of the thermal zones thermal_zone_files = [] @@ -228,19 +221,13 @@ def post_process(self, scaffold, keep_original_models=False): mofile.remove_component_argument("Buildings.BoundaryConditions.SolarIrradiation.DirectTiltedSurface", "HDirTilRoof", "lat") # updating path to internal loads - for s in string_replace_list: - new_file_path = s[1] - new_resource_arg = f'''Modelica.Utilities.Files.loadResource("modelica://{new_file_path}")''' - old_file_path = s[0] - old_resource_arg = f'''Modelica.Utilities.Files.loadResource("modelica://{old_file_path}")''' - - mofile.update_component_modification( - "Modelica.Blocks.Sources.CombiTimeTable", - "internalGains", - "fileName", - new_resource_arg, - if_value=old_resource_arg - ) + + mofile.update_component_modification( + "Modelica.Blocks.Sources.CombiTimeTable", + "internalGains", + "fileName", + "Modelica.Utilities.Files.loadResource(filNam)" + ) # add heat port convective heat flow. mofile.insert_component( @@ -306,6 +293,13 @@ def post_process(self, scaffold, keep_original_models=False): string_comment='Number of fluid ports.', annotations=['connectorSizing=true'] ) + # Add a parameter to put the load filename at the top of the model + mofile.add_parameter( + 'String', 'filNam', + assigned_value=f'"modelica://{self.internal_gains_file}"', + string_comment='modelica path to the internal gains file used in the model CombiTimeTable' + ) + # Set the fraction latent person in the template by simply replacing the value mofile.insert_component( 'Modelica.Blocks.Sources.RealExpression', 'perLatLoa', @@ -634,4 +628,4 @@ def post_process(self, scaffold, keep_original_models=False): package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Loads.{self.building_name}.building' + return f'Loads.{self.building_name}.building' diff --git a/geojson_modelica_translator/model_connectors/load_connectors/time_series.py b/geojson_modelica_translator/model_connectors/load_connectors/time_series.py index e721a98ea..10948712a 100644 --- a/geojson_modelica_translator/model_connectors/load_connectors/time_series.py +++ b/geojson_modelica_translator/model_connectors/load_connectors/time_series.py @@ -181,6 +181,6 @@ def post_process(self, scaffold): def get_modelica_type(self, scaffold): district_params = self.system_parameters.get_param("district_system") if 'fifth_generation' not in district_params: - return f'{scaffold.project_name}.Loads.{self.building_name}.TimeSeriesBuilding' + return f'Loads.{self.building_name}.TimeSeriesBuilding' else: - return f'{scaffold.project_name}.Loads.{self.building_name}.building' + return f'Loads.{self.building_name}.building' diff --git a/geojson_modelica_translator/model_connectors/load_connectors/time_series_mft_ets_coupling.py b/geojson_modelica_translator/model_connectors/load_connectors/time_series_mft_ets_coupling.py index 3797fc310..22dff87db 100644 --- a/geojson_modelica_translator/model_connectors/load_connectors/time_series_mft_ets_coupling.py +++ b/geojson_modelica_translator/model_connectors/load_connectors/time_series_mft_ets_coupling.py @@ -148,4 +148,4 @@ def post_process(self, scaffold): pp.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Loads.{self.building_name}.building' + return f'Loads.{self.building_name}.building' diff --git a/geojson_modelica_translator/model_connectors/model_base.py b/geojson_modelica_translator/model_connectors/model_base.py index 468b0c51e..f20906d38 100644 --- a/geojson_modelica_translator/model_connectors/model_base.py +++ b/geojson_modelica_translator/model_connectors/model_base.py @@ -165,8 +165,8 @@ def to_dict(self, scaffold): output_dict['is_5g_district'] = '' return output_dict - # TODO: this should be implemented here, not in individual classes + # This method needs to be defined in each of the derived model connectors # def get_modelica_type(self, scaffold) - # These methods need to be defined in each of the derived model connectors + # This method needs to be defined in each of the derived model connectors # def to_modelica(self): diff --git a/geojson_modelica_translator/model_connectors/plants/borefield.py b/geojson_modelica_translator/model_connectors/plants/borefield.py index 7e2ea0614..50d1424a7 100644 --- a/geojson_modelica_translator/model_connectors/plants/borefield.py +++ b/geojson_modelica_translator/model_connectors/plants/borefield.py @@ -207,4 +207,4 @@ def to_modelica(self, scaffold): plants_package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Plants.{self.borefield_name}.Borefield' + return f'Plants.{self.borefield_name}.Borefield' diff --git a/geojson_modelica_translator/model_connectors/plants/chp.py b/geojson_modelica_translator/model_connectors/plants/chp.py index a70056c48..a0c469ff1 100644 --- a/geojson_modelica_translator/model_connectors/plants/chp.py +++ b/geojson_modelica_translator/model_connectors/plants/chp.py @@ -101,4 +101,4 @@ def to_modelica(self, scaffold): plants_package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Plants.CentralHeatingPlant' + return 'Plants.CentralHeatingPlant' diff --git a/geojson_modelica_translator/model_connectors/plants/cooling_plant.py b/geojson_modelica_translator/model_connectors/plants/cooling_plant.py index 2c47b87bf..e54611ef4 100644 --- a/geojson_modelica_translator/model_connectors/plants/cooling_plant.py +++ b/geojson_modelica_translator/model_connectors/plants/cooling_plant.py @@ -140,4 +140,4 @@ def to_modelica(self, scaffold): plants_package.save() def get_modelica_type(self, scaffold): - return f'{scaffold.project_name}.Plants.CentralCoolingPlant' + return 'Plants.CentralCoolingPlant' diff --git a/geojson_modelica_translator/modelica/package_parser.py b/geojson_modelica_translator/modelica/package_parser.py index 17a11a612..7601f183a 100644 --- a/geojson_modelica_translator/modelica/package_parser.py +++ b/geojson_modelica_translator/modelica/package_parser.py @@ -1,9 +1,11 @@ # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +import copy import os +import re from pathlib import Path -from typing import Any, Union +from typing import Any, List, Optional, Union from jinja2 import Environment, FileSystemLoader @@ -26,8 +28,17 @@ class method. self.path: Union[str, Path, None] = path self.order_data: Any = None self.package_data: Any = None + self.package_name: Union[str, None] = None + self.within: Union[list, None] = None + self.load() + # read in the path if it was given and pull out the package name + if self.path is not None: + self.path = Path(self.path) + # The package name is also the name of the directory + self.package_name = self.path.name + self.template_env = Environment( loader=FileSystemLoader( searchpath=os.path.join( @@ -37,6 +48,26 @@ class method. ) self.template_env.filters.update(ALL_CUSTOM_FILTERS) + def parse_within_statement(self) -> Optional[List[str]]: + """Read in the package_data and parse out the within statement. The result will + be returns, but will also set the within attribute. + """ + # use a regex to pull out the string between within and ; + if self.package_data is None: + self.within = None + return None + + matches = re.findall(r'within\s(.*?);', self.package_data) + # it is possible that there is no "within" block in the root package file. + if len(matches) == 0 or matches is None: + self.within = None + elif len(matches) == 1: + self.within = matches[0].split(".") + else: + raise ValueError("There are more than on within statements in the package.mo file") + + return self.within + @classmethod def new_from_template(cls, path: Union[str, Path], name: str, order: list[str], within: Union[str, None] = None) -> "PackageParser": """Create new package data based on the package.mo template. If within is not specified, then it is @@ -59,6 +90,8 @@ def new_from_template(cls, path: Union[str, Path], name: str, order: list[str], klass.package_data = template.render(within=within, name=name, order=order) klass.order_data = "\n".join(order) + klass.package_name = name + klass.parse_within_statement() return klass def load(self) -> None: @@ -74,6 +107,8 @@ def load(self) -> None: with open(filename, "r") as f: self.order_data = f.read() + self.parse_within_statement() + def save(self) -> None: """Save the updated files to the same location """ @@ -84,6 +119,23 @@ def save(self) -> None: f.write(self.order_data) f.write("\n") + def save_as(self, new_path: Union[str, Path]) -> None: + """Save the package.mo and package.order file to the new path. Be + careful just running this method without also updating all the related + .mo and package.mo files with the new within statement. Look at the + ModelicaProject class for more support. + + Args: + new_path (Union[str, Path]): Fully qualified path to save files to. + """ + new_path = Path(new_path) + with open(new_path / "package.mo", "w") as f: + f.write(self.package_data) + + with open(new_path / "package.order", "w") as f: + f.write(self.order_data) + f.write("\n") + @property def order(self) -> list[str]: """Return the order of the packages from the package.order file @@ -96,14 +148,42 @@ def order(self) -> list[str]: data.remove("") return data - def rename_model(self, old_model: str, new_model: str): + def rename_package(self, new_model: str): + """Rename the model name in the package.mo file. + + Args: + new_model (str): new name + """ + if self.package_name is None: + raise ValueError("Package name is not set, verify that it was parsed correctly in the source code") + + self.package_data = self.package_data.replace(self.package_name, new_model) + self.package_name = new_model + + def rename_model(self, previous_model: str, new_model: str): """Rename the model name in the package.order file. Args: - old_model (str): existing name new_model (str): new name """ - self.order_data = self.order_data.replace(old_model, new_model) + self.order_data = self.order_data.replace(previous_model, new_model) + + def update_within_statement(self, new_within: str, element_index: Union[int, None] = None): + """Update the within statement in the package.mo file + + Args: + new_within (str): Full string of the new within statement, e.g., a.b.c.d + element_index (int): index of the element to replace, None is the entire string + """ + # new within + new_within_list = copy.deepcopy(self.within) + if element_index is not None: + new_within_list[element_index] = new_within # type: ignore + else: + new_within_list = new_within.split(".") + + self.package_data = self.package_data.replace(f"within {'.'.join(self.within)};", f"within {'.'.join(new_within_list)};") # type: ignore + self.within = new_within_list def add_model(self, new_model_name: str, insert_at: int = -1) -> None: """Insert a new model into the package. Note that the order_data is stored as a string right now, diff --git a/poetry.lock b/poetry.lock index 860a58ad3..674214ba9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -113,13 +113,13 @@ files = [ [[package]] name = "cfgv" -version = "3.3.1" +version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.8" files = [ - {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, - {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] [[package]] @@ -439,13 +439,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.2" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, - {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] [package.extras] @@ -928,12 +928,12 @@ python-dateutil = ">=2.7" [[package]] name = "modelica-builder" -version = "0.2.3" +version = "0.3.0" description = "Modelica builder enables programmatic parsing and modification of Modelica files" optional = false python-versions = "*" files = [ - {file = "modelica-builder-0.2.3.tar.gz", hash = "sha256:f50b822a91598c252de9cb758292c87d80ad8fa005478e8dca71d78eeebc87c3"}, + {file = "modelica-builder-0.3.0.tar.gz", hash = "sha256:f67d3b5c275c401b7f1382f54989d23edc1169d10a4c50966d534f7378bb99d9"}, ] [package.dependencies] @@ -1737,13 +1737,13 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.6" +version = "1.0.7" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_applehelp-1.0.6-py3-none-any.whl", hash = "sha256:c0578efa23cab5a2f3aaa8af5691b952433f4fdfaac255befd3452448e7ea4a4"}, - {file = "sphinxcontrib_applehelp-1.0.6.tar.gz", hash = "sha256:a59274de7a952a99af36b8a5092352d9249279c0e3280b7dceaae8e15873c942"}, + {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"}, + {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"}, ] [package.dependencies] @@ -1755,13 +1755,13 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" -version = "1.0.4" +version = "1.0.5" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_devhelp-1.0.4-py3-none-any.whl", hash = "sha256:d4e20a17f78865d4096733989b5efa0d5e7743900e98e1f6ecd6f489380febc8"}, - {file = "sphinxcontrib_devhelp-1.0.4.tar.gz", hash = "sha256:4fd751c63dc40895ac8740948f26bf1a3c87e4e441cc008672abd1cb2bc8a3d1"}, + {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"}, + {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"}, ] [package.dependencies] @@ -1773,13 +1773,13 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.3" +version = "2.0.4" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_htmlhelp-2.0.3-py3-none-any.whl", hash = "sha256:abee4e6c5471203ad2fc40dc6a16ed99884a5d6b15a6f79c9269a7e82cf04149"}, - {file = "sphinxcontrib_htmlhelp-2.0.3.tar.gz", hash = "sha256:14358d0f88ccf58447f2b54343cdcc0012f32de2f8d27cf934fdbc0b362f9597"}, + {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"}, + {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"}, ] [package.dependencies] @@ -1805,13 +1805,13 @@ test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.5" +version = "1.0.6" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_qthelp-1.0.5-py3-none-any.whl", hash = "sha256:962730a6ad15d21fd6760b14c9e95c00a097413595aa6ee871dd9dfa4b002a16"}, - {file = "sphinxcontrib_qthelp-1.0.5.tar.gz", hash = "sha256:d31d1a1beaf3894866bb318fb712f1edc82687f1c06235a01e5b2c50c36d5c40"}, + {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"}, + {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"}, ] [package.dependencies] @@ -1823,13 +1823,13 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-serializinghtml" -version = "1.1.7" +version = "1.1.8" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_serializinghtml-1.1.7-py3-none-any.whl", hash = "sha256:424164fc3a8b4355a29d5ea8b7f18199022d160c8f7b96e68bb6c50217729b87"}, - {file = "sphinxcontrib_serializinghtml-1.1.7.tar.gz", hash = "sha256:ca31afee32e1508cff4034e258060ce2c81a3b1c49e77da60fdb61f0e7a73c22"}, + {file = "sphinxcontrib_serializinghtml-1.1.8-py3-none-any.whl", hash = "sha256:27849e7227277333d3d32f17c138ee148a51fa01f888a41cd6d4e73bcabe2d06"}, + {file = "sphinxcontrib_serializinghtml-1.1.8.tar.gz", hash = "sha256:aaf3026335146e688fd209b72320314b1b278320cf232e3cda198f873838511a"}, ] [package.dependencies] @@ -1933,13 +1933,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.24.2" +version = "20.24.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.2-py3-none-any.whl", hash = "sha256:43a3052be36080548bdee0b42919c88072037d50d56c28bd3f853cbe92b953ff"}, - {file = "virtualenv-20.24.2.tar.gz", hash = "sha256:fd8a78f46f6b99a67b7ec5cf73f92357891a7b3a40fd97637c27f854aae3b9e0"}, + {file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"}, + {file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"}, ] [package.dependencies] @@ -1969,4 +1969,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9, <3.12" -content-hash = "4c5e07122b2816a0d7a645ec3524d998e8ccb167277df3afd5d217cdf3cf9da5" +content-hash = "d996e0f11863f81f59ee423e9bba8b4e7f549c387c89f92a9b708673f164acf8" diff --git a/pyproject.toml b/pyproject.toml index 1f41ea891..2fe0291f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,8 @@ geojson = "^3.0.0" jinja2 = "3.1.2" jsonpath-ng = "1.5.3" jsonschema = "~4.17" -modelica-builder = "^0.2.3" +modelica-builder = "^0.3.0" +# modelica-builder = { path = "../modelica-builder", develop = true } pandas = "2.0.2" requests = "^2.28" teaser = "0.7.5" diff --git a/tests/modelica/test_package_parser.py b/tests/modelica/test_package_parser.py index 294126504..7d918bacc 100644 --- a/tests/modelica/test_package_parser.py +++ b/tests/modelica/test_package_parser.py @@ -43,7 +43,18 @@ def test_round_trip(self): package = PackageParser(self.output_dir) self.assertListEqual(package.order, ["model_x", "model_y"]) - def test_rename_model(self): + def test_rename_package_model(self): + package = PackageParser.new_from_template( + self.output_dir, 'rename_model', ["model_1", "model_2"], within="RenameWithin" + ) + package.save() + + package.rename_package('my_super_new_model') + self.assertEqual(len(package.order), 2) + self.assertIn('my_super_new_model', package.package_data) + self.assertEqual(package.package_name, 'my_super_new_model') + + def test_rename_model_in_order(self): package = PackageParser.new_from_template( self.output_dir, 'rename_model', ["model_1", "model_2"], within="RenameWithin" ) @@ -63,3 +74,16 @@ def test_add_model(self): package.add_model('model_alpha', 0) self.assertEqual(len(package.order), 4) self.assertListEqual(['model_alpha', 'model_beta', 'model_gamma', 'model_delta'], package.order) + + def test_within_clause(self): + package = PackageParser.new_from_template( + self.output_dir, 'within_clause', ["model_a", "model_b"], within="SomeWithin" + ) + package.save() + + self.assertEqual(package.within, ['SomeWithin']) + + package.update_within_statement('NewWithin') + self.assertEqual(package.within, ['NewWithin']) + + \ No newline at end of file