|
|
@ -1,4 +1,7 @@
|
|
|
|
|
|
|
|
"""Annotate constraints
|
|
|
|
|
|
|
|
"""
|
|
|
|
from importlib.machinery import SourceFileLoader
|
|
|
|
from importlib.machinery import SourceFileLoader
|
|
|
|
|
|
|
|
from typing import List, Any
|
|
|
|
|
|
|
|
|
|
|
|
from .variable import CONVERT_OPTION
|
|
|
|
from .variable import CONVERT_OPTION
|
|
|
|
|
|
|
|
|
|
|
@ -12,7 +15,32 @@ FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
|
|
|
|
INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier']
|
|
|
|
INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_actions_from_condition(condition_name: str,
|
|
|
|
|
|
|
|
) -> List[str]:
|
|
|
|
|
|
|
|
"""get action's name from a condition
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
if condition_name.startswith('hidden_if_'):
|
|
|
|
|
|
|
|
return ['hidden', 'frozen', 'force_default_on_freeze']
|
|
|
|
|
|
|
|
if condition_name == 'auto_frozen_if_not_in':
|
|
|
|
|
|
|
|
return ['auto_frozen']
|
|
|
|
|
|
|
|
return [condition_name.split('_', 1)[0]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_valid_enum_value(variable,
|
|
|
|
|
|
|
|
values,
|
|
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
|
|
"""check that values in valid_enum are valid
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
for value in variable.value:
|
|
|
|
|
|
|
|
if value.name not in values:
|
|
|
|
|
|
|
|
msg = _(f'value "{value.name}" of variable "{variable.name}" is not in list '
|
|
|
|
|
|
|
|
f'of all expected values ({values})')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 15)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ConstrainteAnnotator:
|
|
|
|
class ConstrainteAnnotator:
|
|
|
|
|
|
|
|
"""Annotate constrainte
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self,
|
|
|
|
def __init__(self,
|
|
|
|
objectspace,
|
|
|
|
objectspace,
|
|
|
|
eosfunc_file,
|
|
|
|
eosfunc_file,
|
|
|
@ -23,18 +51,16 @@ class ConstrainteAnnotator:
|
|
|
|
eosfunc = SourceFileLoader('eosfunc', eosfunc_file).load_module()
|
|
|
|
eosfunc = SourceFileLoader('eosfunc', eosfunc_file).load_module()
|
|
|
|
self.functions = dir(eosfunc)
|
|
|
|
self.functions = dir(eosfunc)
|
|
|
|
self.functions.extend(INTERNAL_FUNCTIONS)
|
|
|
|
self.functions.extend(INTERNAL_FUNCTIONS)
|
|
|
|
|
|
|
|
self.valid_enums = {}
|
|
|
|
|
|
|
|
|
|
|
|
self.convert_auto_freeze()
|
|
|
|
self.convert_auto_freeze()
|
|
|
|
self.valid_enums = {}
|
|
|
|
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'check'):
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'check'):
|
|
|
|
self.check_check()
|
|
|
|
self.check_check()
|
|
|
|
self.check_replace_text()
|
|
|
|
|
|
|
|
self.check_valid_enum()
|
|
|
|
self.check_valid_enum()
|
|
|
|
self.check_change_warning()
|
|
|
|
self.check_change_warning()
|
|
|
|
self.convert_check()
|
|
|
|
self.convert_check()
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'condition'):
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'condition'):
|
|
|
|
self.check_params_target()
|
|
|
|
self.convert_condition_target()
|
|
|
|
self.filter_targets()
|
|
|
|
|
|
|
|
self.convert_xxxlist_to_variable()
|
|
|
|
self.convert_xxxlist_to_variable()
|
|
|
|
self.check_condition_fallback_optional()
|
|
|
|
self.check_condition_fallback_optional()
|
|
|
|
self.check_choice_option_condition()
|
|
|
|
self.check_choice_option_condition()
|
|
|
@ -42,16 +68,19 @@ class ConstrainteAnnotator:
|
|
|
|
self.convert_condition()
|
|
|
|
self.convert_condition()
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'fill'):
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'fill'):
|
|
|
|
self.convert_fill()
|
|
|
|
self.convert_fill()
|
|
|
|
self.remove_constraints()
|
|
|
|
del self.objectspace.space.constraints
|
|
|
|
|
|
|
|
|
|
|
|
def convert_auto_freeze(self): # pylint: disable=C0111
|
|
|
|
def convert_auto_freeze(self):
|
|
|
|
|
|
|
|
"""convert auto_freeze to continue
|
|
|
|
|
|
|
|
"""
|
|
|
|
def _convert_auto_freeze(variable, namespace):
|
|
|
|
def _convert_auto_freeze(variable, namespace):
|
|
|
|
if variable.auto_freeze:
|
|
|
|
if variable.auto_freeze:
|
|
|
|
if namespace != Config['variable_namespace']:
|
|
|
|
if namespace != Config['variable_namespace']:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'auto_freeze is not allowed in extra "{namespace}" in {xmlfiles}'), 49)
|
|
|
|
msg = _(f'auto_freeze is not allowed in extra "{namespace}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 49)
|
|
|
|
new_condition = self.objectspace.condition(variable.xmlfiles)
|
|
|
|
new_condition = self.objectspace.condition(variable.xmlfiles)
|
|
|
|
new_condition.name = 'auto_hidden_if_not_in'
|
|
|
|
new_condition.name = 'auto_frozen_if_not_in'
|
|
|
|
new_condition.namespace = namespace
|
|
|
|
new_condition.namespace = namespace
|
|
|
|
new_condition.source = FREEZE_AUTOFREEZE_VARIABLE
|
|
|
|
new_condition.source = FREEZE_AUTOFREEZE_VARIABLE
|
|
|
|
new_param = self.objectspace.param(variable.xmlfiles)
|
|
|
|
new_param = self.objectspace.param(variable.xmlfiles)
|
|
|
@ -65,82 +94,176 @@ class ConstrainteAnnotator:
|
|
|
|
self.objectspace.space.constraints.condition = []
|
|
|
|
self.objectspace.space.constraints.condition = []
|
|
|
|
self.objectspace.space.constraints.condition.append(new_condition)
|
|
|
|
self.objectspace.space.constraints.condition.append(new_condition)
|
|
|
|
for variables in self.objectspace.space.variables.values():
|
|
|
|
for variables in self.objectspace.space.variables.values():
|
|
|
|
if hasattr(variables, 'family'):
|
|
|
|
if not hasattr(variables, 'family'):
|
|
|
|
namespace = variables.name
|
|
|
|
continue
|
|
|
|
for family in variables.family.values():
|
|
|
|
for family in variables.family.values():
|
|
|
|
if hasattr(family, 'variable'):
|
|
|
|
if not hasattr(family, 'variable'):
|
|
|
|
for variable in family.variable.values():
|
|
|
|
continue
|
|
|
|
if isinstance(variable, self.objectspace.leadership):
|
|
|
|
for variable in family.variable.values():
|
|
|
|
for follower in variable.variable:
|
|
|
|
if isinstance(variable, self.objectspace.leadership):
|
|
|
|
_convert_auto_freeze(follower, namespace)
|
|
|
|
for follower in variable.variable:
|
|
|
|
else:
|
|
|
|
_convert_auto_freeze(follower,
|
|
|
|
_convert_auto_freeze(variable, namespace)
|
|
|
|
variables.namespace,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
_convert_auto_freeze(variable,
|
|
|
|
|
|
|
|
variables.namespace,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def check_check(self):
|
|
|
|
def check_check(self):
|
|
|
|
|
|
|
|
"""valid and manage <check>
|
|
|
|
|
|
|
|
"""
|
|
|
|
remove_indexes = []
|
|
|
|
remove_indexes = []
|
|
|
|
for check_idx, check in enumerate(self.objectspace.space.constraints.check):
|
|
|
|
for check_idx, check in enumerate(self.objectspace.space.constraints.check):
|
|
|
|
if not check.name in self.functions:
|
|
|
|
if not check.name in self.functions:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'cannot find check function "{check.name}" in {xmlfiles}'), 1)
|
|
|
|
msg = _(f'cannot find check function "{check.name}" in {xmlfiles}')
|
|
|
|
if hasattr(check, 'param'):
|
|
|
|
raise DictConsistencyError(msg, 1)
|
|
|
|
param_option_indexes = []
|
|
|
|
if not hasattr(check, 'param'):
|
|
|
|
for idx, param in enumerate(check.param):
|
|
|
|
continue
|
|
|
|
if param.type == 'variable' and not self.objectspace.paths.path_is_defined(param.text):
|
|
|
|
param_option_indexes = []
|
|
|
|
if param.optional is True:
|
|
|
|
for idx, param in enumerate(check.param):
|
|
|
|
param_option_indexes.append(idx)
|
|
|
|
if param.type == 'variable':
|
|
|
|
else:
|
|
|
|
if not self.objectspace.paths.path_is_defined(param.text):
|
|
|
|
|
|
|
|
if not param.optional:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'cannot find check param "{param.text}" in {xmlfiles}'), 2)
|
|
|
|
msg = _(f'cannot find check param "{param.text}" in {xmlfiles}')
|
|
|
|
if param.type != 'variable':
|
|
|
|
raise DictConsistencyError(msg, 2)
|
|
|
|
param.notraisepropertyerror = None
|
|
|
|
param_option_indexes.append(idx)
|
|
|
|
param_option_indexes = list(set(param_option_indexes))
|
|
|
|
else:
|
|
|
|
param_option_indexes.sort(reverse=True)
|
|
|
|
# let's replace params by the path
|
|
|
|
for idx in param_option_indexes:
|
|
|
|
param.text = self.objectspace.paths.get_variable_path(param.text,
|
|
|
|
check.param.pop(idx)
|
|
|
|
check.namespace,
|
|
|
|
if check.param == []:
|
|
|
|
)
|
|
|
|
remove_indexes.append(check_idx)
|
|
|
|
param_option_indexes.sort(reverse=True)
|
|
|
|
|
|
|
|
for idx in param_option_indexes:
|
|
|
|
|
|
|
|
check.param.pop(idx)
|
|
|
|
|
|
|
|
if check.param == []:
|
|
|
|
|
|
|
|
remove_indexes.append(check_idx)
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
# let's replace the target by the path
|
|
|
|
|
|
|
|
check.target = self.objectspace.paths.get_variable_path(check.target,
|
|
|
|
|
|
|
|
check.namespace,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
check.is_in_leadership = self.objectspace.paths.get_leader(check.target) is not None
|
|
|
|
remove_indexes.sort(reverse=True)
|
|
|
|
remove_indexes.sort(reverse=True)
|
|
|
|
for idx in remove_indexes:
|
|
|
|
for idx in remove_indexes:
|
|
|
|
del self.objectspace.space.constraints.check[idx]
|
|
|
|
del self.objectspace.space.constraints.check[idx]
|
|
|
|
|
|
|
|
|
|
|
|
def check_replace_text(self):
|
|
|
|
|
|
|
|
for check in self.objectspace.space.constraints.check:
|
|
|
|
|
|
|
|
namespace = check.namespace
|
|
|
|
|
|
|
|
if hasattr(check, 'param'):
|
|
|
|
|
|
|
|
for param in check.param:
|
|
|
|
|
|
|
|
if param.type == 'variable':
|
|
|
|
|
|
|
|
param.text = self.objectspace.paths.get_variable_path(param.text, namespace)
|
|
|
|
|
|
|
|
check.is_in_leadership = self.objectspace.paths.get_leader(check.target) is not None
|
|
|
|
|
|
|
|
# let's replace the target by the path
|
|
|
|
|
|
|
|
check.target = self.objectspace.paths.get_variable_path(check.target, namespace)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_valid_enum(self):
|
|
|
|
def check_valid_enum(self):
|
|
|
|
|
|
|
|
"""verify valid_enum
|
|
|
|
|
|
|
|
"""
|
|
|
|
remove_indexes = []
|
|
|
|
remove_indexes = []
|
|
|
|
for idx, check in enumerate(self.objectspace.space.constraints.check):
|
|
|
|
for idx, check in enumerate(self.objectspace.space.constraints.check):
|
|
|
|
if check.name == 'valid_enum':
|
|
|
|
if check.name == 'valid_enum':
|
|
|
|
if check.target in self.valid_enums:
|
|
|
|
if check.target in self.valid_enums:
|
|
|
|
old_xmlfiles = self.objectspace.display_xmlfiles(self.valid_enums[check.target]['xmlfiles'])
|
|
|
|
check_xmlfiles = self.valid_enums[check.target]['xmlfiles']
|
|
|
|
|
|
|
|
old_xmlfiles = self.objectspace.display_xmlfiles(check_xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'valid_enum define in {xmlfiles} but already set in {old_xmlfiles} for "{check.target}", did you forget remove_check?'), 3)
|
|
|
|
msg = _(f'valid_enum define in {xmlfiles} but already set in {old_xmlfiles} '
|
|
|
|
|
|
|
|
f'for "{check.target}", did you forget remove_check?')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 3)
|
|
|
|
if not hasattr(check, 'param'):
|
|
|
|
if not hasattr(check, 'param'):
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'param is mandatory for a valid_enum of variable "{check.target}" in {xmlfiles}'), 4)
|
|
|
|
msg = _(f'param is mandatory for a valid_enum of variable "{check.target}" '
|
|
|
|
|
|
|
|
f'in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 4)
|
|
|
|
variable = self.objectspace.paths.get_variable_obj(check.target)
|
|
|
|
variable = self.objectspace.paths.get_variable_obj(check.target)
|
|
|
|
self._set_valid_enum(variable,
|
|
|
|
variable_type = variable.type
|
|
|
|
check,
|
|
|
|
values = self._set_valid_enum(variable,
|
|
|
|
)
|
|
|
|
check,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
if values:
|
|
|
|
|
|
|
|
if hasattr(variable, 'value'):
|
|
|
|
|
|
|
|
# check value
|
|
|
|
|
|
|
|
check_valid_enum_value(variable, values)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
# no value, set the first choice has default value
|
|
|
|
|
|
|
|
new_value = self.objectspace.value(check.xmlfiles)
|
|
|
|
|
|
|
|
new_value.name = values[0]
|
|
|
|
|
|
|
|
new_value.type = variable_type
|
|
|
|
|
|
|
|
variable.value = [new_value]
|
|
|
|
remove_indexes.append(idx)
|
|
|
|
remove_indexes.append(idx)
|
|
|
|
remove_indexes.sort(reverse=True)
|
|
|
|
remove_indexes.sort(reverse=True)
|
|
|
|
for idx in remove_indexes:
|
|
|
|
for idx in remove_indexes:
|
|
|
|
del self.objectspace.space.constraints.check[idx]
|
|
|
|
del self.objectspace.space.constraints.check[idx]
|
|
|
|
|
|
|
|
|
|
|
|
def check_change_warning(self):
|
|
|
|
def _set_valid_enum(self,
|
|
|
|
#convert level to "warnings_only"
|
|
|
|
variable,
|
|
|
|
for check in self.objectspace.space.constraints.check:
|
|
|
|
check,
|
|
|
|
if check.level == 'warning':
|
|
|
|
) -> List[Any]:
|
|
|
|
check.warnings_only = True
|
|
|
|
# value for choice's variable is mandatory
|
|
|
|
|
|
|
|
variable.mandatory = True
|
|
|
|
|
|
|
|
# build choice
|
|
|
|
|
|
|
|
variable.choice = []
|
|
|
|
|
|
|
|
variable_type = variable.type
|
|
|
|
|
|
|
|
variable.type = 'choice'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
has_variable = False
|
|
|
|
|
|
|
|
values = []
|
|
|
|
|
|
|
|
for param in check.param:
|
|
|
|
|
|
|
|
if has_variable:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'only one "variable" parameter is allowed for valid_enum '
|
|
|
|
|
|
|
|
f'of variable "{variable.name}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 5)
|
|
|
|
|
|
|
|
param_type = variable_type
|
|
|
|
|
|
|
|
if param.type == 'variable':
|
|
|
|
|
|
|
|
has_variable = True
|
|
|
|
|
|
|
|
if param.optional is True:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'optional parameter in valid_enum for variable "{variable.name}" '
|
|
|
|
|
|
|
|
f'is not allowed in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 14)
|
|
|
|
|
|
|
|
param_variable = self.objectspace.paths.get_variable_obj(param.text)
|
|
|
|
|
|
|
|
if not param_variable.multi:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'only multi "variable" parameter is allowed for valid_enum '
|
|
|
|
|
|
|
|
f'of variable "{variable.name}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 6)
|
|
|
|
|
|
|
|
param_type = 'calculation'
|
|
|
|
|
|
|
|
value = param.text
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
check.warnings_only = False
|
|
|
|
if 'type' in vars(param) and variable_type != param.type:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'parameter in valid_enum has incompatible type "{param.type}" '
|
|
|
|
|
|
|
|
f'with type of the variable "{variable.name}" ("{variable_type}") '
|
|
|
|
|
|
|
|
f'in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 7)
|
|
|
|
|
|
|
|
if hasattr(param, 'text'):
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
value = CONVERT_OPTION[variable_type].get('func', str)(param.text)
|
|
|
|
|
|
|
|
except ValueError as err:
|
|
|
|
|
|
|
|
msg = _(f'unable to change type of a valid_enum entry "{param.text}" '
|
|
|
|
|
|
|
|
f'is not a valid "{variable_type}" for "{variable.name}"')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 13) from err
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
if param.type == 'number':
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
msg = _('param type is number, so value is mandatory for valid_enum '
|
|
|
|
|
|
|
|
f'of variable "{variable.name}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 8)
|
|
|
|
|
|
|
|
value = None
|
|
|
|
|
|
|
|
values.append(value)
|
|
|
|
|
|
|
|
choice = self.objectspace.choice(variable.xmlfiles)
|
|
|
|
|
|
|
|
choice.name = value
|
|
|
|
|
|
|
|
choice.type = param_type
|
|
|
|
|
|
|
|
variable.choice.append(choice)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if has_variable:
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.valid_enums[check.target] = {'type': variable_type,
|
|
|
|
|
|
|
|
'values': values,
|
|
|
|
|
|
|
|
'xmlfiles': check.xmlfiles,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return values
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_change_warning(self):
|
|
|
|
|
|
|
|
"""convert level to "warnings_only"
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
for check in self.objectspace.space.constraints.check:
|
|
|
|
|
|
|
|
check.warnings_only = check.level == 'warning'
|
|
|
|
check.level = None
|
|
|
|
check.level = None
|
|
|
|
|
|
|
|
|
|
|
|
def _get_family_variables_from_target(self,
|
|
|
|
def _get_family_variables_from_target(self,
|
|
|
@ -157,39 +280,49 @@ class ConstrainteAnnotator:
|
|
|
|
variable = self.objectspace.paths.get_family_obj(target.name)
|
|
|
|
variable = self.objectspace.paths.get_family_obj(target.name)
|
|
|
|
return variable, list(variable.variable.values())
|
|
|
|
return variable, list(variable.variable.values())
|
|
|
|
|
|
|
|
|
|
|
|
def check_params_target(self):
|
|
|
|
def convert_condition_target(self):
|
|
|
|
|
|
|
|
"""verify and manage target in condition
|
|
|
|
|
|
|
|
"""
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
if not hasattr(condition, 'target'):
|
|
|
|
if not hasattr(condition, 'target'):
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'target is mandatory in a condition for source "{condition.source}" in {xmlfiles}'), 9)
|
|
|
|
msg = _(f'target is mandatory in a condition for source "{condition.source}" '
|
|
|
|
for target in condition.target:
|
|
|
|
f'in {xmlfiles}')
|
|
|
|
if target.type.endswith('list') and condition.name not in ['disabled_if_in', 'disabled_if_not_in']:
|
|
|
|
raise DictConsistencyError(msg, 9)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(target.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'target "{target.type}" not allow in condition "{condition.name}" in {xmlfiles}'), 10)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def filter_targets(self): # pylint: disable=C0111
|
|
|
|
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
|
|
|
|
namespace = condition.namespace
|
|
|
|
|
|
|
|
for target in condition.target:
|
|
|
|
for target in condition.target:
|
|
|
|
if target.type == 'variable':
|
|
|
|
if target.type == 'variable':
|
|
|
|
if condition.source == target.name:
|
|
|
|
if condition.source == target.name:
|
|
|
|
raise DictConsistencyError(_('target name and source name must be different: {}').format(condition.source), 11)
|
|
|
|
msg = f'target name and source name must be different: {condition.source}'
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(msg), 11)
|
|
|
|
|
|
|
|
target_names = '.'.join([normalize_family(name) \
|
|
|
|
|
|
|
|
for name in target.name.split('.')])
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
target_names = [normalize_family(name) for name in target.name.split('.')]
|
|
|
|
target.name = self.objectspace.paths.get_variable_path(target_names,
|
|
|
|
target.name = self.objectspace.paths.get_variable_path('.'.join(target_names), namespace)
|
|
|
|
condition.namespace,
|
|
|
|
|
|
|
|
)
|
|
|
|
except DictConsistencyError as err:
|
|
|
|
except DictConsistencyError as err:
|
|
|
|
# for optional variable
|
|
|
|
# for optional variable
|
|
|
|
if not target.optional or err.errno != 42:
|
|
|
|
if not target.optional or err.errno != 42:
|
|
|
|
raise err
|
|
|
|
raise err
|
|
|
|
elif target.type == 'family':
|
|
|
|
elif target.type == 'family':
|
|
|
|
|
|
|
|
target_names = '.'.join([normalize_family(name) \
|
|
|
|
|
|
|
|
for name in target.name.split('.')])
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
target_names = [normalize_family(name) for name in target.name.split('.')]
|
|
|
|
target.name = self.objectspace.paths.get_family_path(target_names,
|
|
|
|
target.name = self.objectspace.paths.get_family_path('.'.join(target_names), namespace)
|
|
|
|
condition.namespace,
|
|
|
|
|
|
|
|
)
|
|
|
|
except KeyError:
|
|
|
|
except KeyError:
|
|
|
|
raise DictConsistencyError(_('cannot found family {}').format(target.name), 12)
|
|
|
|
raise DictConsistencyError(_(f'cannot found family {target.name}'), 12)
|
|
|
|
|
|
|
|
elif target.type.endswith('list') and \
|
|
|
|
|
|
|
|
condition.name not in ['disabled_if_in', 'disabled_if_not_in']:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(target.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'target "{target.type}" not allow in condition "{condition.name}" '
|
|
|
|
|
|
|
|
f'in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 10)
|
|
|
|
|
|
|
|
|
|
|
|
def convert_xxxlist_to_variable(self): # pylint: disable=C0111
|
|
|
|
def convert_xxxlist_to_variable(self):
|
|
|
|
# transform *list to variable or family
|
|
|
|
"""transform *list to variable or family
|
|
|
|
|
|
|
|
"""
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
new_targets = []
|
|
|
|
new_targets = []
|
|
|
|
remove_targets = []
|
|
|
|
remove_targets = []
|
|
|
@ -214,33 +347,28 @@ class ConstrainteAnnotator:
|
|
|
|
condition.target.extend(new_targets)
|
|
|
|
condition.target.extend(new_targets)
|
|
|
|
|
|
|
|
|
|
|
|
def check_condition_fallback_optional(self):
|
|
|
|
def check_condition_fallback_optional(self):
|
|
|
|
# a condition with a fallback **and** the source variable doesn't exist
|
|
|
|
"""a condition with a fallback **and** the source variable doesn't exist
|
|
|
|
|
|
|
|
"""
|
|
|
|
remove_conditions = []
|
|
|
|
remove_conditions = []
|
|
|
|
for idx, condition in enumerate(self.objectspace.space.constraints.condition):
|
|
|
|
for idx, condition in enumerate(self.objectspace.space.constraints.condition):
|
|
|
|
# fallback
|
|
|
|
# fallback
|
|
|
|
if condition.fallback is True and not self.objectspace.paths.path_is_defined(condition.source):
|
|
|
|
if condition.fallback is True and \
|
|
|
|
|
|
|
|
not self.objectspace.paths.path_is_defined(condition.source):
|
|
|
|
apply_action = False
|
|
|
|
apply_action = False
|
|
|
|
if condition.name in ['disabled_if_in', 'mandatory_if_in', 'hidden_if_in']:
|
|
|
|
if condition.name in ['disabled_if_in', 'mandatory_if_in', 'hidden_if_in']:
|
|
|
|
apply_action = not condition.force_condition_on_fallback
|
|
|
|
apply_action = not condition.force_condition_on_fallback
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
apply_action = condition.force_inverse_condition_on_fallback
|
|
|
|
apply_action = condition.force_inverse_condition_on_fallback
|
|
|
|
if apply_action:
|
|
|
|
|
|
|
|
actions = self._get_condition_actions(condition.name)
|
|
|
|
|
|
|
|
for target in condition.target:
|
|
|
|
|
|
|
|
leader_or_variable, variables = self._get_family_variables_from_target(target)
|
|
|
|
|
|
|
|
for action_idx, action in enumerate(actions):
|
|
|
|
|
|
|
|
if action_idx == 0:
|
|
|
|
|
|
|
|
setattr(leader_or_variable, action, True)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
for variable in variables:
|
|
|
|
|
|
|
|
setattr(variable, action, True)
|
|
|
|
|
|
|
|
remove_conditions.append(idx)
|
|
|
|
remove_conditions.append(idx)
|
|
|
|
|
|
|
|
if apply_action:
|
|
|
|
|
|
|
|
self.force_actions_to_variable(condition)
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
remove_targets = []
|
|
|
|
remove_targets = []
|
|
|
|
# optional
|
|
|
|
# optional
|
|
|
|
for index, target in enumerate(condition.target):
|
|
|
|
for index, target in enumerate(condition.target):
|
|
|
|
if target.optional is True and not self.objectspace.paths.path_is_defined(target.name):
|
|
|
|
if target.optional is True and \
|
|
|
|
|
|
|
|
not self.objectspace.paths.path_is_defined(target.name):
|
|
|
|
remove_targets.append(index)
|
|
|
|
remove_targets.append(index)
|
|
|
|
remove_targets = list(set(remove_targets))
|
|
|
|
remove_targets = list(set(remove_targets))
|
|
|
|
remove_targets.sort(reverse=True)
|
|
|
|
remove_targets.sort(reverse=True)
|
|
|
@ -251,18 +379,24 @@ class ConstrainteAnnotator:
|
|
|
|
for idx in remove_conditions:
|
|
|
|
for idx in remove_conditions:
|
|
|
|
self.objectspace.space.constraints.condition.pop(idx)
|
|
|
|
self.objectspace.space.constraints.condition.pop(idx)
|
|
|
|
|
|
|
|
|
|
|
|
def _get_condition_actions(self, condition_name):
|
|
|
|
def force_actions_to_variable(self,
|
|
|
|
if condition_name.startswith('disabled_if_'):
|
|
|
|
condition: 'self.objectspace.condition',
|
|
|
|
return ['disabled']
|
|
|
|
) -> None:
|
|
|
|
if condition_name.startswith('hidden_if_'):
|
|
|
|
"""force property to a variable
|
|
|
|
return ['hidden', 'frozen', 'force_default_on_freeze']
|
|
|
|
for example disabled_if_not_in => variable.disabled = True
|
|
|
|
if condition_name.startswith('mandatory_if_'):
|
|
|
|
"""
|
|
|
|
return ['mandatory']
|
|
|
|
actions = get_actions_from_condition(condition.name)
|
|
|
|
if condition_name == 'auto_hidden_if_not_in':
|
|
|
|
for target in condition.target:
|
|
|
|
return ['auto_frozen']
|
|
|
|
leader_or_var, variables = self._get_family_variables_from_target(target)
|
|
|
|
|
|
|
|
main_action = actions[0]
|
|
|
|
|
|
|
|
setattr(leader_or_var, main_action, True)
|
|
|
|
|
|
|
|
for action in actions[1:]:
|
|
|
|
|
|
|
|
for variable in variables:
|
|
|
|
|
|
|
|
setattr(variable, action, True)
|
|
|
|
|
|
|
|
|
|
|
|
def check_choice_option_condition(self):
|
|
|
|
def check_choice_option_condition(self):
|
|
|
|
# remove condition for ChoiceOption that don't have param
|
|
|
|
"""remove condition for ChoiceOption that don't have param
|
|
|
|
|
|
|
|
"""
|
|
|
|
remove_conditions = []
|
|
|
|
remove_conditions = []
|
|
|
|
for condition_idx, condition in enumerate(self.objectspace.space.constraints.condition):
|
|
|
|
for condition_idx, condition in enumerate(self.objectspace.space.constraints.condition):
|
|
|
|
namespace = condition.namespace
|
|
|
|
namespace = condition.namespace
|
|
|
@ -273,54 +407,48 @@ class ConstrainteAnnotator:
|
|
|
|
)
|
|
|
|
)
|
|
|
|
if suffix:
|
|
|
|
if suffix:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'the source "{condition.source}" in condition cannot be a dynamic variable in {xmlfiles}'), 20)
|
|
|
|
msg = _(f'the source "{condition.source}" in condition cannot be a dynamic '
|
|
|
|
valid_enum = None
|
|
|
|
f'variable in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 20)
|
|
|
|
# FIXME only string?
|
|
|
|
# FIXME only string?
|
|
|
|
if condition.source in self.valid_enums and self.valid_enums[condition.source]['type'] == 'string':
|
|
|
|
if condition.source in self.valid_enums and \
|
|
|
|
|
|
|
|
self.valid_enums[condition.source]['type'] == 'string':
|
|
|
|
valid_enum = self.valid_enums[condition.source]['values']
|
|
|
|
valid_enum = self.valid_enums[condition.source]['values']
|
|
|
|
if valid_enum is not None:
|
|
|
|
remove_param = [param_idx for param_idx, param in enumerate(condition.param) \
|
|
|
|
remove_param = []
|
|
|
|
if param.text not in valid_enum]
|
|
|
|
for param_idx, param in enumerate(condition.param):
|
|
|
|
|
|
|
|
if param.text not in valid_enum:
|
|
|
|
|
|
|
|
remove_param.append(param_idx)
|
|
|
|
|
|
|
|
remove_param.sort(reverse=True)
|
|
|
|
remove_param.sort(reverse=True)
|
|
|
|
for idx in remove_param:
|
|
|
|
for idx in remove_param:
|
|
|
|
del condition.param[idx]
|
|
|
|
del condition.param[idx]
|
|
|
|
if condition.param == []:
|
|
|
|
if not condition.param and condition.name.endswith('_if_not_in'):
|
|
|
|
for target in condition.target:
|
|
|
|
self.force_actions_to_variable(condition)
|
|
|
|
leader_or_variable, variables = self._get_family_variables_from_target(target)
|
|
|
|
|
|
|
|
if condition.name == 'disabled_if_not_in':
|
|
|
|
|
|
|
|
leader_or_variable.disabled = True
|
|
|
|
|
|
|
|
elif condition.name == 'hidden_if_not_in':
|
|
|
|
|
|
|
|
leader_or_variable.hidden = True
|
|
|
|
|
|
|
|
for variable in variables:
|
|
|
|
|
|
|
|
variable.frozen = True
|
|
|
|
|
|
|
|
variable.force_default_on_freeze = True
|
|
|
|
|
|
|
|
elif condition.name == 'mandatory_if_not_in':
|
|
|
|
|
|
|
|
leader_or_variable.mandatory = True
|
|
|
|
|
|
|
|
remove_conditions.append(condition_idx)
|
|
|
|
remove_conditions.append(condition_idx)
|
|
|
|
remove_conditions = list(set(remove_conditions))
|
|
|
|
|
|
|
|
remove_conditions.sort(reverse=True)
|
|
|
|
remove_conditions.sort(reverse=True)
|
|
|
|
for idx in remove_conditions:
|
|
|
|
for idx in remove_conditions:
|
|
|
|
self.objectspace.space.constraints.condition.pop(idx)
|
|
|
|
self.objectspace.space.constraints.condition.pop(idx)
|
|
|
|
|
|
|
|
|
|
|
|
def remove_condition_with_empty_target(self):
|
|
|
|
def remove_condition_with_empty_target(self):
|
|
|
|
|
|
|
|
"""remove condition with empty target
|
|
|
|
|
|
|
|
"""
|
|
|
|
# optional target are remove, condition could be empty
|
|
|
|
# optional target are remove, condition could be empty
|
|
|
|
remove_conditions = [condition_idx for condition_idx, condition in enumerate(self.objectspace.space.constraints.condition) if not condition.target]
|
|
|
|
remove_conditions = [condition_idx for condition_idx, condition in \
|
|
|
|
|
|
|
|
enumerate(self.objectspace.space.constraints.condition) \
|
|
|
|
|
|
|
|
if not condition.target]
|
|
|
|
remove_conditions.sort(reverse=True)
|
|
|
|
remove_conditions.sort(reverse=True)
|
|
|
|
for idx in remove_conditions:
|
|
|
|
for idx in remove_conditions:
|
|
|
|
self.objectspace.space.constraints.condition.pop(idx)
|
|
|
|
self.objectspace.space.constraints.condition.pop(idx)
|
|
|
|
|
|
|
|
|
|
|
|
def convert_condition(self):
|
|
|
|
def convert_condition(self):
|
|
|
|
|
|
|
|
"""valid and manage <condition>
|
|
|
|
|
|
|
|
"""
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
for condition in self.objectspace.space.constraints.condition:
|
|
|
|
inverse = condition.name.endswith('_if_not_in')
|
|
|
|
actions = get_actions_from_condition(condition.name)
|
|
|
|
actions = self._get_condition_actions(condition.name)
|
|
|
|
|
|
|
|
for param in condition.param:
|
|
|
|
for param in condition.param:
|
|
|
|
text = getattr(param, 'text', None)
|
|
|
|
text = getattr(param, 'text', None)
|
|
|
|
for target in condition.target:
|
|
|
|
for target in condition.target:
|
|
|
|
leader_or_variable, variables = self._get_family_variables_from_target(target)
|
|
|
|
leader_or_variable, variables = self._get_family_variables_from_target(target)
|
|
|
|
# if option is already disable, do not apply disable_if_in
|
|
|
|
# if option is already disable, do not apply disable_if_in
|
|
|
|
# check only the first action (example of multiple actions: 'hidden', 'frozen', 'force_default_on_freeze')
|
|
|
|
# check only the first action (example of multiple actions:
|
|
|
|
|
|
|
|
# 'hidden', 'frozen', 'force_default_on_freeze')
|
|
|
|
main_action = actions[0]
|
|
|
|
main_action = actions[0]
|
|
|
|
if getattr(leader_or_variable, main_action, False) is True:
|
|
|
|
if getattr(leader_or_variable, main_action, False) is True:
|
|
|
|
continue
|
|
|
|
continue
|
|
|
@ -328,201 +456,155 @@ class ConstrainteAnnotator:
|
|
|
|
(leader_or_variable.auto_save or leader_or_variable.auto_freeze) and \
|
|
|
|
(leader_or_variable.auto_save or leader_or_variable.auto_freeze) and \
|
|
|
|
'force_default_on_freeze' in actions:
|
|
|
|
'force_default_on_freeze' in actions:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(leader_or_variable.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(leader_or_variable.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'cannot have auto_freeze or auto_store with the hidden_if_in or hidden_if_not_in variable "{leader_or_variable.name}" in {xmlfiles}'), 51)
|
|
|
|
msg = _(f'cannot have auto_freeze or auto_store with the hidden_if_in or '
|
|
|
|
for idx, action in enumerate(actions):
|
|
|
|
f'hidden_if_not_in variable "{leader_or_variable.name}" '
|
|
|
|
prop = self.objectspace.property_(leader_or_variable.xmlfiles)
|
|
|
|
f'in {xmlfiles}')
|
|
|
|
prop.type = 'calculation'
|
|
|
|
raise DictConsistencyError(msg, 51)
|
|
|
|
prop.inverse = inverse
|
|
|
|
self.build_property(leader_or_variable,
|
|
|
|
prop.source = condition.source
|
|
|
|
text,
|
|
|
|
prop.expected = text
|
|
|
|
condition,
|
|
|
|
prop.name = action
|
|
|
|
main_action,
|
|
|
|
if idx == 0:
|
|
|
|
)
|
|
|
|
# main action is for the variable or family
|
|
|
|
for action in actions[1:]:
|
|
|
|
if not hasattr(leader_or_variable, 'property'):
|
|
|
|
# other actions are set to the variable or children of family
|
|
|
|
leader_or_variable.property = []
|
|
|
|
for variable in variables:
|
|
|
|
leader_or_variable.property.append(prop)
|
|
|
|
self.build_property(variable,
|
|
|
|
else:
|
|
|
|
text,
|
|
|
|
# other actions are set to the variable or children of family
|
|
|
|
condition,
|
|
|
|
for variable in variables:
|
|
|
|
action,
|
|
|
|
if not hasattr(variable, 'property'):
|
|
|
|
)
|
|
|
|
variable.property = []
|
|
|
|
|
|
|
|
variable.property.append(prop)
|
|
|
|
|
|
|
|
del self.objectspace.space.constraints.condition
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _set_valid_enum(self,
|
|
|
|
def build_property(self,
|
|
|
|
variable,
|
|
|
|
obj,
|
|
|
|
check,
|
|
|
|
text: Any,
|
|
|
|
):
|
|
|
|
condition: 'self.objectspace.condition',
|
|
|
|
type_ = variable.type
|
|
|
|
action: str,
|
|
|
|
target = check.target
|
|
|
|
) -> 'self.objectspace.property_':
|
|
|
|
# value for choice's variable is mandatory
|
|
|
|
"""build property_ for a condition
|
|
|
|
variable.mandatory = True
|
|
|
|
"""
|
|
|
|
# build choice
|
|
|
|
prop = self.objectspace.property_(obj.xmlfiles)
|
|
|
|
variable.choice = []
|
|
|
|
prop.type = 'calculation'
|
|
|
|
variable.type = 'choice'
|
|
|
|
prop.inverse = condition.name.endswith('_if_not_in')
|
|
|
|
|
|
|
|
prop.source = condition.source
|
|
|
|
|
|
|
|
prop.expected = text
|
|
|
|
|
|
|
|
prop.name = action
|
|
|
|
|
|
|
|
if not hasattr(obj, 'property'):
|
|
|
|
|
|
|
|
obj.property = []
|
|
|
|
|
|
|
|
obj.property.append(prop)
|
|
|
|
|
|
|
|
|
|
|
|
has_variable = False
|
|
|
|
def convert_check(self) -> None:
|
|
|
|
values = []
|
|
|
|
"""valid and manage <check>
|
|
|
|
for param in check.param:
|
|
|
|
"""
|
|
|
|
if has_variable:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable "{variable.name}" in {xmlfiles}'), 5)
|
|
|
|
|
|
|
|
param_type = type_
|
|
|
|
|
|
|
|
if param.type == 'variable':
|
|
|
|
|
|
|
|
has_variable = True
|
|
|
|
|
|
|
|
param_variable = self.objectspace.paths.get_variable_obj(param.text)
|
|
|
|
|
|
|
|
if param.optional is True:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'optional parameter in valid_enum for variable "{variable.name}" is not allowed in {xmlfiles}'), 14)
|
|
|
|
|
|
|
|
if not param_variable.multi:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'only multi "variable" parameter is allowed for valid_enum of variable "{variable.name}" in {xmlfiles}'), 6)
|
|
|
|
|
|
|
|
param_type = 'calculation'
|
|
|
|
|
|
|
|
value = param.text
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
if 'type' in vars(param) and type_ != param.type:
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'parameter in valid_enum has incompatible type "{param.type}" with type of the variable "{variable.name}" ("{type_}") in {xmlfiles}'), 7)
|
|
|
|
|
|
|
|
if hasattr(param, 'text'):
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
value = CONVERT_OPTION[type_].get('func', str)(param.text)
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'unable to change type of a valid_enum entry "{param.text}" is not a valid "{type_}" for "{variable.name}"'), 13)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
if param.type == 'number':
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(param.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'param type is number, so value is mandatory for valid_enum of variable "{variable.name}" in {xmlfiles}'), 8)
|
|
|
|
|
|
|
|
value = None
|
|
|
|
|
|
|
|
values.append(value)
|
|
|
|
|
|
|
|
choice = self.objectspace.choice(variable.xmlfiles)
|
|
|
|
|
|
|
|
choice.name = value
|
|
|
|
|
|
|
|
choice.type = param_type
|
|
|
|
|
|
|
|
variable.choice.append(choice)
|
|
|
|
|
|
|
|
if has_variable:
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# FIXME really?
|
|
|
|
|
|
|
|
if param_type != 'calculation':
|
|
|
|
|
|
|
|
self.valid_enums[target] = {'type': type_,
|
|
|
|
|
|
|
|
'values': values,
|
|
|
|
|
|
|
|
'xmlfiles': check.xmlfiles,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
# check value or set first choice value has default value
|
|
|
|
|
|
|
|
if hasattr(variable, 'value'):
|
|
|
|
|
|
|
|
for value in variable.value:
|
|
|
|
|
|
|
|
if value.name not in values:
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'value "{value.name}" of variable "{variable.name}" is not in list of all expected values ({values})'), 15)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
new_value = self.objectspace.value(check.xmlfiles)
|
|
|
|
|
|
|
|
new_value.name = values[0]
|
|
|
|
|
|
|
|
new_value.type = type_
|
|
|
|
|
|
|
|
variable.value = [new_value]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_check(self):
|
|
|
|
|
|
|
|
for check in self.objectspace.space.constraints.check:
|
|
|
|
for check in self.objectspace.space.constraints.check:
|
|
|
|
variable = self.objectspace.paths.get_variable_obj(check.target)
|
|
|
|
variable = self.objectspace.paths.get_variable_obj(check.target)
|
|
|
|
name = check.name
|
|
|
|
if check.name == 'valid_entier':
|
|
|
|
if name == 'valid_entier':
|
|
|
|
|
|
|
|
if not hasattr(check, 'param'):
|
|
|
|
if not hasattr(check, 'param'):
|
|
|
|
raise DictConsistencyError(_('{} must have, at least, 1 param').format(name), 17)
|
|
|
|
msg = _(f'{check.name} must have, at least, 1 param')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 17)
|
|
|
|
for param in check.param:
|
|
|
|
for param in check.param:
|
|
|
|
if param.type != 'number':
|
|
|
|
if param.type != 'number':
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'param in "valid_entier" must be an "integer", not "{param.type}" in {xmlfiles}'), 18)
|
|
|
|
msg = _(f'param in "valid_entier" must be an "integer", not "{param.type}"'
|
|
|
|
|
|
|
|
f' in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 18)
|
|
|
|
if param.name == 'mini':
|
|
|
|
if param.name == 'mini':
|
|
|
|
variable.min_number = int(param.text)
|
|
|
|
variable.min_number = int(param.text)
|
|
|
|
elif param.name == 'maxi':
|
|
|
|
elif param.name == 'maxi':
|
|
|
|
variable.max_number = int(param.text)
|
|
|
|
variable.max_number = int(param.text)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'unknown parameter "{param.name}" in check "valid_entier" for variable "{check.target}" in {xmlfiles}'), 19)
|
|
|
|
msg = _(f'unknown parameter "{param.name}" in check "valid_entier" '
|
|
|
|
|
|
|
|
f'for variable "{check.target}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 19)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
check_ = self.objectspace.check(variable.xmlfiles)
|
|
|
|
|
|
|
|
check_.name = name
|
|
|
|
|
|
|
|
check_.warnings_only = check.warnings_only
|
|
|
|
|
|
|
|
if hasattr(check, 'param'):
|
|
|
|
|
|
|
|
check_.param = check.param
|
|
|
|
|
|
|
|
if not hasattr(variable, 'check'):
|
|
|
|
if not hasattr(variable, 'check'):
|
|
|
|
variable.check = []
|
|
|
|
variable.check = []
|
|
|
|
variable.check.append(check_)
|
|
|
|
variable.check.append(check)
|
|
|
|
del self.objectspace.space.constraints.check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_fill(self): # pylint: disable=C0111,R0912
|
|
|
|
def convert_fill(self) -> None:
|
|
|
|
# sort fill/auto by index
|
|
|
|
"""valid and manage <fill>
|
|
|
|
fills = {fill.index: fill for idx, fill in enumerate(self.objectspace.space.constraints.fill)}
|
|
|
|
"""
|
|
|
|
indexes = list(fills.keys())
|
|
|
|
|
|
|
|
indexes.sort()
|
|
|
|
|
|
|
|
targets = []
|
|
|
|
targets = []
|
|
|
|
for idx in indexes:
|
|
|
|
for fill in self.objectspace.space.constraints.fill:
|
|
|
|
fill = fills[idx]
|
|
|
|
|
|
|
|
# test if it's redefined calculation
|
|
|
|
# test if it's redefined calculation
|
|
|
|
if fill.target in targets:
|
|
|
|
if fill.target in targets:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'A fill already exists for the target of "{fill.target}" created in {xmlfiles}'), 24)
|
|
|
|
msg = _(f'A fill already exists for the target of "{fill.target}" created '
|
|
|
|
|
|
|
|
f'in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 24)
|
|
|
|
targets.append(fill.target)
|
|
|
|
targets.append(fill.target)
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
# test if the function exists
|
|
|
|
if fill.name not in self.functions:
|
|
|
|
if fill.name not in self.functions:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'cannot find fill function "{fill.name}" in {xmlfiles}'), 25)
|
|
|
|
msg = _(f'cannot find fill function "{fill.name}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 25)
|
|
|
|
|
|
|
|
|
|
|
|
namespace = fill.namespace
|
|
|
|
|
|
|
|
# let's replace the target by the path
|
|
|
|
# let's replace the target by the path
|
|
|
|
fill.target, suffix = self.objectspace.paths.get_variable_path(fill.target,
|
|
|
|
fill.target, suffix = self.objectspace.paths.get_variable_path(fill.target,
|
|
|
|
namespace,
|
|
|
|
fill.namespace,
|
|
|
|
with_suffix=True,
|
|
|
|
with_suffix=True,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
if suffix is not None:
|
|
|
|
if suffix is not None:
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
raise DictConsistencyError(_(f'Cannot add fill function to "{fill.target}" only for the suffix "{suffix}" in {xmlfiles}'), 26)
|
|
|
|
msg = _(f'Cannot add fill function to "{fill.target}" only '
|
|
|
|
|
|
|
|
f'for the suffix "{suffix}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 26)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# get the target variable
|
|
|
|
variable = self.objectspace.paths.get_variable_obj(fill.target)
|
|
|
|
variable = self.objectspace.paths.get_variable_obj(fill.target)
|
|
|
|
value = self.objectspace.value(variable.xmlfiles)
|
|
|
|
|
|
|
|
|
|
|
|
# create an object value
|
|
|
|
|
|
|
|
value = self.objectspace.value(fill.xmlfiles)
|
|
|
|
value.type = 'calculation'
|
|
|
|
value.type = 'calculation'
|
|
|
|
value.name = fill.name
|
|
|
|
value.name = fill.name
|
|
|
|
if hasattr(fill, 'param'):
|
|
|
|
|
|
|
|
param_to_delete = []
|
|
|
|
|
|
|
|
for fill_idx, param in enumerate(fill.param):
|
|
|
|
|
|
|
|
if param.type not in ['suffix', 'string'] and not hasattr(param, 'text'):
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f"All '{param.type}' variables must have a value in order to calculate {fill.target} in {xmlfiles}"), 27)
|
|
|
|
|
|
|
|
if param.type == 'suffix':
|
|
|
|
|
|
|
|
if hasattr(param, 'text'):
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'"{param.type}" variables must not have a value in order to calculate "{fill.target}" in {xmlfiles}'), 28)
|
|
|
|
|
|
|
|
if not self.objectspace.paths.variable_is_dynamic(fill.target):
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
|
|
|
|
raise DictConsistencyError(_(f'Cannot set suffix target to the none dynamic variable "{fill.target}" in {xmlfiles}'), 53)
|
|
|
|
|
|
|
|
if param.type == 'string':
|
|
|
|
|
|
|
|
if not hasattr(param, 'text'):
|
|
|
|
|
|
|
|
param.text = None
|
|
|
|
|
|
|
|
if param.type == 'variable':
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
param.text, suffix = self.objectspace.paths.get_variable_path(param.text,
|
|
|
|
|
|
|
|
namespace,
|
|
|
|
|
|
|
|
with_suffix=True,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
if suffix:
|
|
|
|
|
|
|
|
param.suffix = suffix
|
|
|
|
|
|
|
|
except DictConsistencyError as err:
|
|
|
|
|
|
|
|
if err.errno != 42:
|
|
|
|
|
|
|
|
raise err
|
|
|
|
|
|
|
|
if param.optional is False:
|
|
|
|
|
|
|
|
raise err
|
|
|
|
|
|
|
|
param_to_delete.append(fill_idx)
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
param.notraisepropertyerror = None
|
|
|
|
|
|
|
|
param_to_delete.sort(reverse=True)
|
|
|
|
|
|
|
|
for param_idx in param_to_delete:
|
|
|
|
|
|
|
|
fill.param.pop(param_idx)
|
|
|
|
|
|
|
|
value.param = fill.param
|
|
|
|
|
|
|
|
variable.value = [value]
|
|
|
|
variable.value = [value]
|
|
|
|
del self.objectspace.space.constraints.fill
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def remove_constraints(self):
|
|
|
|
# manage params
|
|
|
|
if hasattr(self.objectspace.space.constraints, 'index'):
|
|
|
|
if not hasattr(fill, 'param'):
|
|
|
|
del self.objectspace.space.constraints.index
|
|
|
|
continue
|
|
|
|
del self.objectspace.space.constraints.namespace
|
|
|
|
self.convert_fill_param(fill)
|
|
|
|
del self.objectspace.space.constraints.xmlfiles
|
|
|
|
if fill.param:
|
|
|
|
if vars(self.objectspace.space.constraints): # pragma: no cover
|
|
|
|
value.param = fill.param
|
|
|
|
raise Exception('constraints again?')
|
|
|
|
|
|
|
|
del self.objectspace.space.constraints
|
|
|
|
def convert_fill_param(self,
|
|
|
|
|
|
|
|
fill: "self.objectspace.fill",
|
|
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
|
|
""" valid and convert fill's param
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
param_to_delete = []
|
|
|
|
|
|
|
|
for param_idx, param in enumerate(fill.param):
|
|
|
|
|
|
|
|
if param.type == 'string' and not hasattr(param, 'text'):
|
|
|
|
|
|
|
|
param.text = None
|
|
|
|
|
|
|
|
if param.type == 'suffix':
|
|
|
|
|
|
|
|
if hasattr(param, 'text'):
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'"{param.type}" variables must not have a value in order '
|
|
|
|
|
|
|
|
f'to calculate "{fill.target}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 28)
|
|
|
|
|
|
|
|
if not self.objectspace.paths.variable_is_dynamic(fill.target):
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
|
|
|
|
msg = _('Cannot set suffix target to the none dynamic variable '
|
|
|
|
|
|
|
|
f'"{fill.target}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 53)
|
|
|
|
|
|
|
|
elif not hasattr(param, 'text'):
|
|
|
|
|
|
|
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
|
|
|
|
|
|
|
msg = _(f'All "{param.type}" variables must have a value in order '
|
|
|
|
|
|
|
|
f'to calculate "{fill.target}" in {xmlfiles}')
|
|
|
|
|
|
|
|
raise DictConsistencyError(msg, 27)
|
|
|
|
|
|
|
|
if param.type == 'variable':
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
text, suffix = self.objectspace.paths.get_variable_path(param.text,
|
|
|
|
|
|
|
|
fill.namespace,
|
|
|
|
|
|
|
|
with_suffix=True,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
param.text = text
|
|
|
|
|
|
|
|
if suffix:
|
|
|
|
|
|
|
|
param.suffix = suffix
|
|
|
|
|
|
|
|
except DictConsistencyError as err:
|
|
|
|
|
|
|
|
if err.errno != 42 or not param.optional:
|
|
|
|
|
|
|
|
raise err
|
|
|
|
|
|
|
|
param_to_delete.append(param_idx)
|
|
|
|
|
|
|
|
param_to_delete.sort(reverse=True)
|
|
|
|
|
|
|
|
for param_idx in param_to_delete:
|
|
|
|
|
|
|
|
fill.param.pop(param_idx)
|
|
|
|