Skip to content

Commit ecc745d

Browse files
authored
Merge branch 'master' into F001-restructure_cleanup
2 parents 3920eb6 + 705b00e commit ecc745d

6 files changed

Lines changed: 44 additions & 20 deletions

File tree

OMPython/OMCSession.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,14 @@ def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC
282282
def execute(self, command: str):
283283
return self.omc_process.execute(command=command)
284284

285-
def sendExpression(self, command: str, parsed: bool = True) -> Any:
285+
def sendExpression(self, command: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
286286
"""
287287
Send an expression to the OMC server and return the result.
288288
289289
The complete error handling of the OMC result is done within this method using '"getMessagesStringInternal()'.
290290
Caller should only check for OMSessionException.
291291
"""
292-
return self.omc_process.sendExpression(expr=command, parsed=parsed)
292+
return self.omc_process.sendExpression(expr=command, parsed=parsed, raise_on_error=raise_on_error)
293293

294294
def get_version(self) -> str:
295295
return self.omc_process.get_version()

OMPython/modelica_system_omc.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,15 @@ def buildModel(self, variableFilter: Optional[str] = None):
203203
else:
204204
var_filter = 'variableFilter=".*"'
205205

206-
build_model_result = self._requestApi(apiName="buildModel", entity=self._model_name, properties=var_filter)
206+
# buildModel() can emit 'error'-level diagnostics (e.g. a structurally singular initialization
207+
# system) that OMC itself recovers from without actually failing the build. Don't raise on those
208+
# here; check_model_executable()/_xmlparse() below independently verify the build really succeeded.
209+
build_model_result = self._requestApi(
210+
apiName="buildModel",
211+
entity=self._model_name,
212+
properties=var_filter,
213+
raise_on_error=False,
214+
)
207215
logger.debug("OM model build result: %s", build_model_result)
208216

209217
# check if the executable exists ...
@@ -212,12 +220,12 @@ def buildModel(self, variableFilter: Optional[str] = None):
212220
xml_file = self._session.omcpath(build_model_result[0]).parent / build_model_result[1]
213221
self._xmlparse(xml_file=xml_file)
214222

215-
def sendExpression(self, expr: str, parsed: bool = True) -> Any:
223+
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
216224
"""
217225
Wrapper for OMCSession.sendExpression().
218226
"""
219227
try:
220-
retval = self._session.sendExpression(expr=expr, parsed=parsed)
228+
retval = self._session.sendExpression(expr=expr, parsed=parsed, raise_on_error=raise_on_error)
221229
except OMSessionException as ex:
222230
raise ModelicaSystemError(f"Error executing {repr(expr)}: {ex}") from ex
223231

@@ -231,6 +239,7 @@ def _requestApi(
231239
apiName: str,
232240
entity: Optional[str] = None,
233241
properties: Optional[str] = None,
242+
raise_on_error: bool = True,
234243
) -> Any:
235244
if entity is not None and properties is not None:
236245
expr = f'{apiName}({entity}, {properties})'
@@ -242,7 +251,7 @@ def _requestApi(
242251
else:
243252
expr = f'{apiName}()'
244253

245-
return self.sendExpression(expr=expr)
254+
return self.sendExpression(expr=expr, raise_on_error=raise_on_error)
246255

247256
def getContinuousFinal(
248257
self,

OMPython/om_session_abc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,10 @@ def _tempdir(tempdir_base: OMPathABC) -> OMPathABC:
317317
return tempdir
318318

319319
@abc.abstractmethod
320-
def sendExpression(self, expr: str, parsed: bool = True) -> Any:
320+
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
321321
"""
322322
Function needed to send expressions to the OMC server via ZMQ.
323+
324+
If raise_on_error is False, 'error'-level OMC diagnostics are logged instead of raised as an
325+
OMSessionException; use this only when the caller has its own, more precise way of verifying success.
323326
"""

OMPython/om_session_omc.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,18 @@ def execute(self, command: str):
387387

388388
return self.sendExpression(command, parsed=False)
389389

390-
def sendExpression(self, expr: str, parsed: bool = True) -> Any:
390+
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
391391
"""
392392
Send an expression to the OMC server and return the result.
393393
394394
The complete error handling of the OMC result is done within this method using 'getMessagesStringInternal()'.
395395
Caller should only check for OMSessionException.
396+
397+
Some OMC API calls (e.g. buildModel) can emit 'error'-level diagnostics that are recoverable and don't
398+
actually prevent the call from succeeding (e.g. a structurally singular initialization system that OMC
399+
resolves via a fallback). Callers who have their own, more precise way of verifying success (such as
400+
checking that the resulting files/executable actually exist) can pass raise_on_error=False to have such
401+
messages logged instead of raised as an exception.
396402
"""
397403

398404
if self._omc_zmq is None:
@@ -509,8 +515,11 @@ def sendExpression(self, expr: str, parsed: bool = True) -> Any:
509515
msg_long_list.append(msg_long)
510516
if has_error:
511517
msg_long_str = '\n'.join(f"{idx:02d}: {msg}" for idx, msg in enumerate(msg_long_list))
512-
raise OMSessionException(f"OMC error occurred for 'sendExpression(expr={expr}, parsed={parsed}):\n"
513-
f"{msg_long_str}")
518+
if raise_on_error:
519+
raise OMSessionException(
520+
f"OMC error occurred for 'sendExpression(expr={expr}, parsed={parsed}):\n{msg_long_str}")
521+
logger.warning("OMC reported 'error'-level messages for 'sendExpression(expr=%s, parsed=%s)', but "
522+
"raise_on_error=False was requested; continuing:\n%s", expr, parsed, msg_long_str)
514523

515524
if not parsed:
516525
return result
@@ -866,17 +875,20 @@ def _docker_omc_start(
866875
loop = self._timeout_loop(timestep=0.1)
867876
while next(loop):
868877
try:
869-
with open(file=docker_cid_file, mode="r", encoding="utf-8") as fh:
878+
with open(docker_cid_file, "r", encoding="utf-8") as fh:
870879
docker_cid = fh.read().strip()
871880
except IOError:
872-
pass
873-
if docker_cid is not None:
881+
continue
882+
883+
if docker_cid:
874884
break
875885

876-
if docker_cid is None:
877-
raise OMSessionException(f"Docker did not start (timeout={self._timeout:.2f}s might be too short "
878-
"especially if you did not docker pull the image before this command). "
879-
f"Log-file says:\n{self.get_log()}")
886+
if not docker_cid:
887+
raise OMSessionException(
888+
f"Docker did not start (timeout={self._timeout:.2f}s might be too short "
889+
"especially if you did not docker pull the image before this command). "
890+
f"Log-file says:\n{self.get_log()}"
891+
)
880892

881893
docker_process = self._docker_process_get(docker_cid=docker_cid)
882894
if docker_process is None:

OMPython/om_session_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,5 +379,5 @@ def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC
379379

380380
return self._tempdir(tempdir_base=tempdir_base)
381381

382-
def sendExpression(self, expr: str, parsed: bool = True) -> Any:
382+
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
383383
raise OMSessionException(f"{self.__class__.__name__} does not uses an OMC server!")

tests/test_docker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212

1313
@skip_on_windows
1414
def test_docker():
15-
omcs = OMPython.OMCSessionDocker(docker="openmodelica/openmodelica:v1.25.0-minimal")
15+
omcs = OMPython.OMCSessionDocker(docker="openmodelica/openmodelica:v1.27.0-ompython")
1616
omversion = omcs.sendExpression("getVersion()")
1717
assert isinstance(omversion, str) and omversion.startswith("OpenModelica")
1818

1919
omcsInner = OMPython.OMCSessionDockerContainer(dockerContainer=omcs.get_docker_container_id())
2020
omversion = omcsInner.sendExpression("getVersion()")
2121
assert isinstance(omversion, str) and omversion.startswith("OpenModelica")
2222

23-
omcs2 = OMPython.OMCSessionDocker(docker="openmodelica/openmodelica:v1.25.0-minimal", port=11111)
23+
omcs2 = OMPython.OMCSessionDocker(docker="openmodelica/openmodelica:v1.27.0-ompython", port=11111)
2424
omversion = omcs2.sendExpression("getVersion()")
2525
assert isinstance(omversion, str) and omversion.startswith("OpenModelica")
2626

0 commit comments

Comments
 (0)