test error number

This commit is contained in:
Emmanuel Garette 2020-12-24 12:41:10 +01:00
parent fffd52eec6
commit 04ab1edd36
61 changed files with 164 additions and 121 deletions

View file

@ -6,6 +6,10 @@ from .variable import CONVERT_OPTION
from ..i18n import _ from ..i18n import _
from ..utils import normalize_family from ..utils import normalize_family
from ..error import DictConsistencyError from ..error import DictConsistencyError
from ..config import Config
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']
@ -20,6 +24,8 @@ 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.convert_auto_freeze()
self.valid_enums = {} self.valid_enums = {}
if hasattr(self.objectspace.space.constraints, 'check'): if hasattr(self.objectspace.space.constraints, 'check'):
self.check_check() self.check_check()
@ -39,12 +45,46 @@ class ConstrainteAnnotator:
self.convert_fill() self.convert_fill()
self.remove_constraints() self.remove_constraints()
def convert_auto_freeze(self): # pylint: disable=C0111
if not hasattr(self.objectspace.space, 'variables'):
return
def _convert_auto_freeze(variable, namespace):
if variable.auto_freeze:
if namespace != Config['variable_namespace']:
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'auto_freeze is not allowed in extra "{namespace}" in {xmlfiles}'), 49)
new_condition = self.objectspace.condition(variable.xmlfiles)
new_condition.name = 'auto_hidden_if_not_in'
new_condition.namespace = namespace
new_condition.source = FREEZE_AUTOFREEZE_VARIABLE
new_param = self.objectspace.param(variable.xmlfiles)
new_param.text = 'oui'
new_condition.param = [new_param]
new_target = self.objectspace.target(variable.xmlfiles)
new_target.type = 'variable'
new_target.name = variable.name
new_condition.target = [new_target]
if not hasattr(self.objectspace.space.constraints, 'condition'):
self.objectspace.space.constraints.condition = []
self.objectspace.space.constraints.condition.append(new_condition)
for variables in self.objectspace.space.variables.values():
if hasattr(variables, 'family'):
namespace = variables.name
for family in variables.family.values():
if hasattr(family, 'variable'):
for variable in family.variable.values():
if isinstance(variable, self.objectspace.leadership):
for follower in variable.variable:
_convert_auto_freeze(follower, namespace)
else:
_convert_auto_freeze(variable, namespace)
def check_check(self): def check_check(self):
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}')) raise DictConsistencyError(_(f'cannot find check function "{check.name}" in {xmlfiles}'), 1)
if hasattr(check, 'param'): if hasattr(check, 'param'):
param_option_indexes = [] param_option_indexes = []
for idx, param in enumerate(check.param): for idx, param in enumerate(check.param):
@ -53,7 +93,7 @@ class ConstrainteAnnotator:
param_option_indexes.append(idx) param_option_indexes.append(idx)
else: else:
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}')) raise DictConsistencyError(_(f'cannot find check param "{param.text}" in {xmlfiles}'), 2)
if param.type != 'variable': if param.type != 'variable':
param.notraisepropertyerror = None param.notraisepropertyerror = None
param_option_indexes = list(set(param_option_indexes)) param_option_indexes = list(set(param_option_indexes))
@ -84,9 +124,9 @@ class ConstrainteAnnotator:
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']) old_xmlfiles = self.objectspace.display_xmlfiles(self.valid_enums[check.target]['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?')) raise DictConsistencyError(_(f'valid_enum define in {xmlfiles} but already set in {old_xmlfiles} for "{check.target}", did you forget remove_check?'), 3)
if not hasattr(check, 'param'): if not hasattr(check, 'param'):
raise DictConsistencyError(_(f'param is mandatory for a valid_enum of variable {check.target}')) raise DictConsistencyError(_(f'param is mandatory for a valid_enum of variable {check.target}'), 4)
variable = self.objectspace.paths.get_variable_obj(check.target) variable = self.objectspace.paths.get_variable_obj(check.target)
values = self.load_params_in_valid_enum(check.param, values = self.load_params_in_valid_enum(check.param,
variable.name, variable.name,
@ -113,18 +153,18 @@ class ConstrainteAnnotator:
for param in params: for param in params:
if param.type == 'variable': if param.type == 'variable':
if has_variable is not None: if has_variable is not None:
raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}')) raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}'), 5)
has_variable = True has_variable = True
variable = self.objectspace.paths.get_variable_obj(param.text) variable = self.objectspace.paths.get_variable_obj(param.text)
if not variable.multi: if not variable.multi:
raise DictConsistencyError(_(f'only multi "variable" parameter is allowed for valid_enum of variable {variable_name}')) raise DictConsistencyError(_(f'only multi "variable" parameter is allowed for valid_enum of variable {variable_name}'), 6)
values = param.text values = param.text
else: else:
if has_variable: if has_variable:
raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}')) raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}'), 7)
if not hasattr(param, 'text'): if not hasattr(param, 'text'):
if param.type == 'number': if param.type == 'number':
raise DictConsistencyError(_(f'value is mandatory for valid_enum of variable {variable_name}')) raise DictConsistencyError(_(f'value is mandatory for valid_enum of variable {variable_name}'), 8)
values.append(None) values.append(None)
else: else:
values.append(param.text) values.append(param.text)
@ -156,10 +196,11 @@ class ConstrainteAnnotator:
def check_params_target(self): def check_params_target(self):
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'):
raise DictConsistencyError(_('target is mandatory in condition')) raise DictConsistencyError(_('target is mandatory in condition'), 9)
for target in condition.target: for target in condition.target:
if target.type.endswith('list') and condition.name not in ['disabled_if_in', 'disabled_if_not_in']: if target.type.endswith('list') and condition.name not in ['disabled_if_in', 'disabled_if_not_in']:
raise DictConsistencyError(_(f'target in condition for {target.type} not allow in {condition.name}')) 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 def filter_targets(self): # pylint: disable=C0111
for condition_idx, condition in enumerate(self.objectspace.space.constraints.condition): for condition_idx, condition in enumerate(self.objectspace.space.constraints.condition):
@ -167,7 +208,7 @@ class ConstrainteAnnotator:
for idx, target in enumerate(condition.target): for idx, target in enumerate(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)) raise DictConsistencyError(_('target name and source name must be different: {}').format(condition.source), 11)
try: try:
target_names = [normalize_family(name) for name in target.name.split('.')] target_names = [normalize_family(name) for name in target.name.split('.')]
target.name = self.objectspace.paths.get_variable_path('.'.join(target_names), namespace) target.name = self.objectspace.paths.get_variable_path('.'.join(target_names), namespace)
@ -179,7 +220,7 @@ class ConstrainteAnnotator:
target_names = [normalize_family(name) for name in target.name.split('.')] target_names = [normalize_family(name) for name in target.name.split('.')]
target.name = self.objectspace.paths.get_family_path('.'.join(target_names), namespace) target.name = self.objectspace.paths.get_family_path('.'.join(target_names), namespace)
except KeyError: except KeyError:
raise DictConsistencyError(_('cannot found family {}').format(target.name)) raise DictConsistencyError(_('cannot found family {}').format(target.name), 12)
def convert_xxxlist_to_variable(self): # pylint: disable=C0111 def convert_xxxlist_to_variable(self): # pylint: disable=C0111
# transform *list to variable or family # transform *list to variable or family
@ -318,6 +359,11 @@ class ConstrainteAnnotator:
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
if isinstance(leader_or_variable, self.objectspace.variable) and \
(leader_or_variable.auto_save or leader_or_variable.auto_freeze) and \
'force_default_on_freeze' in actions:
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)
for idx, action in enumerate(actions): for idx, action in enumerate(actions):
prop = self.objectspace.property_(leader_or_variable.xmlfiles) prop = self.objectspace.property_(leader_or_variable.xmlfiles)
prop.type = 'calculation' prop.type = 'calculation'
@ -368,7 +414,7 @@ class ConstrainteAnnotator:
else: else:
choice.name = value choice.name = value
except: except:
raise DictConsistencyError(_(f'unable to change type of a valid_enum entry "{value}" is not a valid "{type_}" for "{variable.name}"')) raise DictConsistencyError(_(f'unable to change type of a valid_enum entry "{value}" is not a valid "{type_}" for "{variable.name}"'), 13)
if choice.name == '': if choice.name == '':
choice.name = None choice.name = None
choices.append(choice.name) choices.append(choice.name)
@ -381,16 +427,16 @@ class ConstrainteAnnotator:
try: try:
cvalue = CONVERT_OPTION[type_].get('func', str)(value.name) cvalue = CONVERT_OPTION[type_].get('func', str)(value.name)
except: except:
raise DictConsistencyError(_(f'unable to change type of value "{value}" is not a valid "{type_}" for "{variable.name}"')) raise DictConsistencyError(_(f'unable to change type of value "{value}" is not a valid "{type_}" for "{variable.name}"'), 14)
if cvalue not in choices: if cvalue not in choices:
raise DictConsistencyError(_('value "{}" of variable "{}" is not in list of all expected values ({})').format(value.name, variable.name, choices)) raise DictConsistencyError(_('value "{}" of variable "{}" is not in list of all expected values ({})').format(value.name, variable.name, choices), 15)
else: else:
new_value = self.objectspace.value(variable.xmlfiles) new_value = self.objectspace.value(variable.xmlfiles)
new_value.name = choices[0] new_value.name = choices[0]
new_value.type = type_ new_value.type = type_
variable.value = [new_value] variable.value = [new_value]
if not variable.choice: if not variable.choice:
raise DictConsistencyError(_('empty valid enum is not allowed for variable {}').format(variable.name)) raise DictConsistencyError(_('empty valid enum is not allowed for variable {}').format(variable.name), 16)
variable.type = 'choice' variable.type = 'choice'
def convert_check(self): def convert_check(self):
@ -399,16 +445,16 @@ class ConstrainteAnnotator:
name = check.name name = check.name
if 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)) raise DictConsistencyError(_('{} must have, at least, 1 param').format(name), 17)
for param in check.param: for param in check.param:
if param.type not in ['string', 'number']: if param.type not in ['string', 'number']:
raise DictConsistencyError(_(f'param in "valid_entier" must not be a "{param.type}"')) raise DictConsistencyError(_(f'param in "valid_entier" must not be a "{param.type}"'), 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:
raise DictConsistencyError(_(f'unknown parameter {param.text} in check "valid_entier" for variable {check.target}')) raise DictConsistencyError(_(f'unknown parameter {param.text} in check "valid_entier" for variable {check.target}'), 19)
else: else:
check_ = self.objectspace.check(variable.xmlfiles) check_ = self.objectspace.check(variable.xmlfiles)
if name == 'valid_differ': if name == 'valid_differ':
@ -417,23 +463,23 @@ class ConstrainteAnnotator:
params_len = 1 params_len = 1
if len(check.param) != params_len: if len(check.param) != params_len:
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles) xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}')) raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}'), 20)
elif name == 'valid_ipnetmask': elif name == 'valid_ipnetmask':
params_len = 1 params_len = 1
if len(check.param) != params_len: if len(check.param) != params_len:
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles) xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}')) raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}'), 21)
name = 'valid_ip_netmask' name = 'valid_ip_netmask'
elif name == 'valid_broadcast': elif name == 'valid_broadcast':
params_len = 2 params_len = 2
if len(check.param) != params_len: if len(check.param) != params_len:
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles) xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}')) raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}'), 22)
elif name == 'valid_in_network': elif name == 'valid_in_network':
if len(check.param) not in (1, 2): if len(check.param) not in (1, 2):
params_len = 2 params_len = 2
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles) xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}')) raise DictConsistencyError(_(f'{name} must have {params_len} param in {xmlfiles}'), 23)
check_.name = name check_.name = name
check_.warnings_only = check.warnings_only check_.warnings_only = check.warnings_only
if hasattr(check, 'param'): if hasattr(check, 'param'):
@ -454,11 +500,11 @@ class ConstrainteAnnotator:
# 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}')) raise DictConsistencyError(_(f'A fill already exists for the target of "{fill.target}" created in {xmlfiles}'), 24)
targets.append(fill.target) targets.append(fill.target)
# #
if fill.name not in self.functions: if fill.name not in self.functions:
raise DictConsistencyError(_('cannot find fill function {}').format(fill.name)) raise DictConsistencyError(_('cannot find fill function {}').format(fill.name), 25)
namespace = fill.namespace namespace = fill.namespace
# let's replace the target by the path # let's replace the target by the path
@ -467,7 +513,7 @@ class ConstrainteAnnotator:
with_suffix=True, with_suffix=True,
) )
if suffix is not None: if suffix is not None:
raise DictConsistencyError(_(f'Cannot add fill function to "{fill.target}" only with the suffix "{suffix}"')) raise DictConsistencyError(_(f'Cannot add fill function to "{fill.target}" only with the suffix "{suffix}"'), 26)
variable = self.objectspace.paths.get_variable_obj(fill.target) variable = self.objectspace.paths.get_variable_obj(fill.target)
value = self.objectspace.value(variable.xmlfiles) value = self.objectspace.value(variable.xmlfiles)
value.type = 'calculation' value.type = 'calculation'
@ -476,9 +522,9 @@ class ConstrainteAnnotator:
param_to_delete = [] param_to_delete = []
for fill_idx, param in enumerate(fill.param): for fill_idx, param in enumerate(fill.param):
if param.type not in ['suffix', 'string'] and not hasattr(param, 'text'): if param.type not in ['suffix', 'string'] and not hasattr(param, 'text'):
raise DictConsistencyError(_(f"All '{param.type}' variables must have a value in order to calculate {fill.target}")) raise DictConsistencyError(_(f"All '{param.type}' variables must have a value in order to calculate {fill.target}"), 27)
if param.type == 'suffix' and hasattr(param, 'text'): if param.type == 'suffix' and hasattr(param, 'text'):
raise DictConsistencyError(_(f"All '{param.type}' variables must not have a value in order to calculate {fill.target}")) raise DictConsistencyError(_(f"All '{param.type}' variables must not have a value in order to calculate {fill.target}"), 28)
if param.type == 'string': if param.type == 'string':
if not hasattr(param, 'text'): if not hasattr(param, 'text'):
param.text = None param.text = None
@ -491,6 +537,8 @@ class ConstrainteAnnotator:
if suffix: if suffix:
param.suffix = suffix param.suffix = suffix
except DictConsistencyError as err: except DictConsistencyError as err:
if err.errno != 42:
raise err
if param.optional is False: if param.optional is False:
raise err raise err
param_to_delete.append(fill_idx) param_to_delete.append(fill_idx)

