|
41 | 41 | import os
|
42 | 42 | import pathlib
|
43 | 43 | import psutil
|
| 44 | +import re |
44 | 45 | import signal
|
45 | 46 | import subprocess
|
46 | 47 | import sys
|
@@ -325,6 +326,9 @@ def __init__(self, timeout=10.00,
|
325 | 326 | # connect to the running omc instance using ZMQ
|
326 | 327 | self._connect_to_omc(timeout)
|
327 | 328 |
|
| 329 | + self._re_log_entries = None |
| 330 | + self._re_log_raw = None |
| 331 | + |
328 | 332 | def __del__(self):
|
329 | 333 | try:
|
330 | 334 | self.sendExpression("quit()")
|
@@ -550,15 +554,60 @@ def sendExpression(self, command, parsed=True):
|
550 | 554 | else:
|
551 | 555 | result = self._omc.recv_string()
|
552 | 556 |
|
553 |
| - # allways check for error |
554 |
| - self._omc.send_string("getErrorString()", flags=zmq.NOBLOCK) |
555 |
| - error_raw = self._omc.recv_string() |
556 |
| - error_str = om_parser_typed(error_raw) |
557 |
| - if error_str: |
558 |
| - if "Error" in error_str: |
559 |
| - raise OMCSessionException(f"OM Error for 'sendExpression({command}, {parsed})': {error_str}") |
560 |
| - else: |
561 |
| - logger.warning(f"[OM]: {error_str}") |
| 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; parsig 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) |
562 | 611 |
|
563 | 612 | if parsed is True:
|
564 | 613 | try:
|
|
0 commit comments