Skip to content

Commit cda6d1c

Browse files
committed
[ModelicaSystem] add type hints for set*() functions and rename arguments
* fix some type hint issues in setInput() * prepare for definition via dictionary replacing 'a=b' and '[a=b, c=d]' style
1 parent 5394e94 commit cda6d1c

1 file changed

Lines changed: 106 additions & 57 deletions

File tree

OMPython/ModelicaSystem.py

Lines changed: 106 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,106 +1001,149 @@ def _strip_space(name):
10011001

10021002
raise ModelicaSystemError("Unhandled input for strip_space()")
10031003

1004-
def setMethodHelper(self, args1, args2, args3, args4=None):
1004+
def setMethodHelper(
1005+
self,
1006+
inputdata: str | list[str] | dict[str, str | int | float],
1007+
classdata: dict[str, Any],
1008+
datatype: str,
1009+
overwritedata: Optional[dict[str, str]] = None,
1010+
) -> bool:
10051011
"""
10061012
Helper function for setParameter(),setContinuous(),setSimulationOptions(),setLinearizationOption(),setOptimizationOption()
1013+
10071014
args1 - string or list of string given by user
10081015
args2 - dict() containing the values of different variables(eg:, parameter,continuous,simulation parameters)
10091016
args3 - function name (eg; continuous, parameter, simulation, linearization,optimization)
10101017
args4 - dict() which stores the new override variables list,
10111018
"""
1012-
def apply_single(args1):
1013-
args1 = self._strip_space(args1)
1014-
value = args1.split("=")
1015-
if value[0] in args2:
1016-
if args3 == "parameter" and self.isParameterChangeable(value[0], value[1]):
1017-
args2[value[0]] = value[1]
1018-
if args4 is not None:
1019-
args4[value[0]] = value[1]
1020-
elif args3 != "parameter":
1021-
args2[value[0]] = value[1]
1022-
if args4 is not None:
1023-
args4[value[0]] = value[1]
1019+
1020+
# TODO: cleanup / data handling / ...
1021+
# (1) args1: Optional[str | list[str]] -> convert to dict
1022+
# (2) work on dict! inputs: dict[str, str | int | float | ?numbers.number?]
1023+
# (3) handle function
1024+
# (4) use it also for other functions with such an input, i.e. 'key=value' | ['key=value']
1025+
# (5) include setInputs()
1026+
1027+
def apply_single(key_val: str):
1028+
key_val_list = key_val.split("=")
1029+
if len(key_val_list) != 2:
1030+
raise ModelicaSystemError(f"Invalid key = value pair: {key_val}")
1031+
1032+
name = self._strip_space(key_val_list[0])
1033+
value = self._strip_space(key_val_list[1])
1034+
1035+
if name in classdata:
1036+
if datatype == "parameter" and not self.isParameterChangeable(name):
1037+
logger.debug(f"It is not possible to set the parameter {repr(name)}. It seems to be "
1038+
"structural, final, protected, evaluated or has a non-constant binding. "
1039+
"Use sendExpression(...) and rebuild the model using buildModel() API; example: "
1040+
"sendExpression(\"setParameterValue("
1041+
f"{self.modelName}, {name}, {value if value is not None else '<?value?>'}"
1042+
")\") ")
1043+
return False
1044+
1045+
classdata[name] = value
1046+
if overwritedata is not None:
1047+
overwritedata[name] = value
10241048

10251049
return True
10261050

10271051
else:
10281052
raise ModelicaSystemError("Unhandled case in setMethodHelper.apply_single() - "
1029-
f"{repr(value[0])} is not a {repr(args3)} variable")
1053+
f"{repr(name)} is not a {repr(datatype)} variable")
10301054

10311055
result = []
1032-
if isinstance(args1, str):
1033-
result = [apply_single(args1)]
1056+
if isinstance(inputdata, str):
1057+
result = [apply_single(inputdata)]
10341058

1035-
elif isinstance(args1, list):
1059+
elif isinstance(inputdata, list):
10361060
result = []
1037-
args1 = self._strip_space(args1)
1038-
for var in args1:
1061+
inputdata = self._strip_space(inputdata)
1062+
for var in inputdata:
10391063
result.append(apply_single(var))
10401064