View file

@ -124,9 +124,11 @@ class FamilyAnnotator:
mode = modes_level[-1] mode = modes_level[-1]
for idx, follower in enumerate(variable.variable): for idx, follower in enumerate(variable.variable):
if follower.auto_save is True: if follower.auto_save is True:
raise DictConsistencyError(_(f'leader/followers {follower.name} could not be auto_save')) xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'leader/followers "{follower.name}" could not be auto_save in {xmlfiles}'), 29)
if follower.auto_freeze is True: if follower.auto_freeze is True:
raise DictConsistencyError(_('leader/followers {follower.name} could not be auto_freeze')) xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'leader/followers "{follower.name}" could not be auto_freeze in {xmlfiles}'), 30)
is_follower = idx != 0 is_follower = idx != 0
path = '{}.{}.{}'.format(family.path, variable.name, follower.name) path = '{}.{}.{}'.format(family.path, variable.name, follower.name)
self.annotate_variable(follower, family_mode, path, is_follower) self.annotate_variable(follower, family_mode, path, is_follower)

View file

@ -63,7 +63,9 @@ class GroupAnnotator:
) )
has_a_leader = True has_a_leader = True
else: else:
raise DictConsistencyError(_('cannot found followers "{}"').format('", "'.join(follower_names))) xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
joined = '", "'.join(follower_names)
raise DictConsistencyError(_(f'when parsing leadership, we espect to find those followers "{joined}" in {xmlfiles}'), 31)
del self.objectspace.space.constraints.group del self.objectspace.space.constraints.group
def manage_leader(self, def manage_leader(self,
@ -78,7 +80,8 @@ class GroupAnnotator:
) -> None: ) -> None:
# manage leader's variable # manage leader's variable
if variable.multi is not True: if variable.multi is not True:
raise DictConsistencyError(_('the variable {} in a group must be multi').format(variable.name)) xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'the variable "{variable.name}" in a group must be multi in {xmlfiles}'), 32)
leader_space.variable = [] leader_space.variable = []
leader_space.name = leadership_name leader_space.name = leadership_name
leader_space.hidden = variable.hidden leader_space.hidden = variable.hidden
@ -121,7 +124,8 @@ class GroupAnnotator:
leader_is_hidden: bool, leader_is_hidden: bool,
) -> None: ) -> None:
if variable.name != follower_names[0]: if variable.name != follower_names[0]:
raise DictConsistencyError(_('cannot found this follower {}').format(follower_names[0])) xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'when parsing leadership, we espect to find the follower "{follower_names[0]}" but we found "{variable.name}" in {xmlfiles}'), 33)
follower_names.remove(variable.name) follower_names.remove(variable.name)
if leader_is_hidden: if leader_is_hidden:
variable.frozen = True variable.frozen = True

