Skip to content

Commit 132ac41

Browse files
committed
??? compatibility layer
1 parent 4b59ea7 commit 132ac41

4 files changed

Lines changed: 273 additions & 66 deletions

File tree

OMPython/ModelicaSystem.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
OMSessionRunner,
3030
OMCSessionLocal,
3131
OMCSessionException,
32+
33+
OMCProcessLocal,
3234
)
3335

3436
# check OMPathBase usage
@@ -2108,6 +2110,138 @@ class ModelicaSystem(ModelicaSystemOMC):
21082110
Compatibility class.
21092111
"""
21102112

2113+
def __init__(
2114+
self,
2115+
fileName: Optional[str | os.PathLike | pathlib.Path] = None,
2116+
modelName: Optional[str] = None,
2117+
lmodel: Optional[list[str | tuple[str, str]]] = None,
2118+
commandLineOptions: Optional[list[str]] = None,
2119+
variableFilter: Optional[str] = None,
2120+
customBuildDirectory: Optional[str | os.PathLike] = None,
2121+
omhome: Optional[str] = None,
2122+
omc_process: Optional[OMCProcessLocal] = None,
2123+
build: bool = True,
2124+
) -> None:
2125+
super().__init__(
2126+
command_line_options=commandLineOptions,
2127+
work_directory=customBuildDirectory,
2128+
omhome=omhome,
2129+
session=omc_process,
2130+
)
2131+
self.model(
2132+
model_name=modelName,
2133+
model_file=fileName,
2134+
libraries=lmodel,
2135+
variable_filter=variableFilter,
2136+
build=build,
2137+
)
2138+
self._getconn = self._session
2139+
2140+
def setCommandLineOptions(self, commandLineOptions: str):
2141+
super().set_command_line_options(command_line_option=commandLineOptions)
2142+
2143+
def setContinuous( # type: ignore[override]
2144+
self,
2145+
cvals: str | list[str] | dict[str, Any],
2146+
) -> bool:
2147+
if isinstance(cvals, dict):
2148+
return super().setContinuous(**cvals)
2149+
raise ModelicaSystemError("Only dict input supported for setContinuous()")
2150+
2151+
def setParameters( # type: ignore[override]
2152+
self,
2153+
pvals: str | list[str] | dict[str, Any],
2154+
) -> bool:
2155+
if isinstance(pvals, dict):
2156+
return super().setParameters(**pvals)
2157+
raise ModelicaSystemError("Only dict input supported for setParameters()")
2158+
2159+
def setOptimizationOptions( # type: ignore[override]
2160+
self,
2161+
optimizationOptions: str | list[str] | dict[str, Any],
2162+
) -> bool:
2163+
if isinstance(optimizationOptions, dict):
2164+
return super().setOptimizationOptions(**optimizationOptions)
2165+
raise ModelicaSystemError("Only dict input supported for setOptimizationOptions()")
2166+
2167+
def setInputs( # type: ignore[override]
2168+
self,
2169+
name: str | list[str] | dict[str, Any],
2170+
) -> bool:
2171+
if isinstance(name, dict):
2172+
return super().setInputs(**name)
2173+
raise ModelicaSystemError("Only dict input supported for setInputs()")
2174+
2175+
def setSimulationOptions( # type: ignore[override]
2176+
self,
2177+
simOptions: str | list[str] | dict[str, Any],
2178+
) -> bool:
2179+
if isinstance(simOptions, dict):
2180+
return super().setSimulationOptions(**simOptions)
2181+
raise ModelicaSystemError("Only dict input supported for setSimulationOptions()")
2182+
2183+
def setLinearizationOptions( # type: ignore[override]
2184+
self,
2185+
linearizationOptions: str | list[str] | dict[str, Any],
2186+
) -> bool:
2187+
if isinstance(linearizationOptions, dict):
2188+
return super().setLinearizationOptions(**linearizationOptions)
2189+
raise ModelicaSystemError("Only dict input supported for setLinearizationOptions()")
2190+
2191+
def getContinuous(
2192+
self,
2193+
names: Optional[str | list[str]] = None,
2194+
):
2195+
retval = super().getContinuous(names=names)
2196+
if self._simulated:
2197+
return retval
2198+
2199+
if isinstance(retval, dict):
2200+
retval2: dict = {}
2201+
for key, val in retval.items():
2202+
if np.isnan(val):
2203+
retval2[key] = None
2204+
else:
2205+
retval2[key] = str(val)
2206+
return retval2
2207+
if isinstance(retval, list):
2208+
retval3: list[str | None] = []
2209+
for val in retval:
2210+
if np.isnan(val):
2211+
retval3.append(None)
2212+
else:
2213+
retval3.append(str(val))
2214+
return retval3
2215+
2216+
raise ModelExecutionException("Invalid data!")
2217+
2218+
def getOutputs(
2219+
self,
2220+
names: Optional[str | list[str]] = None,
2221+
):
2222+
retval = super().getOutputs(names=names)
2223+
if self._simulated:
2224+
return retval
2225+
2226+
if isinstance(retval, dict):
2227+
retval2: dict = {}
2228+
for key, val in retval.items():
2229+
if np.isnan(val):
2230+
retval2[key] = None
2231+
else:
2232+
retval2[key] = str(val)
2233+
return retval2
2234+
if isinstance(retval, list):
2235+
retval3: list[str | None] = []
2236+
for val in retval:
2237+
if np.isnan(val):
2238+
retval3.append(None)
2239+
else:
2240+
retval3.append(str(val))
2241+
return retval3
2242+
2243+
raise ModelExecutionException("Invalid data!")
2244+
21112245

21122246
class ModelicaDoEABC(metaclass=abc.ABCMeta):
21132247
"""
@@ -2680,3 +2814,47 @@ def _prepare_structure_parameters(
26802814
"pre-compiled binary of model.")
26812815

