Skip to content

Commit abf495e

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 08a8500 commit abf495e

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
@@ -985,106 +985,149 @@ def _strip_space(name):
985985

986986
raise ModelicaSystemError("Unhandled input for strip_space()")
987987

988-
def setMethodHelper(self, args1, args2, args3, args4=None):
988+
def setMethodHelper(
989+
self,
990+
inputdata: str | list[str] | dict[str, str | int | float],
991+
classdata: dict[str, Any],
992+
datatype: str,
993+
overwritedata: Optional[dict[str, str]] = None,
994+
) -> bool:
989995
"""
990996
Helper function for setParameter(),setContinuous(),setSimulationOptions(),setLinearizationOption(),setOptimizationOption()
997+
991998
args1 - string or list of string given by user
992999
args2 - dict() containing the values of different variables(eg:, parameter,continuous,simulation parameters)
9931000
args3 - function name (eg; continuous, parameter, simulation, linearization,optimization)
9941001
args4 - dict() which stores the new override variables list,
9951002
"""
996-
def apply_single(args1):
997-
args1 = self._strip_space(args1)
998-
value = args1.split("=")
999-
if value[0] in args2:
1000-
if args3 == "parameter" and self.isParameterChangeable(value[0], value[1]):
1001-
args2[value[0]] = value[1]
1002-
if args4 is not None:
1003-
args4[value[0]] = value[1]
1004-
elif args3 != "parameter":
1005-
args2[value[0]] = value[1]
1006-
if args4 is not None:
1007-
args4[value[0]] = value[1]
1003+
1004+
# TODO: cleanup / data handling / ...
1005+
# (1) args1: Optional[str | list[str]] -> convert to dict
1006+
# (2) work on dict! inputs: dict[str, str | int | float | ?numbers.number?]
1007+
# (3) handle function
1008+
# (4) use it also for other functions with such an input, i.e. 'key=value' | ['key=value']
1009+
# (5) include setInputs()
1010+
1011+
def apply_single(key_val: str):
1012+
key_val_list = key_val.split("=")
1013+
if len(key_val_list) != 2:
1014+
raise ModelicaSystemError(f"Invalid key = value pair: {key_val}")
1015+
1016+
name = self._strip_space(key_val_list[0])
1017+
value = self._strip_space(key_val_list[1])
1018+
1019+
if name in classdata:
1020+
if datatype == "parameter" and not self.isParameterChangeable(name):
1021+
logger.debug(f"It is not possible to set the parameter {repr(name)}. It seems to be "
1022+
"structural, final, protected, evaluated or has a non-constant binding. "
1023+
"Use sendExpression(...) and rebuild the model using buildModel() API; example: "
1024+
"sendExpression(\"setParameterValue("
1025+
f"{self.modelName}, {name}, {value if value is not None else '<?value?>'}"
1026+
")\") ")
1027+
return False
1028+
1029+
classdata[name] = value
1030+
if overwritedata is not None:
1031+
overwritedata[name] = value
10081032

10091033
return True
10101034

10111035
else:
10121036
raise ModelicaSystemError("Unhandled case in setMethodHelper.apply_single() - "
1013-
f"{repr(value[0])} is not a {repr(args3)} variable")
1037+
f"{repr(name)} is not a {repr(datatype)} variable")
10141038

10151039
result = []
1016-
if isinstance(args1, str):
1017-
result = [apply_single(args1)]
1040+
if isinstance(inputdata, str):
1041+
result = [apply_single(inputdata)]
10181042

1019-
elif isinstance(args1, list):
1043+
elif isinstance(inputdata, list):
10201044
result = []
1021-
args1 = self._strip_space(args1)
1022-
for var in args1:
1045+
inputdata = self._strip_space(inputdata)
1046+
for var in inputdata:
10231047
result.append(apply_single(var))
10241048

10251049
return all(result)
10261050