10411065
return all(result)
10421066

1043-
def setContinuous(self, cvals): # 13
1067+
def isParameterChangeable(
1068+
self,
1069+
name: str,
1070+
):
1071+
q = self.getQuantities(name)
1072+
if q[0]["changeable"] == "false":
1073+
return False
1074+
return True
1075+
1076+
def setContinuous(self, cvals: str | list[str] | dict[str, str | int | float]) -> bool:
10441077
"""
10451078
This method is used to set continuous values. It can be called:
10461079
with a sequence of continuous name and assigning corresponding values as arguments as show in the example below:
10471080
usage
10481081
>>> setContinuous("Name=value")
10491082
>>> setContinuous(["Name1=value1","Name2=value2"])
10501083
"""
1051-
return self.setMethodHelper(cvals, self.continuouslist, "continuous", self.overridevariables)
1084+
return self.setMethodHelper(
1085+
inputdata=cvals,
1086+
classdata=self.continuouslist,
1087+
datatype="continuous",
1088+
overwritedata=self.overridevariables)
10521089

1053-
def setParameters(self, pvals): # 14
1090+
def setParameters(self, pvals: str | list[str] | dict[str, str | int | float]) -> bool:
10541091
"""
10551092
This method is used to set parameter values. It can be called:
10561093
with a sequence of parameter name and assigning corresponding value as arguments as show in the example below:
10571094
usage
10581095
>>> setParameters("Name=value")
10591096
>>> setParameters(["Name1=value1","Name2=value2"])
10601097
"""
1061-
return self.setMethodHelper(pvals, self.paramlist, "parameter", self.overridevariables)
1062-
1063-
def isParameterChangeable(self, name, value):
1064-
q = self.getQuantities(name)
1065-
if q[0]["changeable"] == "false":
1066-
logger.debug(f"setParameters() failed : It is not possible to set the following signal {repr(name)}. "
1067-
"It seems to be structural, final, protected or evaluated or has a non-constant binding, "
1068-
f"use sendExpression(\"setParameterValue({self.modelName}, {name}, {value})\") "
1069-
"and rebuild the model using buildModel() API")
1070-
return False
1071-
return True
1098+
return self.setMethodHelper(
1099+
inputdata=pvals,
1100+
classdata=self.paramlist,
1101+
datatype="parameter",
1102+
overwritedata=self.overridevariables)
10721103

1073-
def setSimulationOptions(self, simOptions): # 16
1104+
def setSimulationOptions(self, simOptions: str | list[str] | dict[str, str | int | float]) -> bool:
10741105
"""
10751106
This method is used to set simulation options. It can be called:
10761107
with a sequence of simulation options name and assigning corresponding values as arguments as show in the example below:
10771108
usage
10781109
>>> setSimulationOptions("Name=value")
10791110
>>> setSimulationOptions(["Name1=value1","Name2=value2"])
10801111
"""
1081-
return self.setMethodHelper(simOptions, self.simulateOptions, "simulation-option", self.simoptionsoverride)
1112+
return self.setMethodHelper(
1113+
inputdata=simOptions,
1114+
classdata=self.simulateOptions,
1115+
datatype="simulation-option",
1116+
overwritedata=self.simoptionsoverride)
10821117

1083-
def setLinearizationOptions(self, linearizationOptions): # 18
1118+
def setLinearizationOptions(self, linearizationOptions: str | list[str] | dict[str, str | int | float]) -> bool:
10841119
"""
10851120
This method is used to set linearization options. It can be called:
10861121
with a sequence of linearization options name and assigning corresponding value as arguments as show in the example below
10871122
usage
10881123
>>> setLinearizationOptions("Name=value")
10891124
>>> setLinearizationOptions(["Name1=value1","Name2=value2"])
10901125
"""
1091-
return self.setMethodHelper(linearizationOptions, self.linearOptions, "Linearization-option", None)
1126+
return self.setMethodHelper(
1127+
inputdata=linearizationOptions,
1128+
classdata=self.linearOptions,
1129+
datatype="Linearization-option",
1130+
overwritedata=None)
10921131

