From 352bcc41c683d8acfd17eb80936606ba90ead781 Mon Sep 17 00:00:00 2001 From: syntron Date: Mon, 15 Dec 2025 21:46:06 +0100 Subject: [PATCH 1/5] [ModelicaSystem] improve handling of model simulation * ensure a message if logged if returncode != 0 --- OMPython/ModelicaSystem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index dfc70fd6..b9af22bc 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -1185,15 +1185,15 @@ def simulate( cmd_definition = om_cmd.definition() returncode = self._session.run_model_executable(cmd_run_data=cmd_definition) # and check returncode *AND* resultfile - if returncode != 0 and self._result_file.is_file(): + if returncode != 0: # check for an empty (=> 0B) result file which indicates a crash of the model executable # see: https://github.com/OpenModelica/OMPython/issues/261 # https://github.com/OpenModelica/OpenModelica/issues/13829 - if self._result_file.size() == 0: + if self._result_file.is_file() and self._result_file.size() == 0: self._result_file.unlink() raise ModelicaSystemError("Empty result file - this indicates a crash of the model executable!") - logger.warning(f"Return code = {returncode} but result file exists!") + logger.warning(f"Return code = {returncode} but result file was created!") self._simulated = True From 256af2526ee028aa786f7d04259977e45883fdea Mon Sep 17 00:00:00 2001 From: syntron Date: Tue, 16 Dec 2025 21:17:23 +0100 Subject: [PATCH 2/5] [ModelicaSystemDoE] fix exception handling * self.session().run_model_executable() will raise OMCSessionException! --- OMPython/ModelicaSystem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OMPython/ModelicaSystem.py b/OMPython/ModelicaSystem.py index b9af22bc..dd8e35af 100644 --- a/OMPython/ModelicaSystem.py +++ b/OMPython/ModelicaSystem.py @@ -2188,9 +2188,9 @@ def worker(worker_id, task_queue): try: returncode = self.get_session().run_model_executable(cmd_run_data=cmd_definition) logger.info(f"[Worker {worker_id}] Simulation {resultpath.name} " - f"finished with return code: {returncode}") - except ModelicaSystemError as ex: - logger.warning(f"Simulation error for {resultpath.name}: {ex}") + f"finished with return code {returncode}") + except OMCSessionException as ex: + logger.warning(f"Error executing {repr(cmd_definition.get_cmd())}: {ex}") # Mark the task as done task_queue.task_done() From 2c92c0009d4eb14e4e6d8be87f6f99e536936e32 Mon Sep 17 00:00:00 2001 From: syntron Date: Thu, 27 Nov 2025 10:21:54 +0100 Subject: [PATCH 3/5] [OMCSession] fix definiton of _timeout variable - use set_timeout() checks --- OMPython/OMCSession.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OMPython/OMCSession.py b/OMPython/OMCSession.py index cd1789c8..8898c210 100644 --- a/OMPython/OMCSession.py +++ b/OMPython/OMCSession.py @@ -642,7 +642,9 @@ def __init__( """ # store variables - self._timeout = timeout + # set_timeout() is used to define the value of _timeout as it includes additional checks + self._timeout: float + self.set_timeout(timeout=timeout) # generate a random string for this instance of OMC self._random_string = uuid.uuid4().hex # get a temporary directory From 2baab7c5d46255ad57992b05572e060774861927 Mon Sep 17 00:00:00 2001 From: syntron Date: Thu, 27 Nov 2025 21:19:13 +0100 Subject: [PATCH 4/5] [OMCSession] move call to set_timeout() to __post_init__ --- OMPython/OMCSession.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/OMPython/OMCSession.py b/OMPython/OMCSession.py index 8898c210..cd1789c8 100644 --- a/OMPython/OMCSession.py +++ b/OMPython/OMCSession.py @@ -642,9 +642,7 @@ def __init__( """ # store variables - # set_timeout() is used to define the value of _timeout as it includes additional checks - self._timeout: float - self.set_timeout(timeout=timeout) + self._timeout = timeout # generate a random string for this instance of OMC self._random_string = uuid.uuid4().hex # get a temporary directory From dc6dd5d66aeda9a79668418aa9f855da43196a2b Mon Sep 17 00:00:00 2001 From: syntron Date: Thu, 24 Jul 2025 20:52:18 +0200 Subject: [PATCH 5/5] [OMCPath] remove compatibility code for Python < 3.12 --- .github/workflows/Test.yml | 2 +- OMPython/OMCSession.py | 58 ++------------------------------------ 2 files changed, 3 insertions(+), 57 deletions(-) diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index 3d87cac2..fe6e1176 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -17,7 +17,7 @@ jobs: # test for: # * oldest supported version # * latest available Python version - python-version: ['3.10', '3.14'] + python-version: ['3.12', '3.14'] # * Linux using ubuntu-latest # * Windows using windows-latest os: ['ubuntu-latest', 'windows-latest'] diff --git a/OMPython/OMCSession.py b/OMPython/OMCSession.py index cd1789c8..ff9b49c2 100644 --- a/OMPython/OMCSession.py +++ b/OMPython/OMCSession.py @@ -249,7 +249,7 @@ def getClassNames(self, className=None, recursive=False, qualified=False, sort=F return self._ask(question='getClassNames', opt=opt) -class OMCPathReal(pathlib.PurePosixPath): +class OMCPath(pathlib.PurePosixPath): """ Implementation of a basic (PurePosix)Path object which uses OMC as backend. The connection to OMC is provided via an instances of OMCSession* classes. @@ -415,49 +415,6 @@ def stat(self): "use size() to get the file size.") -if sys.version_info < (3, 12): - - class OMCPathCompatibility(pathlib.Path): - """ - Compatibility class for OMCPath in Python < 3.12. This allows to run all code which uses OMCPath (mainly - ModelicaSystem) on these Python versions. There is one remaining limitation: only OMCProcessLocal will work as - OMCPathCompatibility is based on the standard pathlib.Path implementation. - """ - - # modified copy of pathlib.Path.__new__() definition - def __new__(cls, *args, **kwargs): - logger.warning("Python < 3.12 - using a version of class OMCPath " - "based on pathlib.Path for local usage only.") - - if cls is OMCPathCompatibility: - cls = OMCPathCompatibilityWindows if os.name == 'nt' else OMCPathCompatibilityPosix - self = cls._from_parts(args) - if not self._flavour.is_supported: - raise NotImplementedError(f"cannot instantiate {cls.__name__} on your system") - return self - - def size(self) -> int: - """ - Needed compatibility function to have the same interface as OMCPathReal - """ - return self.stat().st_size - - class OMCPathCompatibilityPosix(pathlib.PosixPath, OMCPathCompatibility): - """ - Compatibility class for OMCPath on Posix systems (Python < 3.12) - """ - - class OMCPathCompatibilityWindows(pathlib.WindowsPath, OMCPathCompatibility): - """ - Compatibility class for OMCPath on Windows systems (Python < 3.12) - """ - - OMCPath = OMCPathCompatibility - -else: - OMCPath = OMCPathReal - - @dataclasses.dataclass class OMCSessionRunData: """ @@ -770,13 +727,6 @@ def omcpath(self, *path) -> OMCPath: """ Create an OMCPath object based on the given path segments and the current OMCSession* class. """ - - # fallback solution for Python < 3.12; a modified pathlib.Path object is used as OMCPath replacement - if sys.version_info < (3, 12): - if isinstance(self, OMCSessionLocal): - # noinspection PyArgumentList - return OMCPath(*path) - raise OMCSessionException("OMCPath is supported for Python < 3.12 only if OMCSessionLocal is used!") return OMCPath(*path, session=self) def omcpath_tempdir(self, tempdir_base: Optional[OMCPath] = None) -> OMCPath: @@ -787,11 +737,7 @@ def omcpath_tempdir(self, tempdir_base: Optional[OMCPath] = None) -> OMCPath: names = [str(uuid.uuid4()) for _ in range(100)] if tempdir_base is None: - # fallback solution for Python < 3.12; a modified pathlib.Path object is used as OMCPath replacement - if sys.version_info < (3, 12): - tempdir_str = tempfile.gettempdir() - else: - tempdir_str = self.sendExpression("getTempDirectoryPath()") + tempdir_str = self.sendExpression(command="getTempDirectoryPath()") tempdir_base = self.omcpath(tempdir_str) tempdir: Optional[OMCPath] = None