Skip to content

Commit c57b8bc

Browse files
authored
[OMCSession*] Cleanup / mypy check (#291)
* [DummyPopen] remove redundant parentheses * [OMCSession*] move logging into OMCSessionZMQ.sendExpression() * [OMCSessionZMQ] fix f-string * [OMCSessionZMQ] layout fix based on PyCharm warnings * [OMCSessionZMQ] rename omhome => _omhome * [OMCSessionZMQ] update _create_omc_log_file() * [OMCSessionZMQ] remove fixme - check source of this line * [OMCSessionZMQ] simplify _port_file * [OMCSessionZMQ] simplify _connect_to_omc() / _port * [OMCSessionZMQ] cleanup self._start_omc_process() * [OMCSessionZMQ] cleanup self._set_omc_command() * [OMCSession*] fix mypy warnings
1 parent c912116 commit c57b8bc

File tree

1 file changed

+81
-62
lines changed

1 file changed

+81
-62
lines changed

OMPython/OMCSession.py

Lines changed: 81 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
import sys
4949
import tempfile
5050
import time
51-
from typing import Optional
51+
from typing import Any, Optional
5252
import uuid
5353
import warnings
5454
import zmq
@@ -57,12 +57,11 @@
5757
from OMPython.OMTypedParser import parseString as om_parser_typed
5858
from OMPython.OMParser import om_parser_basic
5959

60-
6160
# define logger using the current module name as ID
6261
logger = logging.getLogger(__name__)
6362

6463

65-
class DummyPopen():
64+
class DummyPopen:
6665
def __init__(self, pid):
6766
self.pid = pid
6867
self.process = psutil.Process(pid)
@@ -84,14 +83,14 @@ class OMCSessionException(Exception):
8483

8584
class OMCSessionCmd:
8685

87-
def __init__(self, session: OMCSessionZMQ, readonly: Optional[bool] = False):
86+
def __init__(self, session: OMCSessionZMQ, readonly: bool = False):
8887
if not isinstance(session, OMCSessionZMQ):
8988
raise OMCSessionException("Invalid session definition!")
9089
self._session = session
9190
self._readonly = readonly
92-
self._omc_cache = {}
91+
self._omc_cache: dict[tuple[str, bool], Any] = {}
9392

94-
def _ask(self, question: str, opt: Optional[list[str]] = None, parsed: Optional[bool] = True):
93+
def _ask(self, question: str, opt: Optional[list[str]] = None, parsed: bool = True):
9594

9695
if opt is None:
9796
expression = question
@@ -107,8 +106,6 @@ def _ask(self, question: str, opt: Optional[list[str]] = None, parsed: Optional[
107106
if p in self._omc_cache:
108107
return self._omc_cache[p]
109108

110-
logger.debug('OMC ask: %s (parsed=%s)', expression, parsed)
111-
112109
try:
113110
res = self._session.sendExpression(expression, parsed=parsed)
114111
except OMCSessionException as ex:
@@ -273,26 +270,29 @@ def getClassNames(self, className=None, recursive=False, qualified=False, sort=F
273270

274271
class OMCSessionZMQ:
275272

276-
def __init__(self, timeout=10.00,
277-
docker=None, dockerContainer=None, dockerExtraArgs=None, dockerOpenModelicaPath="omc",
278-
dockerNetwork=None, port=None, omhome: str = None):
273+
def __init__(self,
274+
timeout: float = 10.00,
275+
docker: Optional[str] = None,
276+
dockerContainer: Optional[int] = None,
277+
dockerExtraArgs: Optional[list] = None,
278+
dockerOpenModelicaPath: str = "omc",
279+
dockerNetwork: Optional[str] = None,
280+
port: Optional[int] = None,
281+
omhome: Optional[str] = None):
279282
if dockerExtraArgs is None:
280283
dockerExtraArgs = []
281284

282-
self.omhome = self._get_omhome(omhome=omhome)
285+
self._omhome = self._get_omhome(omhome=omhome)
283286

284287
self._omc_process = None
285288
self._omc_command = None
286-
self._omc = None
287-
self._dockerCid = None
289+
self._omc: Optional[Any] = None
290+
self._dockerCid: Optional[int] = None
288291
self._serverIPAddress = "127.0.0.1"
289292
self._interactivePort = None
290-
# FIXME: this code is not well written... need to be refactored
291293
self._temp_dir = pathlib.Path(tempfile.gettempdir())
292294
# generate a random string for this session
293295
self._random_string = uuid.uuid4().hex
294-
# omc log file
295-
self._omc_log_file = None
296296
try:
297297
self._currentUser = getpass.getuser()
298298
if not self._currentUser:
@@ -301,30 +301,28 @@ def __init__(self, timeout=10.00,
301301
# We are running as a uid not existing in the password database... Pretend we are nobody
302302
self._currentUser = "nobody"
303303

304-
# Locating and using the IOR
305-
if sys.platform != 'win32' or docker or dockerContainer:
306-
self._port_file = "openmodelica." + self._currentUser + ".port." + self._random_string
307-
else:
308-
self._port_file = "openmodelica.port." + self._random_string
309304
self._docker = docker
310305
self._dockerContainer = dockerContainer
311306
self._dockerExtraArgs = dockerExtraArgs
312307
self._dockerOpenModelicaPath = dockerOpenModelicaPath
313308
self._dockerNetwork = dockerNetwork
314-
self._create_omc_log_file("port")
309+
self._omc_log_file = self._create_omc_log_file("port")
315310
self._timeout = timeout
316-
self._port_file = ((pathlib.Path("/tmp") if docker else self._temp_dir) / self._port_file).as_posix()
311+
# Locating and using the IOR
312+
if sys.platform != 'win32' or docker or dockerContainer:
313+
port_file = "openmodelica." + self._currentUser + ".port." + self._random_string
314+
else:
315+
port_file = "openmodelica.port." + self._random_string
316+
self._port_file = ((pathlib.Path("/tmp") if docker else self._temp_dir) / port_file).as_posix()
317317
self._interactivePort = port
318318
# set omc executable path and args
319-
self._set_omc_command([
320-
"--interactive=zmq",
321-
"--locale=C",
322-
f"-z={self._random_string}"
323-
])
319+
self._omc_command = self._set_omc_command(omc_path_and_args_list=["--interactive=zmq",
320+
"--locale=C",
321+
f"-z={self._random_string}"])
324322
# start up omc executable, which is waiting for the ZMQ connection
325-
self._start_omc_process(timeout)
323+
self._omc_process = self._start_omc_process(timeout)
326324
# connect to the running omc instance using ZMQ
327-
self._connect_to_omc(timeout)
325+
self._omc_port = self._connect_to_omc(timeout)
328326

329327
self._re_log_entries = None
330328
self._re_log_raw = None
@@ -344,27 +342,29 @@ def __del__(self):
344342
self._omc_process.kill()
345343
self._omc_process.wait()
346344

347-
def _create_omc_log_file(self, suffix):
345+
def _create_omc_log_file(self, suffix): # output?
348346
if sys.platform == 'win32':
349347
log_filename = f"openmodelica.{suffix}.{self._random_string}.log"
350348
else:
351349
log_filename = f"openmodelica.{self._currentUser}.{suffix}.{self._random_string}.log"
352350
# this file must be closed in the destructor
353-
self._omc_log_file = open(self._temp_dir / log_filename, "w+")
351+
omc_log_file = open(self._temp_dir / log_filename, "w+")
352+
353+
return omc_log_file
354354

355-
def _start_omc_process(self, timeout):
355+
def _start_omc_process(self, timeout): # output?
356356
if sys.platform == 'win32':
357-
omhome_bin = (self.omhome / "bin").as_posix()
357+
omhome_bin = (self._omhome / "bin").as_posix()
358358
my_env = os.environ.copy()
359359
my_env["PATH"] = omhome_bin + os.pathsep + my_env["PATH"]
360-
self._omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
361-
stderr=self._omc_log_file, env=my_env)
360+
omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
361+
stderr=self._omc_log_file, env=my_env)
362362
else:
363363
# set the user environment variable so omc running from wsgi has the same user as OMPython
364364
my_env = os.environ.copy()
365365
my_env["USER"] = self._currentUser
366-
self._omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
367-
stderr=self._omc_log_file, env=my_env)
366+
omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
367+
stderr=self._omc_log_file, env=my_env)
368368
if self._docker:
369369
for i in range(0, 40):
370370
try:
@@ -387,29 +387,30 @@ def _start_omc_process(self, timeout):
387387
dockerTop = None
388388
if self._docker or self._dockerContainer:
389389
if self._dockerNetwork == "separate":
390-
self._serverIPAddress = json.loads(subprocess.check_output(["docker", "inspect", self._dockerCid]).decode().strip())[0]["NetworkSettings"]["IPAddress"]
390+
output = subprocess.check_output(["docker", "inspect", self._dockerCid]).decode().strip()
391+
self._serverIPAddress = json.loads(output)[0]["NetworkSettings"]["IPAddress"]
391392
for i in range(0, 40):
392393
if sys.platform == 'win32':
393394
break
394395
dockerTop = subprocess.check_output(["docker", "top", self._dockerCid]).decode().strip()
395-
self._omc_process = None
396+
omc_process = None
396397
for line in dockerTop.split("\n"):
397398
columns = line.split()
398399
if self._random_string in line:
399400
try:
400-
self._omc_process = DummyPopen(int(columns[1]))
401+
omc_process = DummyPopen(int(columns[1]))
401402
except psutil.NoSuchProcess:
402403
raise OMCSessionException(
403404
f"Could not find PID {dockerTop} - is this a docker instance spawned "
404405
f"without --pid=host?\nLog-file says:\n{open(self._omc_log_file.name).read()}")
405406
break
406-
if self._omc_process is not None:
407+
if omc_process is not None:
407408
break
408409
time.sleep(timeout / 40.0)
409-
if self._omc_process is None:
410+
if omc_process is None:
410411
raise OMCSessionException("Docker top did not contain omc process %s:\n%s\nLog-file says:\n%s"
411412
% (self._random_string, dockerTop, open(self._omc_log_file.name).read()))
412-
return self._omc_process
413+
return omc_process
413414

414415
def _getuid(self):
415416
"""
@@ -419,7 +420,7 @@ def _getuid(self):
419420
"""
420421
return 1000 if sys.platform == 'win32' else os.getuid()
421422

422-
def _set_omc_command(self, omc_path_and_args_list):
423+
def _set_omc_command(self, omc_path_and_args_list) -> list:
423424
"""Define the command that will be called by the subprocess module.
424425
425426
On Windows, use the list input style of the subprocess module to
@@ -446,20 +447,31 @@ def _set_omc_command(self, omc_path_and_args_list):
446447
else:
447448
raise OMCSessionException('dockerNetwork was set to %s, but only \"host\" or \"separate\" is allowed')
448449
self._dockerCidFile = self._omc_log_file.name + ".docker.cid"
449-
omcCommand = ["docker", "run", "--cidfile", self._dockerCidFile, "--rm", "--env", "USER=%s" % self._currentUser, "--user", str(self._getuid())] + self._dockerExtraArgs + dockerNetworkStr + [self._docker, self._dockerOpenModelicaPath]
450+
omcCommand = (["docker", "run",
451+
"--cidfile", self._dockerCidFile,
452+
"--rm",
453+
"--env", "USER=%s" % self._currentUser,
454+
"--user", str(self._getuid())]
455+
+ self._dockerExtraArgs
456+
+ dockerNetworkStr
457+
+ [self._docker, self._dockerOpenModelicaPath])
450458
elif self._dockerContainer:
451-
omcCommand = ["docker", "exec", "--env", "USER=%s" % self._currentUser, "--user", str(self._getuid())] + self._dockerExtraArgs + [self._dockerContainer, self._dockerOpenModelicaPath]
459+
omcCommand = (["docker", "exec",
460+
"--env", "USER=%s" % self._currentUser,
461+
"--user", str(self._getuid())]
462+
+ self._dockerExtraArgs
463+
+ [self._dockerContainer, self._dockerOpenModelicaPath])
452464
self._dockerCid = self._dockerContainer
453465
else:
454466
omcCommand = [str(self._get_omc_path())]
455467
if self._interactivePort:
456468
extraFlags = extraFlags + ["--interactivePort=%d" % int(self._interactivePort)]
457469

458-
self._omc_command = omcCommand + omc_path_and_args_list + extraFlags
470+
omc_command = omcCommand + omc_path_and_args_list + extraFlags
459471

460-
return self._omc_command
472+
return omc_command
461473

462-
def _get_omhome(self, omhome: str = None):
474+
def _get_omhome(self, omhome: Optional[str] = None):
463475
# use the provided path
464476
if omhome is not None:
465477
return pathlib.Path(omhome)
@@ -477,26 +489,28 @@ def _get_omhome(self, omhome: str = None):
477489
raise OMCSessionException("Cannot find OpenModelica executable, please install from openmodelica.org")
478490

479491
def _get_omc_path(self) -> pathlib.Path:
480-
return self.omhome / "bin" / "omc"
492+
return self._omhome / "bin" / "omc"
481493

482-
def _connect_to_omc(self, timeout):
483-
self._omc_zeromq_uri = "file:///" + self._port_file
494+
def _connect_to_omc(self, timeout) -> str:
495+
omc_zeromq_uri = "file:///" + self._port_file
484496
# See if the omc server is running
485497
attempts = 0
486-
self._port = None
498+
port = None
487499
while True:
488500
if self._dockerCid:
489501
try:
490-
self._port = subprocess.check_output(["docker", "exec", self._dockerCid, "cat", self._port_file],
491-
stderr=subprocess.DEVNULL).decode().strip()
502+
port = subprocess.check_output(args=["docker",
503+
"exec", str(self._dockerCid),
504+
"cat", str(self._port_file)],
505+
stderr=subprocess.DEVNULL).decode().strip()
492506
break
493507
except subprocess.CalledProcessError:
494508
pass
495509
else:
496510
if os.path.isfile(self._port_file):
497511
# Read the port file
498512
with open(self._port_file, 'r') as f_p:
499-
self._port = f_p.readline()
513+
port = f_p.readline()
500514
os.remove(self._port_file)
501515
break
502516

@@ -506,18 +520,21 @@ def _connect_to_omc(self, timeout):
506520
self._omc_log_file.close()
507521
logger.error("OMC Server did not start. Please start it! Log-file says:\n%s" % open(name).read())
508522
raise OMCSessionException(f"OMC Server did not start (timeout={timeout}). "
509-
"Could not open file {self._port_file}")
523+
f"Could not open file {self._port_file}")
510524
time.sleep(timeout / 80.0)
511525

512-
self._port = self._port.replace("0.0.0.0", self._serverIPAddress)
513-
logger.info(f"OMC Server is up and running at {self._omc_zeromq_uri} pid={self._omc_process.pid} cid={self._dockerCid}")
526+
port = port.replace("0.0.0.0", self._serverIPAddress)
527+
logger.info(f"OMC Server is up and running at {omc_zeromq_uri} "
528+
f"pid={self._omc_process.pid if self._omc_process else '?'} cid={self._dockerCid}")
514529

515530
# Create the ZeroMQ socket and connect to OMC server
516531
context = zmq.Context.instance()
517532
self._omc = context.socket(zmq.REQ)
518533
self._omc.setsockopt(zmq.LINGER, 0) # Dismisses pending messages if closed
519534
self._omc.setsockopt(zmq.IMMEDIATE, True) # Queue messages only to completed connections
520-
self._omc.connect(self._port)
535+
self._omc.connect(port)
536+
537+
return port
521538

522539
def execute(self, command):
523540
warnings.warn("This function is depreciated and will be removed in future versions; "
@@ -533,6 +550,8 @@ def sendExpression(self, command, parsed=True):
533550
if self._omc is None:
534551
raise OMCSessionException("No OMC running. Create a new instance of OMCSessionZMQ!")
535552

553+
logger.debug("sendExpression(%r, parsed=%r)", command, parsed)
554+
536555
attempts = 0
537556
while True:
538557
try:

0 commit comments

Comments
 (0)