View file

@ -1,3 +1,7 @@
from ..i18n import _
from ..error import DictConsistencyError
PROPERTIES = ('hidden', 'frozen', 'auto_freeze', 'auto_save', 'force_default_on_freeze', PROPERTIES = ('hidden', 'frozen', 'auto_freeze', 'auto_save', 'force_default_on_freeze',
'force_store_value', 'disabled', 'mandatory') 'force_store_value', 'disabled', 'mandatory')
CONVERT_PROPERTIES = {'auto_save': ['force_store_value'], 'auto_freeze': ['force_store_value', 'auto_freeze']} CONVERT_PROPERTIES = {'auto_save': ['force_store_value'], 'auto_freeze': ['force_store_value', 'auto_freeze']}
@ -21,6 +25,9 @@ class PropertyAnnotator:
if hasattr(variable, 'mode') and variable.mode: if hasattr(variable, 'mode') and variable.mode:
properties.append(variable.mode) properties.append(variable.mode)
variable.mode = None variable.mode = None
if 'force_store_value' in properties and 'force_default_on_freeze' in properties:
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'cannot have auto_freeze or auto_store with the hidden variable "{variable.name}" in {xmlfiles}'), 50)
if properties: if properties:
variable.properties = frozenset(properties) variable.properties = frozenset(properties)
@ -52,4 +59,3 @@ class PropertyAnnotator:
self.convert_property(follower) self.convert_property(follower)
else: else:
self.convert_property(variable) self.convert_property(variable)

