5151import warnings
5252
5353# TODO: replace this with the new parser
54- from OMPython import OMTypedParser
55- from OMPython import OMParser
54+ from OMPython . OMTypedParser import parseString as om_parser_typed
55+ from OMPython . OMParser import om_parser_basic
5656
5757
5858# define logger using the current module name as ID
@@ -75,15 +75,16 @@ def wait(self, timeout):
7575 return self .process .wait (timeout = timeout )
7676
7777
78+ class OMCSessionException (Exception ):
79+ pass
80+
81+
7882class OMCSessionBase (metaclass = abc .ABCMeta ):
7983
8084 def __init__ (self , readonly = False ):
8185 self ._readonly = readonly
8286 self ._omc_cache = {}
8387
84- def clearOMParserResult (self ):
85- OMParser .result = {}
86-
8788 def execute (self , command ):
8889 warnings .warn ("This function is depreciated and will be removed in future versions; "
8990 "please use sendExpression() instead" , DeprecationWarning , stacklevel = 1 )
@@ -122,7 +123,7 @@ def ask(self, question, opt=None, parsed=True):
122123
123124 try :
124125 res = self .sendExpression (expression , parsed = parsed )
125- except Exception :
126+ except OMCSessionException :
126127 logger .error ("OMC failed: %s, %s, parsed=%s" , question , opt , parsed )
127128 raise
128129
@@ -197,7 +198,7 @@ def getClassComment(self, className):
197198 return self .ask ('getClassComment' , className )
198199 except pyparsing .ParseException as ex :
199200 logger .warning ("Method 'getClassComment' failed for %s" , className )
200- logger .warning ('OMTypedParser error: %s' , ex .message )
201+ logger .warning ('OMTypedParser error: %s' , ex .msg )
201202 return 'No description available'
202203
203204 def getNthComponent (self , className , comp_id ):
@@ -232,44 +233,20 @@ def getParameterValue(self, className, parameterName):
232233 try :
233234 return self .ask ('getParameterValue' , f'{ className } , { parameterName } ' )
234235 except pyparsing .ParseException as ex :
235- logger .warning ('OMTypedParser error: %s' , ex .message )
236+ logger .warning ('OMTypedParser error: %s' , ex .msg )
236237 return ""
237238
238239 def getComponentModifierNames (self , className , componentName ):
239240 return self .ask ('getComponentModifierNames' , f'{ className } , { componentName } ' )
240241
241242 def getComponentModifierValue (self , className , componentName ):
242- try :
243- # FIXME: OMPython exception UnboundLocalError exception for 'Modelica.Fluid.Machines.ControlledPump'
244- return self .ask ('getComponentModifierValue' , f'{ className } , { componentName } ' )
245- except pyparsing .ParseException as ex :
246- logger .warning ('OMTypedParser error: %s' , ex .message )
247- result = self .ask ('getComponentModifierValue' , f'{ className } , { componentName } ' , parsed = False )
248- try :
249- answer = OMParser .check_for_values (result )
250- OMParser .result = {}
251- return answer [2 :]
252- except (TypeError , UnboundLocalError ) as ex :
253- logger .warning ('OMParser error: %s' , ex )
254- return result
243+ return self .ask (question = 'getComponentModifierValue' , opt = f'{ className } , { componentName } ' )
255244
256245 def getExtendsModifierNames (self , className , componentName ):
257246 return self .ask ('getExtendsModifierNames' , f'{ className } , { componentName } ' )
258247
259248 def getExtendsModifierValue (self , className , extendsName , modifierName ):
260- try :
261- # FIXME: OMPython exception UnboundLocalError exception for 'Modelica.Fluid.Machines.ControlledPump'
262- return self .ask ('getExtendsModifierValue' , f'{ className } , { extendsName } , { modifierName } ' )
263- except pyparsing .ParseException as ex :
264- logger .warning ('OMTypedParser error: %s' , ex .message )
265- result = self .ask ('getExtendsModifierValue' , f'{ className } , { extendsName } , { modifierName } ' , parsed = False )
266- try :
267- answer = OMParser .check_for_values (result )
268- OMParser .result = {}
269- return answer [2 :]
270- except (TypeError , UnboundLocalError ) as ex :
271- logger .warning ('OMParser error: %s' , ex )
272- return result
249+ return self .ask (question = 'getExtendsModifierValue' , opt = f'{ className } , { extendsName } , { modifierName } ' )
273250
274251 def getNthComponentModification (self , className , comp_id ):
275252 # FIXME: OMPython exception Results KeyError exception
@@ -323,7 +300,7 @@ def __init__(self, readonly=False, timeout=10.00,
323300 self ._serverIPAddress = "127.0.0.1"
324301 self ._interactivePort = None
325302 # FIXME: this code is not well written... need to be refactored
326- self ._temp_dir = tempfile .gettempdir ()
303+ self ._temp_dir = pathlib . Path ( tempfile .gettempdir () )
327304 # generate a random string for this session
328305 self ._random_string = uuid .uuid4 ().hex
329306 # omc log file
@@ -348,7 +325,7 @@ def __init__(self, readonly=False, timeout=10.00,
348325 self ._dockerNetwork = dockerNetwork
349326 self ._create_omc_log_file ("port" )
350327 self ._timeout = timeout
351- self ._port_file = os . path . join ("/tmp" if docker else self ._temp_dir , self ._port_file ).replace ( " \\ " , "/" )
328+ self ._port_file = (( pathlib . Path ("/tmp" ) if docker else self ._temp_dir ) / self ._port_file ).as_posix ( )
352329 self ._interactivePort = port
353330 # set omc executable path and args
354331 self ._set_omc_command ([
@@ -364,14 +341,15 @@ def __init__(self, readonly=False, timeout=10.00,
364341 def __del__ (self ):
365342 try :
366343 self .sendExpression ("quit()" )
367- except Exception :
344+ except OMCSessionException :
368345 pass
369346 self ._omc_log_file .close ()
370347 try :
371348 self ._omc_process .wait (timeout = 2.0 )
372- except Exception :
349+ except subprocess . TimeoutExpired :
373350 if self ._omc_process :
374- logger .warning ("OMC did not exit after being sent the quit() command; killing the process with pid=%s" , self ._omc_process .pid )
351+ logger .warning ("OMC did not exit after being sent the quit() command; "
352+ "killing the process with pid=%s" , self ._omc_process .pid )
375353 self ._omc_process .kill ()
376354 self ._omc_process .wait ()
377355
@@ -381,7 +359,7 @@ def _create_omc_log_file(self, suffix):
381359 else :
382360 log_filename = f"openmodelica.{ self ._currentUser } .{ suffix } .{ self ._random_string } .log"
383361 # this file must be closed in the destructor
384- self ._omc_log_file = open (pathlib . Path ( self ._temp_dir ) / log_filename , "w+" )
362+ self ._omc_log_file = open (self ._temp_dir / log_filename , "w+" )
385363
386364 def _start_omc_process (self , timeout ):
387365 if sys .platform == 'win32' :
@@ -401,18 +379,19 @@ def _start_omc_process(self, timeout):
401379 try :
402380 with open (self ._dockerCidFile , "r" ) as fin :
403381 self ._dockerCid = fin .read ().strip ()
404- except Exception :
382+ except IOError :
405383 pass
406384 if self ._dockerCid :
407385 break
408386 time .sleep (timeout / 40.0 )
409387 try :
410388 os .remove (self ._dockerCidFile )
411- except Exception :
389+ except FileNotFoundError :
412390 pass
413391 if self ._dockerCid is None :
414392 logger .error ("Docker did not start. Log-file says:\n %s" % (open (self ._omc_log_file .name ).read ()))
415- raise Exception ("Docker did not start (timeout=%f might be too short especially if you did not docker pull the image before this command)." % timeout )
393+ raise OMCSessionException ("Docker did not start (timeout=%f might be too short especially if you did "
394+ "not docker pull the image before this command)." % timeout )
416395
417396 dockerTop = None
418397 if self ._docker or self ._dockerContainer :
@@ -429,17 +408,16 @@ def _start_omc_process(self, timeout):
429408 try :
430409 self ._omc_process = DummyPopen (int (columns [1 ]))
431410 except psutil .NoSuchProcess :
432- raise Exception (
433- f"Could not find PID { dockerTop } - is this a docker instance spawned without --pid=host? \n "
434- f"Log -file says:\n { open (self ._omc_log_file .name ).read ()} " )
411+ raise OMCSessionException (
412+ f"Could not find PID { dockerTop } - is this a docker instance spawned "
413+ f"without --pid=host? \n Log -file says:\n { open (self ._omc_log_file .name ).read ()} " )
435414 break
436415 if self ._omc_process is not None :
437416 break
438417 time .sleep (timeout / 40.0 )
439418 if self ._omc_process is None :
440-
441- raise Exception ("Docker top did not contain omc process %s:\n %s\n Log-file says:\n %s"
442- % (self ._random_string , dockerTop , open (self ._omc_log_file .name ).read ()))
419+ raise OMCSessionException ("Docker top did not contain omc process %s:\n %s\n Log-file says:\n %s"
420+ % (self ._random_string , dockerTop , open (self ._omc_log_file .name ).read ()))
443421 return self ._omc_process
444422
445423 def _getuid (self ):
@@ -460,7 +438,9 @@ def _set_omc_command(self, omc_path_and_args_list):
460438 if (self ._docker or self ._dockerContainer ) and sys .platform == "win32" :
461439 extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere" ]
462440 if not self ._interactivePort :
463- raise Exception ("docker on Windows requires knowing which port to connect to. For dockerContainer=..., the container needs to have already manually exposed this port when it was started (-p 127.0.0.1:n:n) or you get an error later." )
441+ raise OMCSessionException ("docker on Windows requires knowing which port to connect to. For "
442+ "dockerContainer=..., the container needs to have already manually exposed "
443+ "this port when it was started (-p 127.0.0.1:n:n) or you get an error later." )
464444 else :
465445 extraFlags = []
466446 if self ._docker :
@@ -473,7 +453,7 @@ def _set_omc_command(self, omc_path_and_args_list):
473453 dockerNetworkStr = []
474454 extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere" ]
475455 else :
476- raise Exception ('dockerNetwork was set to %s, but only \" host\" or \" separate\" is allowed' )
456+ raise OMCSessionException ('dockerNetwork was set to %s, but only \" host\" or \" separate\" is allowed' )
477457 self ._dockerCidFile = self ._omc_log_file .name + ".docker.cid"
478458 omcCommand = ["docker" , "run" , "--cidfile" , self ._dockerCidFile , "--rm" , "--env" , "USER=%s" % self ._currentUser , "--user" , str (self ._getuid ())] + self ._dockerExtraArgs + dockerNetworkStr + [self ._docker , self ._dockerOpenModelicaPath ]
479459 elif self ._dockerContainer :
@@ -503,7 +483,7 @@ def _get_omhome(self, omhome: str = None):
503483 if path_to_omc is not None :
504484 return pathlib .Path (path_to_omc ).parents [1 ]
505485
506- raise ValueError ("Cannot find OpenModelica executable, please install from openmodelica.org" )
486+ raise OMCSessionException ("Cannot find OpenModelica executable, please install from openmodelica.org" )
507487
508488 def _get_omc_path (self ) -> pathlib .Path :
509489 return self .omhome / "bin" / "omc"
@@ -516,9 +496,10 @@ def _connect_to_omc(self, timeout):
516496 while True :
517497 if self ._dockerCid :
518498 try :
519- self ._port = subprocess .check_output (["docker" , "exec" , self ._dockerCid , "cat" , self ._port_file ], stderr = subprocess .DEVNULL ).decode ().strip ()
499+ self ._port = subprocess .check_output (["docker" , "exec" , self ._dockerCid , "cat" , self ._port_file ],
500+ stderr = subprocess .DEVNULL ).decode ().strip ()
520501 break
521- except Exception :
502+ except subprocess . CalledProcessError :
522503 pass
523504 else :
524505 if os .path .isfile (self ._port_file ):
@@ -533,7 +514,8 @@ def _connect_to_omc(self, timeout):
533514 name = self ._omc_log_file .name
534515 self ._omc_log_file .close ()
535516 logger .error ("OMC Server did not start. Please start it! Log-file says:\n %s" % open (name ).read ())
536- raise Exception (f"OMC Server did not start (timeout={ timeout } ). Could not open file { self ._port_file } " )
517+ raise OMCSessionException (f"OMC Server did not start (timeout={ timeout } ). "
518+ "Could not open file {self._port_file}" )
537519 time .sleep (timeout / 80.0 )
538520
539521 self ._port = self ._port .replace ("0.0.0.0" , self ._serverIPAddress )
@@ -549,7 +531,7 @@ def _connect_to_omc(self, timeout):
549531 def sendExpression (self , command , parsed = True ):
550532 p = self ._omc_process .poll () # check if process is running
551533 if p is not None :
552- raise Exception ("Process Exited, No connection with OMC. Create a new instance of OMCSessionZMQ" )
534+ raise OMCSessionException ("Process Exited, No connection with OMC. Create a new instance of OMCSessionZMQ! " )
553535
554536 attempts = 0
555537 while True :
@@ -563,7 +545,7 @@ def sendExpression(self, command, parsed=True):
563545 self ._omc_log_file .seek (0 )
564546 log = self ._omc_log_file .read ()
565547 self ._omc_log_file .close ()
566- raise Exception (f"No connection with OMC (timeout={ self ._timeout } ). Log-file says: \n { log } " )
548+ raise OMCSessionException (f"No connection with OMC (timeout={ self ._timeout } ). Log-file says: \n { log } " )
567549 time .sleep (self ._timeout / 50.0 )
568550 if command == "quit()" :
569551 self ._omc .close ()
@@ -572,7 +554,14 @@ def sendExpression(self, command, parsed=True):
572554 else :
573555 result = self ._omc .recv_string ()
574556 if parsed is True :
575- answer = OMTypedParser .parseString (result )
576- return answer
557+ try :
558+ return om_parser_typed (result )
559+ except pyparsing .ParseException as ex :
560+ logger .warning ('OMTypedParser error: %s. Returning the basic parser result.' , ex .msg )
561+ try :
562+ return om_parser_basic (result )
563+ except (TypeError , UnboundLocalError ) as ex :
564+ logger .warning ('OMParser error: %s. Returning the unparsed result.' , ex )
565+ return result
577566 else :
578567 return result
0 commit comments