From a9442b509ae60665368f4db7f6312b0cc0d60356 Mon Sep 17 00:00:00 2001 From: syntron Date: Wed, 9 Jul 2025 20:26:04 +0200 Subject: [PATCH 1/5] [ModelicaSystem] update handling of xml_file --- OMPython/ModelicaSystem.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index ae480dde..bf0c22a0 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -480,8 +480,10 @@ def buildModel(self, variableFilter: Optional[str] = None): buildModelResult = self._requestApi("buildModel", self._model_name, properties=varFilter) logger.debug("OM model build result: %s", buildModelResult) - self._xml_file = pathlib.Path(buildModelResult[0]).parent / buildModelResult[1] - self._xmlparse() + xml_file = pathlib.Path(buildModelResult[0]).parent / buildModelResult[1] + self._xmlparse(xml_file=xml_file) + # TODO: remove _xml_file?! + self._xml_file = xml_file def sendExpression(self, expr: str, parsed: bool = True): try: @@ -507,11 +509,11 @@ def _requestApi(self, apiName, entity=None, properties=None): # 2 return self.sendExpression(exp) - def _xmlparse(self): - if not self._xml_file.is_file(): - raise ModelicaSystemError(f"XML file not generated: {self._xml_file}") + def _xmlparse(self, xml_file: pathlib.Path): + if not xml_file.is_file(): + raise ModelicaSystemError(f"XML file not generated: {xml_file}") - tree = ET.parse(self._xml_file) + tree = ET.parse(xml_file) rootCQ = tree.getroot() for attr in rootCQ.iter('DefaultExperiment'): for key in ("startTime", "stopTime", "stepSize", "tolerance", From c4fabc5c5705d7443e7463deb0ea298697dca01c Mon Sep 17 00:00:00 2001 From: syntron Date: Wed, 9 Jul 2025 20:26:42 +0200 Subject: [PATCH 2/5] [ModelicaSystem] replace ET.parse() with ET.ElementTree(ET.fromstring()) read the file content and work on this string see: https://stackoverflow.com/questions/647071/python-xml-elementtree-from-a-string-source --- OMPython/ModelicaSystem.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index bf0c22a0..454bc472 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -513,7 +513,8 @@ def _xmlparse(self, xml_file: pathlib.Path): if not xml_file.is_file(): raise ModelicaSystemError(f"XML file not generated: {xml_file}") - tree = ET.parse(xml_file) + xml_content = xml_file.read_text() + tree = ET.ElementTree(ET.fromstring(xml_content)) rootCQ = tree.getroot() for attr in rootCQ.iter('DefaultExperiment'): for key in ("startTime", "stopTime", "stepSize", "tolerance", From 3133f61ea308fc6eb58690ba6f8f2d8da7102118 Mon Sep 17 00:00:00 2001 From: syntron Date: Thu, 10 Jul 2025 09:59:04 +0200 Subject: [PATCH 3/5] [ModelicaSystem._xmlparse] mypy fixes & cleanup --- OMPython/ModelicaSystem.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index 454bc472..3fc47bea 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -519,14 +519,24 @@ def _xmlparse(self, xml_file: pathlib.Path): for attr in rootCQ.iter('DefaultExperiment'): for key in ("startTime", "stopTime", "stepSize", "tolerance", "solver", "outputFormat"): - self._simulate_options[key] = attr.get(key) + self._simulate_options[key] = str(attr.get(key)) for sv in rootCQ.iter('ScalarVariable'): - scalar = {} - for key in ("name", "description", "variability", "causality", "alias"): - scalar[key] = sv.get(key) - scalar["changeable"] = sv.get('isValueChangeable') - scalar["aliasvariable"] = sv.get('aliasVariable') + translations = { + "alias": "alias", + "aliasvariable": "aliasVariable", + "causality": "causality", + "changeable": "isValueChangeable", + "description": "description", + "name": "name", + "variability": "variability", + } + + scalar: dict[str, Any] = {} + for key_dst, key_src in translations.items(): + val = sv.get(key_src) + scalar[key_dst] = None if val is None else str(val) + ch = list(sv) for att in ch: scalar["start"] = att.get('start') @@ -534,6 +544,7 @@ def _xmlparse(self, xml_file: pathlib.Path): scalar["max"] = att.get('max') scalar["unit"] = att.get('unit') + # save parameters in the corresponding class variables if scalar["variability"] == "parameter": if scalar["name"] in self._override_variables: self._params[scalar["name"]] = self._override_variables[scalar["name"]] From 33ea4607da95359f031e972cf3d33a0396a2301e Mon Sep 17 00:00:00 2001 From: syntron Date: Thu, 10 Jul 2025 10:03:53 +0200 Subject: [PATCH 4/5] [ModelicaSystem] remove class variable _xml_file --- OMPython/ModelicaSystem.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index 3fc47bea..ccaaedfa 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -383,7 +383,6 @@ def __init__( if not isinstance(lmodel, list): raise ModelicaSystemError(f"Invalid input type for lmodel: {type(lmodel)} - list expected!") - self._xml_file = None self._lmodel = lmodel # may be needed if model is derived from other model self._model_name = modelName # Model class name self._file_name = pathlib.Path(fileName).resolve() if fileName is not None else None # Model file/package name @@ -482,8 +481,6 @@ def buildModel(self, variableFilter: Optional[str] = None): xml_file = pathlib.Path(buildModelResult[0]).parent / buildModelResult[1] self._xmlparse(xml_file=xml_file) - # TODO: remove _xml_file?! - self._xml_file = xml_file def sendExpression(self, expr: str, parsed: bool = True): try: @@ -1549,7 +1546,8 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N compatibility, because linearize() used to return `[A, B, C, D]`. """ - if self._xml_file is None: + if len(self._quantities) == 0: + # if self._quantities has no content, the xml file was not parsed; see self._xmlparse() raise ModelicaSystemError( "Linearization cannot be performed as the model is not build, " "use ModelicaSystem() to build the model first" From fa1f4536006475239019fcebdcc5c0f5eecbb9a8 Mon Sep 17 00:00:00 2001 From: syntron Date: Sat, 12 Jul 2025 12:03:40 +0200 Subject: [PATCH 5/5] [ModelicaSystem] fix mypy warning - value can have different types in this code (int or str) --- OMPython/ModelicaSystem.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index ccaaedfa..16205bbc 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -1558,10 +1558,10 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N overrideLinearFile = self._tempdir / f'{self._model_name}_override_linear.txt' with open(file=overrideLinearFile, mode="w", encoding="utf-8") as fh: - for key, value in self._override_variables.items(): - fh.write(f"{key}={value}\n") - for key, value in self._linearization_options.items(): - fh.write(f"{key}={value}\n") + for key1, value1 in self._override_variables.items(): + fh.write(f"{key1}={value1}\n") + for key2, value2 in self._linearization_options.items(): + fh.write(f"{key2}={value2}\n") om_cmd.arg_set(key="overrideFile", val=overrideLinearFile.as_posix())