26822816
return {}
2817+
2818+
2819+
class ModelicaSystemCmd(ModelExecutionCmd):
2820+
def __init__(
2821+
self,
2822+
runpath: pathlib.Path,
2823+
modelname: str,
2824+
timeout: float = 10.0,
2825+
) -> None:
2826+
super().__init__(
2827+
runpath=runpath,
2828+
timeout=timeout,
2829+
cmd_prefix=[],
2830+
model_name=modelname,
2831+
)
2832+
2833+
def get_exe(self) -> pathlib.Path:
2834+
"""Get the path to the compiled model executable."""
2835+
import platform
2836+
2837+
path_run = pathlib.Path(self._runpath)
2838+
if platform.system() == "Windows":
2839+
path_exe = path_run / f"{self._model_name}.exe"
2840+
else:
2841+
path_exe = path_run / self._model_name
2842+
2843+
if not path_exe.exists():
2844+
raise ModelicaSystemError(f"Application file path not found: {path_exe}")
2845+
2846+
return path_exe
2847+
2848+
def get_cmd(self) -> list:
2849+
"""Get a list with the path to the executable and all command line args.
2850+
2851+
This can later be used as an argument for subprocess.run().
2852+
"""
2853+
2854+
cmdl = [self.get_exe().as_posix()] + self.get_cmd_args()
2855+
2856+
return cmdl
2857+
2858+
def run(self):
2859+
cmd_definition = self.definition()
2860+
return cmd_definition.run()

OMPython/OMCSession.py

Lines changed: 83 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class OMCSessionCmd:
7171
Implementation of Open Modelica Compiler API functions. Depreciated!
7272
"""
7373

74-
def __init__(self, session: OMCSessionABC, readonly: bool = False):
75-
if not isinstance(session, OMCSessionABC):
74+
def __init__(self, session: OMSessionABC, readonly: bool = False):
75+
if not isinstance(session, OMSessionABC):
7676
raise OMCSessionException("Invalid OMC process definition!")
7777
self._session = session
7878
self._readonly = readonly
@@ -629,70 +629,6 @@ def run(self) -> int:
629629
return returncode
630630

631631

632-
# TODO: OMCSessionCMd => separate file; based on OMCSessionZMQ?
633-
634-
class OMCSessionZMQ:
635-
"""
636-
This class is a compatibility layer for the new schema using OMCSession* classes.
637-
"""
638-
639-
def __init__(
640-
self,
641-
timeout: float = 10.00,
642-
omhome: Optional[str] = None,
643-
omc_process: Optional[OMCSessionABC] = None,
644-
) -> None:
645-
"""
646-
Initialisation for OMCSessionZMQ
647-
"""
648-
warnings.warn(message="The class OMCSessionZMQ is depreciated and will be removed in future versions; "
649-
"please use OMCProcess* classes instead!",
650-
category=DeprecationWarning,
651-
stacklevel=2)
652-
653-
if omc_process is None:
654-
omc_process = OMCSessionLocal(omhome=omhome, timeout=timeout)
655-
elif not isinstance(omc_process, OMCSessionABC):
656-
raise OMCSessionException("Invalid definition of the OMC process!")
657-
self.omc_process = omc_process
658-
659-
def __del__(self):
660-
if hasattr(self, 'omc_process'):
661-
del self.omc_process
662-
663-
@staticmethod
664-
def escape_str(value: str) -> str:
665-
"""
666-
Escape a string such that it can be used as string within OMC expressions, i.e. escape all double quotes.
667-
"""
668-
return OMCSessionABC.escape_str(value=value)
669-
670-
def omcpath(self, *path) -> OMPathABC:
671-
"""
672-
Create an OMCPath object based on the given path segments and the current OMC process definition.
673-
"""
674-
return self.omc_process.omcpath(*path)
675-
676-
def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC:
677-
"""
678-
Get a temporary directory using OMC. It is our own implementation as non-local usage relies on OMC to run all
679-
filesystem related access.
680-
"""
681-
return self.omc_process.omcpath_tempdir(tempdir_base=tempdir_base)
682-
683-
def execute(self, command: str):
684-
return self.omc_process.execute(command=command)
685-
686-
def sendExpression(self, command: str, parsed: bool = True) -> Any:
687-
"""
688-
Send an expression to the OMC server and return the result.
689-
690-
The complete error handling of the OMC result is done within this method using '"getMessagesStringInternal()'.
691-
Caller should only check for OMCSessionException.
692-
"""
693-
return self.omc_process.sendExpression(command=command, parsed=parsed)
694-
695-
696632
class PostInitCaller(type):
697633
"""
698634
Metaclass definition to define a new function __post_init__() which is called after all __init__() functions where
@@ -1310,6 +1246,79 @@ def _omc_port_get(self) -> str:
13101246
return port
13111247