View file

@ -247,5 +247,6 @@ class ServiceAnnotator:
if not hasattr(file_, 'source'): if not hasattr(file_, 'source'):
file_.source = basename(file_.name) file_.source = basename(file_.name)
elif not hasattr(file_, 'source'): elif not hasattr(file_, 'source'):
raise DictConsistencyError(_('attribute source mandatory for file with variable name for {}').format(file_.name)) xmlfiles = self.objectspace.display_xmlfiles(file_.xmlfiles)
raise DictConsistencyError(_(f'attribute "source" is mandatory for the file "{file_.name}" in {xmlfiles}'), 34)

View file

@ -37,9 +37,6 @@ FORCE_CHOICE = {'oui/non': ['oui', 'non'],
'schedulemod': ['pre', 'post']} 'schedulemod': ['pre', 'post']}
FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
RENAME_ATTIBUTES = {'description': 'doc'} RENAME_ATTIBUTES = {'description': 'doc'}
@ -49,7 +46,6 @@ class VariableAnnotator:
): ):
self.objectspace = objectspace self.objectspace = objectspace
self.convert_variable() self.convert_variable()
self.convert_auto_freeze()
self.convert_separators() self.convert_separators()
def convert_variable(self): def convert_variable(self):
@ -99,7 +95,7 @@ class VariableAnnotator:
def _valid_type(variable): def _valid_type(variable):
if variable.type not in CONVERT_OPTION: if variable.type not in CONVERT_OPTION:
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles) xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
raise DictConsistencyError(_(f'unvalid type "{variable.type}" for variable "{variable.name}" in {xmlfiles}')) raise DictConsistencyError(_(f'unvalid type "{variable.type}" for variable "{variable.name}" in {xmlfiles}'), 36)
if not hasattr(self.objectspace.space, 'variables'): if not hasattr(self.objectspace.space, 'variables'):
return return
@ -109,10 +105,6 @@ class VariableAnnotator:
families.doc = families.name families.doc = families.name
for family in families.family.values(): for family in families.family.values():
family.doc = family.name family.doc = family.name
for key, value in RENAME_ATTIBUTES.items():
if hasattr(family, key):
setattr(family, value, getattr(family, key))
setattr(family, key, None)
family.name = normalize_family(family.name) family.name = normalize_family(family.name)
if hasattr(family, 'variable'): if hasattr(family, 'variable'):
for variable in family.variable.values(): for variable in family.variable.values():
@ -142,37 +134,6 @@ class VariableAnnotator:
) )
_valid_type(variable) _valid_type(variable)
def convert_auto_freeze(self): # pylint: disable=C0111
def _convert_auto_freeze(variable, namespace):
if variable.auto_freeze:
new_condition = self.objectspace.condition(variable.xmlfiles)
new_condition.name = 'auto_hidden_if_not_in'
new_condition.namespace = namespace
new_condition.source = FREEZE_AUTOFREEZE_VARIABLE
new_param = self.objectspace.param(variable.xmlfiles)
new_param.text = 'oui'
new_condition.param = [new_param]
new_target = self.objectspace.target(variable.xmlfiles)
new_target.type = 'variable'
path = variable.namespace + '.' + normalize_family(family.name) + '.' + variable.name
new_target.name = path
new_condition.target = [new_target]
if not hasattr(self.objectspace.space.constraints, 'condition'):
self.objectspace.space.constraints.condition = []
self.objectspace.space.constraints.condition.append(new_condition)
if hasattr(self.objectspace.space, 'variables'):
for variables in self.objectspace.space.variables.values():
if hasattr(variables, 'family'):
namespace = variables.name
for family in variables.family.values():
if hasattr(family, 'variable'):
for variable in family.variable.values():
if isinstance(variable, self.objectspace.leadership):
for follower in variable.variable:
_convert_auto_freeze(follower, namespace)
else:
_convert_auto_freeze(variable, namespace)
def convert_separators(self): # pylint: disable=C0111,R0201 def convert_separators(self): # pylint: disable=C0111,R0201
if not hasattr(self.objectspace.space, 'variables'): if not hasattr(self.objectspace.space, 'variables'):
return return
@ -187,7 +148,7 @@ class VariableAnnotator:
separator.namespace, separator.namespace,
) )
xmlfiles = self.objectspace.display_xmlfiles(separator.xmlfiles) xmlfiles = self.objectspace.display_xmlfiles(separator.xmlfiles)
raise DictConsistencyError(_(f'{subpath} already has a separator in {xmlfiles}')) raise DictConsistencyError(_(f'{subpath} already has a separator in {xmlfiles}'), 35)
option.separator = separator.text option.separator = separator.text
del family.separators del family.separators