1027-
def setContinuous(self, cvals): # 13
1051+
def isParameterChangeable(
1052+
self,
1053+
name: str,
1054+
):
1055+
q = self.getQuantities(name)
1056+
if q[0]["changeable"] == "false":
1057+
return False
1058+
return True
1059+
1060+
def setContinuous(self, cvals: str | list[str] | dict[str, str | int | float]) -> bool:
10281061
"""
10291062
This method is used to set continuous values. It can be called:
10301063
with a sequence of continuous name and assigning corresponding values as arguments as show in the example below:
10311064
usage
10321065
>>> setContinuous("Name=value")
10331066
>>> setContinuous(["Name1=value1","Name2=value2"])
10341067
"""
1035-
return self.setMethodHelper(cvals, self.continuouslist, "continuous", self.overridevariables)
1068+
return self.setMethodHelper(
1069+
inputdata=cvals,
1070+
classdata=self.continuouslist,
1071+
datatype="continuous",
1072+
overwritedata=self.overridevariables)
10361073

1037-
def setParameters(self, pvals): # 14
1074+
def setParameters(self, pvals: str | list[str] | dict[str, str | int | float]) -> bool:
10381075
"""
10391076
This method is used to set parameter values. It can be called:
10401077
with a sequence of parameter name and assigning corresponding value as arguments as show in the example below:
10411078
usage
10421079
>>> setParameters("Name=value")
10431080
>>> setParameters(["Name1=value1","Name2=value2"])
10441081
"""
1045-
return self.setMethodHelper(pvals, self.paramlist, "parameter", self.overridevariables)
1046-
1047-
def isParameterChangeable(self, name, value):
1048-
q = self.getQuantities(name)
1049-
if q[0]["changeable"] == "false":
1050-
logger.verbose(f"setParameters() failed : It is not possible to set the following signal {repr(name)}. "
1051-
"It seems to be structural, final, protected or evaluated or has a non-constant binding, "
1052-
f"use sendExpression(\"setParameterValue({self.modelName}, {name}, {value})\") "
1053-
"and rebuild the model using buildModel() API")
1054-
return False
1055-
return True
1082+
return self.setMethodHelper(
1083+
inputdata=pvals,
1084+
classdata=self.paramlist,
1085+
datatype="parameter",
1086+
overwritedata=self.overridevariables)
10561087

1057-
def setSimulationOptions(self, simOptions): # 16
1088+
def setSimulationOptions(self, simOptions: str | list[str] | dict[str, str | int | float]) -> bool:
10581089
"""
10591090
This method is used to set simulation options. It can be called:
10601091
with a sequence of simulation options name and assigning corresponding values as arguments as show in the example below:
10611092
usage
10621093
>>> setSimulationOptions("Name=value")
10631094
>>> setSimulationOptions(["Name1=value1","Name2=value2"])
10641095
"""
1065-
return self.setMethodHelper(simOptions, self.simulateOptions, "simulation-option", self.simoptionsoverride)
1096+
return self.setMethodHelper(
1097+
inputdata=simOptions,
1098+
classdata=self.simulateOptions,
1099+
datatype="simulation-option",
1100+
overwritedata=self.simoptionsoverride)
10661101

1067-
def setLinearizationOptions(self, linearizationOptions): # 18
1102+
def setLinearizationOptions(self, linearizationOptions: str | list[str] | dict[str, str | int | float]) -> bool:
10681103
"""
10691104
This method is used to set linearization options. It can be called:
10701105
with a sequence of linearization options name and assigning corresponding value as arguments as show in the example below
10711106
usage
10721107
>>> setLinearizationOptions("Name=value")
10731108
>>> setLinearizationOptions(["Name1=value1","Name2=value2"])
10741109
"""
1075-
return self.setMethodHelper(linearizationOptions, self.linearOptions, "Linearization-option", None)
1110+
return self.setMethodHelper(
1111+
inputdata=linearizationOptions,
1112+
classdata=self.linearOptions,
1113+
datatype="Linearization-option",
1114+
overwritedata=None)
10761115

