4141import os
4242import pathlib
4343import psutil
44+ import re
4445import signal
4546import subprocess
4647import sys
@@ -325,6 +326,9 @@ def __init__(self, timeout=10.00,
325326 # connect to the running omc instance using ZMQ
326327 self ._connect_to_omc (timeout )
327328
329+ self ._re_log_entries = None
330+ self ._re_log_raw = None
331+
328332 def __del__ (self ):
329333 try :
330334 self .sendExpression ("quit()" )
@@ -549,6 +553,62 @@ def sendExpression(self, command, parsed=True):
549553 return None
550554 else :
551555 result = self ._omc .recv_string ()
556+
557+ if command == "getErrorString()" :
558+ # no error handling if 'getErrorString()' is called
559+ pass
560+ elif command == "getMessagesStringInternal()" :
561+ # no error handling if 'getMessagesStringInternal()' is called; parsing NOT possible!
562+ if parsed :
563+ logger .warning ("Result of 'getMessagesStringInternal()' cannot be parsed - set parsed to False!" )
564+ parsed = False
565+ else :
566+ # allways check for error
567+ self ._omc .send_string ('getMessagesStringInternal()' , flags = zmq .NOBLOCK )
568+ error_raw = self ._omc .recv_string ()
569+ # run error handling only if there is something to check
570+ if error_raw != "{}\n " :
571+ if not self ._re_log_entries :
572+ self ._re_log_entries = re .compile (pattern = r'record OpenModelica\.Scripting\.ErrorMessage'
573+ '(.*?)'
574+ r'end OpenModelica\.Scripting\.ErrorMessage;' ,
575+ flags = re .MULTILINE | re .DOTALL )
576+ if not self ._re_log_raw :
577+ self ._re_log_raw = re .compile (
578+ pattern = r"\s+message = \"(.*?)\",\n" # message
579+ r"\s+kind = .OpenModelica.Scripting.ErrorKind.(.*?),\n" # kind
580+ r"\s+level = .OpenModelica.Scripting.ErrorLevel.(.*?),\n" # level
581+ r"\s+id = (.*?)" # id
582+ "(,\n |\n )" , # end marker
583+ flags = re .MULTILINE | re .DOTALL )
584+
585+ # extract all ErrorMessage records
586+ log_entries = self ._re_log_entries .findall (string = error_raw )
587+ for log_entry in reversed (log_entries ):
588+ log_raw = self ._re_log_raw .findall (string = log_entry )
589+ if len (log_raw ) != 1 or len (log_raw [0 ]) != 5 :
590+ logger .warning ("Invalid ErrorMessage record returned by 'getMessagesStringInternal()':"
591+ f" { repr (log_entry )} !" )
592+
593+ log_message = log_raw [0 ][0 ].encode ().decode ('unicode_escape' )
594+ log_kind = log_raw [0 ][1 ]
595+ log_level = log_raw [0 ][2 ]
596+ log_id = log_raw [0 ][3 ]
597+
598+ msg = (f"[OMC log for 'sendExpression({ command } , { parsed } )']: "
599+ f"[{ log_kind } :{ log_level } :{ log_id } ] { log_message } " )
600+
601+ # response according to the used log level
602+ # see: https://build.openmodelica.org/Documentation/OpenModelica.Scripting.ErrorLevel.html
603+ if log_level == 'error' :
604+ raise OMCSessionException (msg )
605+ elif log_level == 'warning' :
606+ logger .warning (msg )
607+ elif log_level == 'notification' :
608+ logger .info (msg )
609+ else : # internal
610+ logger .debug (msg )
611+
552612 if parsed is True :
553613 try :
554614 return om_parser_typed (result )
@@ -557,7 +617,6 @@ def sendExpression(self, command, parsed=True):
557617 try :
558618 return om_parser_basic (result )
559619 except (TypeError , UnboundLocalError ) as ex :
560- logger .warning ('OMParser error: %s. Returning the unparsed result.' , ex )
561- return result
620+ raise OMCSessionException ("Cannot parse OMC result" ) from ex
562621 else :
563622 return result
0 commit comments