1093-
def setOptimizationOptions(self, optimizationOptions): # 17
1132+
def setOptimizationOptions(self, optimizationOptions: str | list[str] | dict[str, str | int | float]) -> bool:
10941133
"""
10951134
This method is used to set optimization options. It can be called:
10961135
with a sequence of optimization options name and assigning corresponding values as arguments as show in the example below:
10971136
usage
10981137
>>> setOptimizationOptions("Name=value")
10991138
>>> setOptimizationOptions(["Name1=value1","Name2=value2"])
11001139
"""
1101-
return self.setMethodHelper(optimizationOptions, self.optimizeOptions, "optimization-option", None)
1140+
return self.setMethodHelper(
1141+
inputdata=optimizationOptions,
1142+
classdata=self.optimizeOptions,
1143+
datatype="optimization-option",
1144+
overwritedata=None)
11021145

1103-
def setInputs(self, name): # 15
1146+
def setInputs(self, name: str | list[str] | dict[str, str | int | float]) -> bool:
11041147
"""
11051148
This method is used to set input values. It can be called:
11061149
with a sequence of input name and assigning corresponding values as arguments as show in the example below:
@@ -1109,34 +1152,40 @@ def setInputs(self, name): # 15
11091152
>>> setInputs(["Name1=value1","Name2=value2"])
11101153
"""
11111154
if isinstance(name, str):
1112-
name = self._strip_space(name)
1113-
value = name.split("=")
1114-
if value[0] in self.inputlist:
1115-
tmpvalue = eval(value[1])
1155+
name1: str = name
1156+
name1 = name1.replace(" ", "")
1157+
value1 = name1.split("=")
1158+
if value1[0] in self.inputlist:
1159+
tmpvalue = eval(value1[1])
11161160
if isinstance(tmpvalue, (int, float)):
1117-
self.inputlist[value[0]] = [(float(self.simulateOptions["startTime"]), float(value[1])),
1118-
(float(self.simulateOptions["stopTime"]), float(value[1]))]
1161+
self.inputlist[value1[0]] = [(float(self.simulateOptions["startTime"]), float(value1[1])),
1162+
(float(self.simulateOptions["stopTime"]), float(value1[1]))]
11191163
elif isinstance(tmpvalue, list):
11201164
self.checkValidInputs(tmpvalue)
1121-
self.inputlist[value[0]] = tmpvalue
1165+
self.inputlist[value1[0]] = tmpvalue
11221166
self.inputFlag = True
11231167
else:
1124-
raise ModelicaSystemError(f"{value[0]} is not an input")
1168+
raise ModelicaSystemError(f"{value1[0]} is not an input")
11251169
elif isinstance(name, list):
1126-
name = self._strip_space(name)
1127-
for var in name:
1128-
value = var.split("=")
1129-
if value[0] in self.inputlist:
1130-
tmpvalue = eval(value[1])
1170+
name_list: list[str] = name
1171+
for name2 in name_list:
1172+
name2 = name2.replace(" ", "")
1173+
value2 = name2.split("=")
1174+
if value2[0] in self.inputlist:
1175+
tmpvalue = eval(value2[1])
11311176
if isinstance(tmpvalue, (int, float)):
1132-
self.inputlist[value[0]] = [(float(self.simulateOptions["startTime"]), float(value[1])),
1133-
(float(self.simulateOptions["stopTime"]), float(value[1]))]
1177+
self.inputlist[value2[0]] = [(float(self.simulateOptions["startTime"]), float(value2[1])),
1178+
(float(self.simulateOptions["stopTime"]), float(value2[1]))]
11341179
elif isinstance(tmpvalue, list):
11351180
self.checkValidInputs(tmpvalue)
1136-
self.inputlist[value[0]] = tmpvalue
1181+
self.inputlist[value2[0]] = tmpvalue
11371182
self.inputFlag = True
11381183
else:
1139-
raise ModelicaSystemError(f"{value[0]} is not an input!")
1184+
raise ModelicaSystemError(f"{value2[0]} is not an input!")
1185+
elif isinstance(name, dict):
1186+
raise NotImplementedError("Must be defined!")
1187+
1188+
return True
11401189

11411190
def checkValidInputs(self, name):
11421191
if name != sorted(name, key=lambda x: x[0]):

0 commit comments

Comments
 (0)