View file

@ -29,6 +29,9 @@ class DictConsistencyError(Exception):
"""It's not only that the Creole XML is valid against the Creole DTD """It's not only that the Creole XML is valid against the Creole DTD
it's that it is not consistent. it's that it is not consistent.
""" """
def __init__(self, msg, errno):
super().__init__(msg)
self.errno = errno
class LoaderError(Exception): class LoaderError(Exception):

View file

@ -170,7 +170,7 @@ class RougailObjSpace:
continue continue
if child.tag == 'family': if child.tag == 'family':
if child.attrib['name'] in family_names: if child.attrib['name'] in family_names:
raise DictConsistencyError(_(f'Family "{child.attrib["name"]}" is set several times in "{xmlfile}"')) raise DictConsistencyError(_(f'Family "{child.attrib["name"]}" is set several times in "{xmlfile}"'), 44)
family_names.append(child.attrib['name']) family_names.append(child.attrib['name'])
if child.tag == 'variables': if child.tag == 'variables':
# variables has no name, so force namespace name # variables has no name, so force namespace name
@ -273,7 +273,7 @@ class RougailObjSpace:
if exists is False: if exists is False:
raise SpaceObjShallNotBeUpdated() raise SpaceObjShallNotBeUpdated()
xmlfiles = self.display_xmlfiles(existed_var.xmlfiles) xmlfiles = self.display_xmlfiles(existed_var.xmlfiles)
raise DictConsistencyError(_(f'"{child.tag}" named "{name}" cannot be re-created in "{xmlfile}", already defined in {xmlfiles}')) raise DictConsistencyError(_(f'"{child.tag}" named "{name}" cannot be re-created in "{xmlfile}", already defined in {xmlfiles}'), 45)
# if this object must only be modified if object already exists # if this object must only be modified if object already exists
exists = self.convert_boolean(subspace.get('exists', False)) exists = self.convert_boolean(subspace.get('exists', False))
if exists is True: if exists is True:
@ -283,7 +283,7 @@ class RougailObjSpace:
if child.tag not in vars(space): if child.tag not in vars(space):
setattr(space, child.tag, {}) setattr(space, child.tag, {})
return getattr(self, child.tag)(xmlfile) return getattr(self, child.tag)(xmlfile)
raise DictConsistencyError(_(f'Redefined object in "{xmlfile}": "{name}" does not exist yet')) raise DictConsistencyError(_(f'Redefined object in "{xmlfile}": "{name}" does not exist yet'), 46)
def get_existed_obj(self, def get_existed_obj(self,
name: str, name: str,
@ -301,7 +301,7 @@ class RougailObjSpace:
old_family_name = namespace + '.' + old_family_name old_family_name = namespace + '.' + old_family_name
if space.path != old_family_name: if space.path != old_family_name:
xmlfiles = self.display_xmlfiles(space.xmlfiles) xmlfiles = self.display_xmlfiles(space.xmlfiles)
raise DictConsistencyError(_(f'Variable was previously create in family "{old_family_name}", now it is in "{space.path}" in {xmlfiles}')) raise DictConsistencyError(_(f'Variable was previously create in family "{old_family_name}", now it is in "{space.path}" in {xmlfiles}'), 47)
return self.paths.get_variable_obj(name) return self.paths.get_variable_obj(name)
children = getattr(space, child.tag, {}) children = getattr(space, child.tag, {})
if name in children: if name in children:
@ -344,7 +344,7 @@ class RougailObjSpace:
for attr, val in child.attrib.items(): for attr, val in child.attrib.items():
if redefine and attr in UNREDEFINABLE: if redefine and attr in UNREDEFINABLE:
xmlfiles = self.display_xmlfiles(variableobj.xmlfiles[:-1]) xmlfiles = self.display_xmlfiles(variableobj.xmlfiles[:-1])
raise DictConsistencyError(_(f'cannot redefine attribute "{attr}" for variable "{child.attrib["name"]}" in "{xmlfile}", already defined in {xmlfiles}')) raise DictConsistencyError(_(f'cannot redefine attribute "{attr}" for variable "{child.attrib["name"]}" in "{xmlfile}", already defined in {xmlfiles}'), 48)
if attr in self.booleans_attributs: if attr in self.booleans_attributs:
val = self.convert_boolean(val) val = self.convert_boolean(val)
if attr == 'name' and getattr(variableobj, 'name', None): if attr == 'name' and getattr(variableobj, 'name', None):

View file

@ -28,7 +28,7 @@ class Path:
else: else:
full_name = name full_name = name
if full_name in self.families and self.families[full_name]['variableobj'] != variableobj: if full_name in self.families and self.families[full_name]['variableobj'] != variableobj:
raise DictConsistencyError(_(f'Duplicate family name {name}')) raise DictConsistencyError(_(f'Duplicate family name {name}'), 37)
self.families[full_name] = dict(name=name, self.families[full_name] = dict(name=name,
namespace=namespace, namespace=namespace,
variableobj=variableobj, variableobj=variableobj,
@ -45,9 +45,7 @@ class Path:
raise OperationError('current_namespace must not be None') raise OperationError('current_namespace must not be None')
dico = self.families[name] dico = self.families[name]
if dico['namespace'] != Config['variable_namespace'] and current_namespace != dico['namespace']: if dico['namespace'] != Config['variable_namespace'] and current_namespace != dico['namespace']:
raise DictConsistencyError(_('A family located in the {} namespace ' raise DictConsistencyError(_(f'A family located in the "{dico["namespace"]}" namespace shall not be used in the "{current_namespace}" namespace'), 38)
'shall not be used in the {} namespace').format(
dico['namespace'], current_namespace))
return dico['name'] return dico['name']
def get_family_obj(self, def get_family_obj(self,
@ -56,7 +54,7 @@ class Path:
if '.' not in name and name in self.full_paths_families: if '.' not in name and name in self.full_paths_families:
name = self.full_paths_families[name] name = self.full_paths_families[name]
if name not in self.families: if name not in self.families:
raise DictConsistencyError(_('unknown family {}').format(name)) raise DictConsistencyError(_('unknown family {}').format(name), 39)
dico = self.families[name] dico = self.families[name]
return dico['variableobj'] return dico['variableobj']
@ -92,7 +90,7 @@ class Path:
dico = self._get_variable(name) dico = self._get_variable(name)
if dico['leader'] != None: if dico['leader'] != None:
raise DictConsistencyError(_('Already defined leader {} for variable' raise DictConsistencyError(_('Already defined leader {} for variable'
' {}'.format(dico['leader'], name))) ' {}'.format(dico['leader'], name)), 40)
dico['leader'] = leader_name dico['leader'] = leader_name
def get_leader(self, name): # pylint: disable=C0111 def get_leader(self, name): # pylint: disable=C0111
@ -156,9 +154,7 @@ class Path:
dico = self._get_variable(name) dico = self._get_variable(name)
if not allow_source: if not allow_source:
if dico['namespace'] not in [Config['variable_namespace'], 'services'] and current_namespace != dico['namespace']: if dico['namespace'] not in [Config['variable_namespace'], 'services'] and current_namespace != dico['namespace']:
raise DictConsistencyError(_('A variable located in the {} namespace ' raise DictConsistencyError(_(f'A variable located in the "{dico["namespace"]}" namespace shall not be used in the "{current_namespace}" namespace'), 41)
'shall not be used in the {} namespace').format(
dico['namespace'], current_namespace))
if '.' in dico['name']: if '.' in dico['name']:
value = dico['name'] value = dico['name']
else: else:
@ -200,7 +196,7 @@ class Path:
if not with_suffix: if not with_suffix:
raise Exception('This option is dynamic, should use "with_suffix" attribute') raise Exception('This option is dynamic, should use "with_suffix" attribute')
return variable, name[len(var_name):] return variable, name[len(var_name):]
raise DictConsistencyError(_('unknown option {}').format(name)) raise DictConsistencyError(_('unknown option {}').format(name), 42)
if with_suffix: if with_suffix:
return self.variables[name], None return self.variables[name], None
return self.variables[name] return self.variables[name]

View file

@ -37,7 +37,7 @@ class XMLReflector(object):
# document = parse(BytesIO(xmlfile), XMLParser(remove_blank_text=True)) # document = parse(BytesIO(xmlfile), XMLParser(remove_blank_text=True))
document = parse(xmlfile) document = parse(xmlfile)
if not self.dtd.validate(document): if not self.dtd.validate(document):
raise DictConsistencyError(_(f'"{xmlfile}" not a valid xml file: {self.dtd.error_log.filter_from_errors()[0]}')) raise DictConsistencyError(_(f'"{xmlfile}" not a valid xml file: {self.dtd.error_log.filter_from_errors()[0]}'), 43)
return document.getroot() return document.getroot()
def load_xml_from_folders(self, xmlfolders): def load_xml_from_folders(self, xmlfolders):

View file

@ -1 +0,0 @@
{"rougail.general.mode_conteneur_actif": "non", "rougail.general.autosavevar": "oui"}

View file

@ -1,15 +0,0 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_3 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non', values=('oui', 'non'))
option_4 = StrOption(properties=frozenset({'basic', 'force_store_value', Calculation(calc_value, Params(ParamValue('hidden'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('oui')})), Calculation(calc_value, Params(ParamValue('frozen'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('oui')})), Calculation(calc_value, Params(ParamValue('force_default_on_freeze'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('oui')}))}), name='autosavevar', doc='autosave variable', multi=False, default=Calculation(func.calc_val, Params((ParamValue("oui")), kwargs={})))
option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'basic'}), children=[option_3, option_4])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View file

@ -2,7 +2,10 @@
<rougail> <rougail>
<variables> <variables>
<family name="general"> <family name="general">
<variable name="mode_conteneur_actif" type="oui/non" description="No change" auto_freeze="True"> <variable name="module_instancie" type="oui/non" description="No change">
<value>non</value>
</variable>
<variable name="mode_conteneur_actif" type="oui/non" description="No change" auto_freeze="True" hidden="True">
<value>non</value> <value>non</value>
</variable> </variable>
</family> </family>
@ -10,7 +13,7 @@
</variables> </variables>
<constraints> <constraints>
<fill name="calc_val" target="mode_conteneur_actif"> <fill name="calc_val" target="mode_conteneur_actif">
<param>value</param> <param>oui</param>
</fill> </fill>
</constraints> </constraints>
</rougail> </rougail>

View file

@ -0,0 +1,15 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="général">
<variable name="module_instancie" type="oui/non" description="No change">
<value>non</value>
</variable>
<variable name="activer_ejabberd" type="oui/non" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab
-->

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<rougail>
<variables>
<family name='ejabberd'>
<variable name="mode" type="string" auto_freeze="True">
<value>pre</value>
</variable>
</family>
</variables>
</rougail>

View file

View file

View file

@ -2,9 +2,10 @@
<rougail> <rougail>
<variables> <variables>
<family name="general"> <family name="general">
<variable name="leader" type="string" description="leader" auto_freeze="True"/> <variable name="module_instancie" type="oui/non" description="No change"/>
<variable name="follower1" type="string" description="follower1"/> <variable name="leader" type="string" description="leader" auto_freeze="True" multi="True"/>
<variable name="follower2" type="string" description="follower2"/> <variable name="follower1" type="string" description="follower1" multi="True"/>
<variable name="follower2" type="string" description="follower2" multi="True"/>
</family> </family>
</variables> </variables>

View file

@ -71,13 +71,14 @@ def launch_flattener(test_dir, test_ok=False):
eolobj.space_visitor(eosfunc) eolobj.space_visitor(eosfunc)
tiramisu_objects = eolobj.save() tiramisu_objects = eolobj.save()
tiramisu_dir = join(test_dir, 'tiramisu') tiramisu_dir = join(test_dir, 'tiramisu')
tiramisu_file = join(tiramisu_dir, 'base.py') if isdir(tiramisu_dir):
if not isfile(tiramisu_file) or debug: tiramisu_file = join(tiramisu_dir, 'base.py')
with open(tiramisu_file, 'w') as fh: if not isfile(tiramisu_file) or debug:
fh.write(tiramisu_objects) with open(tiramisu_file, 'w') as fh:
with open(tiramisu_file, 'r') as fh: fh.write(tiramisu_objects)
tiramisu_objects_ori = fh.read() with open(tiramisu_file, 'r') as fh:
assert tiramisu_objects == tiramisu_objects_ori tiramisu_objects_ori = fh.read()
assert tiramisu_objects == tiramisu_objects_ori
def fake_traduc(txt): def fake_traduc(txt):
@ -106,8 +107,15 @@ def test_dictionary(test_dir):
def test_error_dictionary(test_dir_error): def test_error_dictionary(test_dir_error):
assert getcwd() == ORI_DIR assert getcwd() == ORI_DIR
test_dir = join(dico_dirs, test_dir_error) test_dir = join(dico_dirs, test_dir_error)
with raises(DictConsistencyError): errno = 0
for i in listdir(test_dir):
if i.startswith('errno_'):
if errno:
raise Exception('multiple errno')
errno = int(i.split('_')[1])
with raises(DictConsistencyError) as err:
launch_flattener(test_dir) launch_flattener(test_dir)
assert err.value.errno == errno, f'expected errno: {errno}, errno: {err.value.errno}, value: {err.value}'
assert getcwd() == ORI_DIR assert getcwd() == ORI_DIR