13121248

1249+
# TODO: OMCSessionCMd => separate file; based on OMCSessionZMQ?
1250+
class OMCSessionZMQ(OMSessionABC):
1251+
"""
1252+
This class is a compatibility layer for the new schema using OMCSession* classes.
1253+
"""
1254+
1255+
def __init__(
1256+
self,
1257+
timeout: float = 10.00,
1258+
omhome: Optional[str] = None,
1259+
omc_process: Optional[OMCSessionABC] = None,
1260+
) -> None:
1261+
"""
1262+
Initialisation for OMCSessionZMQ
1263+
"""
1264+
super().__init__(timeout=timeout)
1265+
warnings.warn(message="The class OMCSessionZMQ is depreciated and will be removed in future versions; "
1266+
"please use OMCProcess* classes instead!",
1267+
category=DeprecationWarning,
1268+
stacklevel=2)
1269+
1270+
if omc_process is None:
1271+
omc_process = OMCSessionLocal(omhome=omhome, timeout=timeout)
1272+
elif not isinstance(omc_process, OMCSessionABC):
1273+
raise OMCSessionException("Invalid definition of the OMC process!")
1274+
self.omc_process = omc_process
1275+
1276+
def __del__(self):
1277+
if hasattr(self, 'omc_process'):
1278+
del self.omc_process
1279+
1280+
@staticmethod
1281+
def escape_str(value: str) -> str:
1282+
"""
1283+
Escape a string such that it can be used as string within OMC expressions, i.e. escape all double quotes.
1284+
"""
1285+
return OMCSessionABC.escape_str(value=value)
1286+
1287+
def omcpath(self, *path) -> OMPathABC:
1288+
"""
1289+
Create an OMCPath object based on the given path segments and the current OMC process definition.
1290+
"""
1291+
return self.omc_process.omcpath(*path)
1292+
1293+
def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC:
1294+
"""
1295+
Get a temporary directory using OMC. It is our own implementation as non-local usage relies on OMC to run all
1296+
filesystem related access.
1297+
"""
1298+
return self.omc_process.omcpath_tempdir(tempdir_base=tempdir_base)
1299+
1300+
def execute(self, command: str):
1301+
return self.omc_process.execute(command=command)
1302+
1303+
def sendExpression(self, command: str, parsed: bool = True) -> Any:
1304+
"""
1305+
Send an expression to the OMC server and return the result.
1306+
1307+
The complete error handling of the OMC result is done within this method using '"getMessagesStringInternal()'.
1308+
Caller should only check for OMCSessionException.
1309+
"""
1310+
return self.omc_process.sendExpression(command=command, parsed=parsed)
1311+
1312+
def get_version(self) -> str:
1313+
return self.omc_process.get_version()
1314+
1315+
def model_execution_prefix(self, cwd: Optional[OMPathABC] = None) -> list[str]:
1316+
return self.omc_process.model_execution_prefix(cwd=cwd)
1317+
1318+
def set_workdir(self, workdir: OMPathABC) -> None:
1319+
return self.omc_process.set_workdir(workdir=workdir)
1320+
1321+
13131322
class OMCSessionDockerABC(OMCSessionABC, metaclass=abc.ABCMeta):
13141323
"""
13151324
Base class for OMCSession implementations which run the OMC server in a Docker container.
@@ -2159,3 +2168,11 @@ def omcpath_tempdir(self, tempdir_base: Optional[OMPathABC] = None) -> OMPathABC
21592168

21602169
def sendExpression(self, command: str, parsed: bool = True) -> Any:
21612170
raise OMCSessionException(f"{self.__class__.__name__} does not uses an OMC server!")
2171+
2172+
2173+
DummyPopen = DockerPopen
2174+
OMCProcessLocal = OMCSessionLocal
2175+
OMCProcessPort = OMCSessionPort
2176+
OMCProcessDocker = OMCSessionDocker
2177+
OMCProcessDockerContainer = OMCSessionDockerContainer
2178+
OMCProcessWSL = OMCSessionWSL

OMPython/OMTypedParser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,6 @@ def om_parser_typed(string) -> Any:
161161
if len(res) == 0:
162162
return None
163163
return res[0]
164+
165+
166+
parseString = om_parser_typed

0 commit comments

Comments
 (0)