Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions OMPython/OMCSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,14 +282,14 @@ def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC
def execute(self, command: str):
return self.omc_process.execute(command=command)

def sendExpression(self, command: str, parsed: bool = True) -> Any:
def sendExpression(self, command: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
"""
Send an expression to the OMC server and return the result.

The complete error handling of the OMC result is done within this method using '"getMessagesStringInternal()'.
Caller should only check for OMSessionException.
"""
return self.omc_process.sendExpression(expr=command, parsed=parsed)
return self.omc_process.sendExpression(expr=command, parsed=parsed, raise_on_error=raise_on_error)

def get_version(self) -> str:
return self.omc_process.get_version()
Expand Down
13 changes: 9 additions & 4 deletions OMPython/modelica_system_omc.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,11 @@ def buildModel(self, variableFilter: Optional[str] = None):
else:
var_filter = 'variableFilter=".*"'

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

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

def sendExpression(self, expr: str, parsed: bool = True) -> Any:
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
"""
Wrapper for OMCSession.sendExpression().
"""
try:
retval = self._session.sendExpression(expr=expr, parsed=parsed)
retval = self._session.sendExpression(expr=expr, parsed=parsed, raise_on_error=raise_on_error)
except OMSessionException as ex:
raise ModelicaSystemError(f"Error executing {repr(expr)}: {ex}") from ex

Expand All @@ -231,6 +235,7 @@ def _requestApi(
apiName: str,
entity: Optional[str] = None,
properties: Optional[str] = None,
raise_on_error: bool = True,
) -> Any:
if entity is not None and properties is not None:
expr = f'{apiName}({entity}, {properties})'
Expand All @@ -242,7 +247,7 @@ def _requestApi(
else:
expr = f'{apiName}()'

return self.sendExpression(expr=expr)
return self.sendExpression(expr=expr, raise_on_error=raise_on_error)

def getContinuousFinal(
self,
Expand Down
5 changes: 4 additions & 1 deletion OMPython/om_session_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,10 @@ def _tempdir(tempdir_base: OMPathABC) -> OMPathABC:
return tempdir

@abc.abstractmethod
def sendExpression(self, expr: str, parsed: bool = True) -> Any:
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
"""
Function needed to send expressions to the OMC server via ZMQ.

If raise_on_error is False, 'error'-level OMC diagnostics are logged instead of raised as an
OMSessionException; use this only when the caller has its own, more precise way of verifying success.
"""
15 changes: 12 additions & 3 deletions OMPython/om_session_omc.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,18 @@ def execute(self, command: str):

return self.sendExpression(command, parsed=False)

def sendExpression(self, expr: str, parsed: bool = True) -> Any:
def sendExpression(self, expr: str, parsed: bool = True, raise_on_error: bool = True) -> Any:
"""
Send an expression to the OMC server and return the result.

The complete error handling of the OMC result is done within this method using 'getMessagesStringInternal()'.
Caller should only check for OMSessionException.

Some OMC API calls (e.g. buildModel) can emit 'error'-level diagnostics that are recoverable and don't
actually prevent the call from succeeding (e.g. a structurally singular initialization system that OMC
resolves via a fallback). Callers who have their own, more precise way of verifying success (such as
checking that the resulting files/executable actually exist) can pass raise_on_error=False to have such
messages logged instead of raised as an exception.
"""

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

if not parsed:
return result
Expand Down
2 changes: 1 addition & 1 deletion OMPython/om_session_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,5 +379,5 @@ def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC

return self._tempdir(tempdir_base=tempdir_base)

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