1077-
def setOptimizationOptions(self, optimizationOptions): # 17
1116+
def setOptimizationOptions(self, optimizationOptions: str | list[str] | dict[str, str | int | float]) -> bool:
10781117
"""
10791118
This method is used to set optimization options. It can be called:
10801119
with a sequence of optimization options name and assigning corresponding values as arguments as show in the example below:
10811120
usage
10821121
>>> setOptimizationOptions("Name=value")
10831122
>>> setOptimizationOptions(["Name1=value1","Name2=value2"])
10841123
"""
1085-
return self.setMethodHelper(optimizationOptions, self.optimizeOptions, "optimization-option", None)
1124+
return self.setMethodHelper(
1125+
inputdata=optimizationOptions,
1126+
classdata=self.optimizeOptions,
1127+
datatype="optimization-option",
1128+
overwritedata=None)
10861129

1087-
def setInputs(self, name): # 15
1130+
def setInputs(self, name: str | list[str] | dict[str, str | int | float]) -> bool:
10881131
"""
10891132
This method is used to set input values. It can be called:
10901133
with a sequence of input name and assigning corresponding values as arguments as show in the example below:
@@ -1093,34 +1136,40 @@ def setInputs(self, name): # 15
10931136
>>> setInputs(["Name1=value1","Name2=value2"])
10941137
"""
10951138
if isinstance(name, str):
1096-
name = self._strip_space(name)
1097-
value = name.split("=")
1098-
if value[0] in self.inputlist:
1099-
tmpvalue = eval(value[1])
1139+
name1: str = name
1140+
name1 = name1.replace(" ", "")
1141+
value1 = name1.split("=")
1142+
if value1[0] in self.inputlist:
1143+
tmpvalue = eval(value1[1])
11001144
if isinstance(tmpvalue, (int, float)):
1101-
self.inputlist[value[0]] = [(float(self.simulateOptions["startTime"]), float(value[1])),
1102-
(float(self.simulateOptions["stopTime"]), float(value[1]))]
1145+
self.inputlist[value1[0]] = [(float(self.simulateOptions["startTime"]), float(value1[1])),
1146+
(float(self.simulateOptions["stopTime"]), float(value1[1]))]
11031147
elif isinstance(tmpvalue, list):
11041148
self.checkValidInputs(tmpvalue)
1105-
self.inputlist[value[0]] = tmpvalue
1149+
self.inputlist[value1[0]] = tmpvalue
11061150
self.inputFlag = True
11071151
else:
1108-
raise ModelicaSystemError(f"{value[0]} is not an input")
1152+
raise ModelicaSystemError(f"{value1[0]} is not an input")
11091153
elif isinstance(name, list):
1110-
name = self._strip_space(name)
1111-
for var in name:
1112-
value = var.split("=")
1113-
if value[0] in self.inputlist:
1114-
tmpvalue = eval(value[1])
1154+
name_list: list[str] = name
1155+
for name2 in name_list:
1156+
name2 = name2.replace(" ", "")
1157+
value2 = name2.split("=")
1158+
if value2[0] in self.inputlist:
1159+
tmpvalue = eval(value2[1])
11151160
if isinstance(tmpvalue, (int, float)):
1116-
self.inputlist[value[0]] = [(float(self.simulateOptions["startTime"]), float(value[1])),
1117-
(float(self.simulateOptions["stopTime"]), float(value[1]))]
1161+
self.inputlist[value2[0]] = [(float(self.simulateOptions["startTime"]), float(value2[1])),
1162+
(float(self.simulateOptions["stopTime"]), float(value2[1]))]
11181163
elif isinstance(tmpvalue, list):
11191164
self.checkValidInputs(tmpvalue)
1120-
self.inputlist[value[0]] = tmpvalue
1165+
self.inputlist[value2[0]] = tmpvalue
11211166
self.inputFlag = True
11221167
else:
1123-
raise ModelicaSystemError(f"{value[0]} is not an input!")
1168+
raise ModelicaSystemError(f"{value2[0]} is not an input!")
1169+
elif isinstance(name, dict):
1170+
raise NotImplementedError("Must be defined!")
1171+
1172+
return True
11241173

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

0 commit comments

Comments
 (0)