refactor valid_enum
This commit is contained in:
@ -56,9 +56,6 @@ KEY_TYPE = {'variable': 'symlink',
|
||||
'URLOption': 'web_address',
|
||||
'FilenameOption': 'filename'}
|
||||
|
||||
TYPE_PARAM_CHECK = ('string', 'python', 'variable')
|
||||
TYPE_PARAM_CONDITION = ('string', 'python', 'number', 'variable')
|
||||
TYPE_PARAM_FILL = ('string', 'number', 'variable')
|
||||
CONVERSION = {'number': int}
|
||||
|
||||
FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
|
||||
@ -476,9 +473,11 @@ class VariableAnnotator:
|
||||
check.name = 'valid_enum'
|
||||
check.target = path
|
||||
check.namespace = namespace
|
||||
param = self.objectspace.param()
|
||||
param.text = str(FORCE_CHOICE[variable.type])
|
||||
check.param = [param]
|
||||
check.param = []
|
||||
for value in FORCE_CHOICE[variable.type]:
|
||||
param = self.objectspace.param()
|
||||
param.text = value
|
||||
check.param.append(param)
|
||||
if not hasattr(self.objectspace.space, 'constraints'):
|
||||
self.objectspace.space.constraints = self.objectspace.constraints()
|
||||
self.objectspace.space.constraints.namespace = namespace
|
||||
@ -627,8 +626,6 @@ class ConstraintAnnotator:
|
||||
if hasattr(check, 'param'):
|
||||
param_option_indexes = []
|
||||
for idx, param in enumerate(check.param):
|
||||
if param.type not in TYPE_PARAM_CHECK:
|
||||
raise DictConsistencyError(_('cannot use {} type as a param in check for {}').format(param.type, check.target))
|
||||
if param.type == 'variable' and not self.objectspace.paths.path_is_defined(param.text):
|
||||
if param.optional is True:
|
||||
param_option_indexes.append(idx)
|
||||
@ -661,55 +658,50 @@ class ConstraintAnnotator:
|
||||
remove_indexes = []
|
||||
for idx, check in enumerate(self.objectspace.space.constraints.check):
|
||||
if check.name == 'valid_enum':
|
||||
if len(check.param) != 1:
|
||||
raise DictConsistencyError(_(f'cannot set more than one param for valid_enum for variable {check.target}'))
|
||||
param = check.param[0]
|
||||
if check.target in self.valid_enums:
|
||||
raise DictConsistencyError(_(f'valid_enum already set for {check.target}'))
|
||||
if param.type not in ['string', 'python', 'number']:
|
||||
raise DictConsistencyError(_(f'unknown type {param.type} for param in valid_enum for {check.target}'))
|
||||
if not hasattr(check, 'param'):
|
||||
raise DictConsistencyError(_(f'param is mandatory for a valid_enum of variable {check.target}'))
|
||||
variable = self.objectspace.paths.get_variable_obj(check.target)
|
||||
values = self.load_params_in_validenum(param,
|
||||
variable.name,
|
||||
variable.type,
|
||||
)
|
||||
self.valid_enums[check.target] = {'type': param.type,
|
||||
'values': values}
|
||||
values = self.load_params_in_valid_enum(check.param,
|
||||
variable.name,
|
||||
variable.type,
|
||||
)
|
||||
self._set_valid_enum(variable,
|
||||
values,
|
||||
variable.type,
|
||||
check.target
|
||||
)
|
||||
remove_indexes.append(idx)
|
||||
remove_indexes.sort(reverse=True)
|
||||
for idx in remove_indexes:
|
||||
del self.objectspace.space.constraints.check[idx]
|
||||
|
||||
def load_params_in_validenum(self,
|
||||
param,
|
||||
variable_name,
|
||||
variable_type,
|
||||
):
|
||||
if not hasattr(param, 'text') and (param.type == 'python' or param.type == 'number'):
|
||||
raise DictConsistencyError(_(f"All '{param.type}' variables shall be set in order to calculate valid_enum for variable {variable_name}"))
|
||||
if variable_type == 'string' and param.type == 'number':
|
||||
raise DictConsistencyError(_(f'Unconsistency valid_enum type ({param.type}), for variable {variable_name}'))
|
||||
if param.type == 'python':
|
||||
try:
|
||||
values = eval(param.text, {'eosfunc': self.eosfunc, '__builtins__': {'range': range, 'str': str}})
|
||||
except NameError:
|
||||
raise DictConsistencyError(_('The function {} is unknown').format(param.text))
|
||||
else:
|
||||
try:
|
||||
values = literal_eval(param.text)
|
||||
except ValueError:
|
||||
raise DictConsistencyError(_(f'Cannot load {param.text} in valid_enum'))
|
||||
if not isinstance(values, list):
|
||||
raise DictConsistencyError(_('Function {} shall return a list').format(param.text))
|
||||
for value in values:
|
||||
if variable_type == 'string' and not isinstance(value, str):
|
||||
raise DictConsistencyError(_(f'Cannot load "{param.text}", "{value}" is not a string'))
|
||||
if variable_type == 'number' and not isinstance(value, int):
|
||||
raise DictConsistencyError(_(f'Cannot load "{param.text}", "{value}" is not a number'))
|
||||
def load_params_in_valid_enum(self,
|
||||
params,
|
||||
variable_name,
|
||||
variable_type,
|
||||
):
|
||||
has_variable = None
|
||||
values = []
|
||||
for param in params:
|
||||
if param.type == 'variable':
|
||||
if has_variable is not None:
|
||||
raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}'))
|
||||
has_variable = True
|
||||
variable = self.objectspace.paths.get_variable_obj(param.text)
|
||||
if not variable.multi:
|
||||
raise DictConsistencyError(_(f'only multi "variable" parameter is allowed for valid_enum of variable {variable_name}'))
|
||||
values = param.text
|
||||
else:
|
||||
if has_variable:
|
||||
raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}'))
|
||||
if not hasattr(param, 'text'):
|
||||
if param.type == 'number':
|
||||
raise DictConsistencyError(_(f'value is mandatory for valid_enum of variable {variable_name}'))
|
||||
values.append(None)
|
||||
else:
|
||||
values.append(param.text)
|
||||
return values
|
||||
|
||||
def check_change_warning(self):
|
||||
@ -736,9 +728,6 @@ class ConstraintAnnotator:
|
||||
|
||||
def check_params_target(self):
|
||||
for condition in self.objectspace.space.constraints.condition:
|
||||
for param in condition.param:
|
||||
if param.type not in TYPE_PARAM_CONDITION:
|
||||
raise DictConsistencyError(_(f'cannot use {param.type} type as a param in a condition'))
|
||||
if not hasattr(condition, 'target'):
|
||||
raise DictConsistencyError(_('target is mandatory in condition'))
|
||||
for target in condition.target:
|
||||
@ -919,40 +908,52 @@ class ConstraintAnnotator:
|
||||
variable.property.append(prop)
|
||||
del self.objectspace.space.constraints.condition
|
||||
|
||||
def _set_valid_enum(self, variable, values, type_):
|
||||
def _set_valid_enum(self, variable, values, type_, target):
|
||||
# value for choice's variable is mandatory
|
||||
variable.mandatory = True
|
||||
# build choice
|
||||
variable.choice = []
|
||||
choices = []
|
||||
for value in values:
|
||||
if isinstance(values, str):
|
||||
choice = self.objectspace.choice()
|
||||
try:
|
||||
choice.name = CONVERSION.get(type_, str)(value)
|
||||
except:
|
||||
raise DictConsistencyError(_(f'unable to change type of a valid_enum entry "{value}" is not a valid "{type_}" for "{variable.name}"'))
|
||||
if choice.name == '':
|
||||
choice.name = None
|
||||
choices.append(choice.name)
|
||||
choice.type = type_
|
||||
choice.type = 'calculation'
|
||||
choice.name = values
|
||||
variable.choice.append(choice)
|
||||
else:
|
||||
self.valid_enums[target] = {'type': type_,
|
||||
'values': values,
|
||||
}
|
||||
choices = []
|
||||
for value in values:
|
||||
choice = self.objectspace.choice()
|
||||
try:
|
||||
if value is not None:
|
||||
choice.name = CONVERSION.get(type_, str)(value)
|
||||
else:
|
||||
choice.name = value
|
||||
except:
|
||||
raise DictConsistencyError(_(f'unable to change type of a valid_enum entry "{value}" is not a valid "{type_}" for "{variable.name}"'))
|
||||
if choice.name == '':
|
||||
choice.name = None
|
||||
choices.append(choice.name)
|
||||
choice.type = type_
|
||||
variable.choice.append(choice)
|
||||
# check value or set first choice value has default value
|
||||
if hasattr(variable, 'value'):
|
||||
for value in variable.value:
|
||||
value.type = type_
|
||||
try:
|
||||
cvalue = CONVERSION.get(type_, str)(value.name)
|
||||
except:
|
||||
raise DictConsistencyError(_(f'unable to change type of value "{value}" is not a valid "{type_}" for "{variable.name}"'))
|
||||
if cvalue not in choices:
|
||||
raise DictConsistencyError(_('value "{}" of variable "{}" is not in list of all expected values ({})').format(value.name, variable.name, choices))
|
||||
else:
|
||||
new_value = self.objectspace.value()
|
||||
new_value.name = choices[0]
|
||||
new_value.type = type_
|
||||
variable.value = [new_value]
|
||||
if not variable.choice:
|
||||
raise DictConsistencyError(_('empty valid enum is not allowed for variable {}').format(variable.name))
|
||||
# check value or set first choice value has default value
|
||||
if hasattr(variable, 'value'):
|
||||
for value in variable.value:
|
||||
value.type = type_
|
||||
try:
|
||||
cvalue = CONVERSION.get(type_, str)(value.name)
|
||||
except:
|
||||
raise DictConsistencyError(_(f'unable to change type of value "{value}" is not a valid "{type_}" for "{variable.name}"'))
|
||||
if cvalue not in choices:
|
||||
raise DictConsistencyError(_('value "{}" of variable "{}" is not in list of all expected values ({})').format(value.name, variable.name, choices))
|
||||
else:
|
||||
new_value = self.objectspace.value()
|
||||
new_value.name = values[0]
|
||||
new_value.type = type_
|
||||
variable.value = [new_value]
|
||||
variable.type = 'choice'
|
||||
|
||||
def convert_check(self):
|
||||
@ -1030,8 +1031,6 @@ class ConstraintAnnotator:
|
||||
if hasattr(fill, 'param'):
|
||||
param_to_delete = []
|
||||
for fill_idx, param in enumerate(fill.param):
|
||||
if param.type not in TYPE_PARAM_FILL:
|
||||
raise DictConsistencyError(_(f'cannot use {param.type} type as a param in a fill/auto'))
|
||||
if param.type != 'string' and not hasattr(param, 'text'):
|
||||
raise DictConsistencyError(_(f"All '{param.type}' variables shall have a value in order to calculate {fill.target}"))
|
||||
if param.type == 'variable':
|
||||
|
@ -141,7 +141,7 @@
|
||||
<!ATTLIST group description CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT param (#PCDATA)>
|
||||
<!ATTLIST param type (string|variable|number|python) "string">
|
||||
<!ATTLIST param type (string|number|variable|information) "string">
|
||||
<!ATTLIST param name CDATA #IMPLIED>
|
||||
<!ATTLIST param notraisepropertyerror (True|False) "False">
|
||||
<!ATTLIST param optional (True|False) "False">
|
||||
|
@ -252,7 +252,7 @@ class Common:
|
||||
if not self.attrib[key]:
|
||||
continue
|
||||
value = "frozenset({" + self.attrib[key] + "})"
|
||||
elif key in ['default', 'multi', 'suffixes', 'validators']:
|
||||
elif key in ['default', 'multi', 'suffixes', 'validators', 'values']:
|
||||
value = self.attrib[key]
|
||||
elif isinstance(value, str) and key != 'opt' and not value.startswith('['):
|
||||
value = "'" + value.replace("'", "\\\'") + "'"
|
||||
@ -368,9 +368,16 @@ class Variable(Common):
|
||||
elif tag == 'check':
|
||||
self.attrib['validators'].append(self.calculation_value(child, ['ParamSelfOption()']))
|
||||
elif tag == 'choice':
|
||||
choices.append(child.name)
|
||||
if child.type == 'calculation':
|
||||
value = self.storage.get(child.name).get()
|
||||
choices = f"Calculation(func.calc_value, Params((ParamOption({value}))))"
|
||||
else:
|
||||
choices.append(child.name)
|
||||
if choices:
|
||||
self.attrib['values'] = tuple(choices)
|
||||
if isinstance(choices, list):
|
||||
self.attrib['values'] = str(tuple(choices))
|
||||
else:
|
||||
self.attrib['values'] = choices
|
||||
if self.attrib['default'] == []:
|
||||
del self.attrib['default']
|
||||
elif not self.attrib['multi'] and isinstance(self.attrib['default'], list):
|
||||
|
Reference in New Issue
Block a user