diff --git a/src/rougail/annotator/constrainte.py b/src/rougail/annotator/constrainte.py
index 6c81202a..a65f6a45 100644
--- a/src/rougail/annotator/constrainte.py
+++ b/src/rougail/annotator/constrainte.py
@@ -6,6 +6,10 @@ from .variable import CONVERT_OPTION
from ..i18n import _
from ..utils import normalize_family
from ..error import DictConsistencyError
+from ..config import Config
+
+FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
+
INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier']
@@ -20,6 +24,8 @@ class ConstrainteAnnotator:
eosfunc = SourceFileLoader('eosfunc', eosfunc_file).load_module()
self.functions = dir(eosfunc)
self.functions.extend(INTERNAL_FUNCTIONS)
+
+ self.convert_auto_freeze()
self.valid_enums = {}
if hasattr(self.objectspace.space.constraints, 'check'):
self.check_check()
@@ -39,12 +45,46 @@ class ConstrainteAnnotator:
self.convert_fill()
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):
remove_indexes = []
for check_idx, check in enumerate(self.objectspace.space.constraints.check):
if not check.name in self.functions:
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'):
param_option_indexes = []
for idx, param in enumerate(check.param):
@@ -53,7 +93,7 @@ class ConstrainteAnnotator:
param_option_indexes.append(idx)
else:
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':
param.notraisepropertyerror = None
param_option_indexes = list(set(param_option_indexes))
@@ -84,9 +124,9 @@ class ConstrainteAnnotator:
if check.target in self.valid_enums:
old_xmlfiles = self.objectspace.display_xmlfiles(self.valid_enums[check.target]['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'):
- 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)
values = self.load_params_in_valid_enum(check.param,
variable.name,
@@ -113,18 +153,18 @@ class ConstrainteAnnotator:
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}'))
+ raise DictConsistencyError(_(f'only one "variable" parameter is allowed for valid_enum of variable {variable_name}'), 5)
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}'))
+ raise DictConsistencyError(_(f'only multi "variable" parameter is allowed for valid_enum of variable {variable_name}'), 6)
values = param.text
else:
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 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)
else:
values.append(param.text)
@@ -156,10 +196,11 @@ class ConstrainteAnnotator:
def check_params_target(self):
for condition in self.objectspace.space.constraints.condition:
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:
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
for condition_idx, condition in enumerate(self.objectspace.space.constraints.condition):
@@ -167,7 +208,7 @@ class ConstrainteAnnotator:
for idx, target in enumerate(condition.target):
if target.type == 'variable':
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:
target_names = [normalize_family(name) for name in target.name.split('.')]
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.name = self.objectspace.paths.get_family_path('.'.join(target_names), namespace)
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
# transform *list to variable or family
@@ -318,6 +359,11 @@ class ConstrainteAnnotator:
main_action = actions[0]
if getattr(leader_or_variable, main_action, False) is True:
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):
prop = self.objectspace.property_(leader_or_variable.xmlfiles)
prop.type = 'calculation'
@@ -368,7 +414,7 @@ class ConstrainteAnnotator:
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}"'))
+ 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 == '':
choice.name = None
choices.append(choice.name)
@@ -381,16 +427,16 @@ class ConstrainteAnnotator:
try:
cvalue = CONVERT_OPTION[type_].get('func', str)(value.name)
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:
- 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:
new_value = self.objectspace.value(variable.xmlfiles)
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))
+ raise DictConsistencyError(_('empty valid enum is not allowed for variable {}').format(variable.name), 16)
variable.type = 'choice'
def convert_check(self):
@@ -399,16 +445,16 @@ class ConstrainteAnnotator:
name = check.name
if name == 'valid_entier':
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:
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':
variable.min_number = int(param.text)
elif param.name == 'maxi':
variable.max_number = int(param.text)
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:
check_ = self.objectspace.check(variable.xmlfiles)
if name == 'valid_differ':
@@ -417,23 +463,23 @@ class ConstrainteAnnotator:
params_len = 1
if len(check.param) != params_len:
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':
params_len = 1
if len(check.param) != params_len:
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'
elif name == 'valid_broadcast':
params_len = 2
if len(check.param) != params_len:
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':
if len(check.param) not in (1, 2):
params_len = 2
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_.warnings_only = check.warnings_only
if hasattr(check, 'param'):
@@ -454,11 +500,11 @@ class ConstrainteAnnotator:
# test if it's redefined calculation
if fill.target in targets:
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)
#
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
# let's replace the target by the path
@@ -467,7 +513,7 @@ class ConstrainteAnnotator:
with_suffix=True,
)
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)
value = self.objectspace.value(variable.xmlfiles)
value.type = 'calculation'
@@ -476,9 +522,9 @@ class ConstrainteAnnotator:
param_to_delete = []
for fill_idx, param in enumerate(fill.param):
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'):
- 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 not hasattr(param, 'text'):
param.text = None
@@ -491,6 +537,8 @@ class ConstrainteAnnotator:
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)
diff --git a/src/rougail/annotator/family.py b/src/rougail/annotator/family.py
index 78361e00..43d3ceb4 100644
--- a/src/rougail/annotator/family.py
+++ b/src/rougail/annotator/family.py
@@ -124,9 +124,11 @@ class FamilyAnnotator:
mode = modes_level[-1]
for idx, follower in enumerate(variable.variable):
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:
- 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
path = '{}.{}.{}'.format(family.path, variable.name, follower.name)
self.annotate_variable(follower, family_mode, path, is_follower)
diff --git a/src/rougail/annotator/group.py b/src/rougail/annotator/group.py
index 532ba9f3..aaba954a 100644
--- a/src/rougail/annotator/group.py
+++ b/src/rougail/annotator/group.py
@@ -63,7 +63,9 @@ class GroupAnnotator:
)
has_a_leader = True
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
def manage_leader(self,
@@ -78,7 +80,8 @@ class GroupAnnotator:
) -> None:
# manage leader's variable
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.name = leadership_name
leader_space.hidden = variable.hidden
@@ -121,7 +124,8 @@ class GroupAnnotator:
leader_is_hidden: bool,
) -> None:
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)
if leader_is_hidden:
variable.frozen = True
diff --git a/src/rougail/annotator/property.py b/src/rougail/annotator/property.py
index 741538e3..6a2aebbe 100644
--- a/src/rougail/annotator/property.py
+++ b/src/rougail/annotator/property.py
@@ -1,3 +1,7 @@
+from ..i18n import _
+from ..error import DictConsistencyError
+
+
PROPERTIES = ('hidden', 'frozen', 'auto_freeze', 'auto_save', 'force_default_on_freeze',
'force_store_value', 'disabled', 'mandatory')
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:
properties.append(variable.mode)
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:
variable.properties = frozenset(properties)
@@ -52,4 +59,3 @@ class PropertyAnnotator:
self.convert_property(follower)
else:
self.convert_property(variable)
-
diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py
index e4e72116..c5daabd4 100644
--- a/src/rougail/annotator/service.py
+++ b/src/rougail/annotator/service.py
@@ -247,5 +247,6 @@ class ServiceAnnotator:
if not hasattr(file_, 'source'):
file_.source = basename(file_.name)
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)
diff --git a/src/rougail/annotator/variable.py b/src/rougail/annotator/variable.py
index 69e8b512..e258f60f 100644
--- a/src/rougail/annotator/variable.py
+++ b/src/rougail/annotator/variable.py
@@ -37,9 +37,6 @@ FORCE_CHOICE = {'oui/non': ['oui', 'non'],
'schedulemod': ['pre', 'post']}
-FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
-
-
RENAME_ATTIBUTES = {'description': 'doc'}
@@ -49,7 +46,6 @@ class VariableAnnotator:
):
self.objectspace = objectspace
self.convert_variable()
- self.convert_auto_freeze()
self.convert_separators()
def convert_variable(self):
@@ -99,7 +95,7 @@ class VariableAnnotator:
def _valid_type(variable):
if variable.type not in CONVERT_OPTION:
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'):
return
@@ -109,10 +105,6 @@ class VariableAnnotator:
families.doc = families.name
for family in families.family.values():
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)
if hasattr(family, 'variable'):
for variable in family.variable.values():
@@ -142,37 +134,6 @@ class VariableAnnotator:
)
_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
if not hasattr(self.objectspace.space, 'variables'):
return
@@ -187,7 +148,7 @@ class VariableAnnotator:
separator.namespace,
)
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
del family.separators
diff --git a/src/rougail/error.py b/src/rougail/error.py
index 221e355f..68252f61 100644
--- a/src/rougail/error.py
+++ b/src/rougail/error.py
@@ -29,6 +29,9 @@ class DictConsistencyError(Exception):
"""It's not only that the Creole XML is valid against the Creole DTD
it's that it is not consistent.
"""
+ def __init__(self, msg, errno):
+ super().__init__(msg)
+ self.errno = errno
class LoaderError(Exception):
diff --git a/src/rougail/objspace.py b/src/rougail/objspace.py
index 0a462bc3..bcb2ac36 100644
--- a/src/rougail/objspace.py
+++ b/src/rougail/objspace.py
@@ -170,7 +170,7 @@ class RougailObjSpace:
continue
if child.tag == 'family':
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'])
if child.tag == 'variables':
# variables has no name, so force namespace name
@@ -273,7 +273,7 @@ class RougailObjSpace:
if exists is False:
raise SpaceObjShallNotBeUpdated()
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
exists = self.convert_boolean(subspace.get('exists', False))
if exists is True:
@@ -283,7 +283,7 @@ class RougailObjSpace:
if child.tag not in vars(space):
setattr(space, child.tag, {})
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,
name: str,
@@ -301,7 +301,7 @@ class RougailObjSpace:
old_family_name = namespace + '.' + old_family_name
if space.path != old_family_name:
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)
children = getattr(space, child.tag, {})
if name in children:
@@ -344,7 +344,7 @@ class RougailObjSpace:
for attr, val in child.attrib.items():
if redefine and attr in UNREDEFINABLE:
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:
val = self.convert_boolean(val)
if attr == 'name' and getattr(variableobj, 'name', None):
diff --git a/src/rougail/path.py b/src/rougail/path.py
index 00abc959..b8374b16 100644
--- a/src/rougail/path.py
+++ b/src/rougail/path.py
@@ -28,7 +28,7 @@ class Path:
else:
full_name = name
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,
namespace=namespace,
variableobj=variableobj,
@@ -45,9 +45,7 @@ class Path:
raise OperationError('current_namespace must not be None')
dico = self.families[name]
if dico['namespace'] != Config['variable_namespace'] and current_namespace != dico['namespace']:
- raise DictConsistencyError(_('A family located in the {} namespace '
- 'shall not be used in the {} namespace').format(
- dico['namespace'], current_namespace))
+ raise DictConsistencyError(_(f'A family located in the "{dico["namespace"]}" namespace shall not be used in the "{current_namespace}" namespace'), 38)
return dico['name']
def get_family_obj(self,
@@ -56,7 +54,7 @@ class Path:
if '.' not in name and name in self.full_paths_families:
name = self.full_paths_families[name]
if name not in self.families:
- raise DictConsistencyError(_('unknown family {}').format(name))
+ raise DictConsistencyError(_('unknown family {}').format(name), 39)
dico = self.families[name]
return dico['variableobj']
@@ -92,7 +90,7 @@ class Path:
dico = self._get_variable(name)
if dico['leader'] != None:
raise DictConsistencyError(_('Already defined leader {} for variable'
- ' {}'.format(dico['leader'], name)))
+ ' {}'.format(dico['leader'], name)), 40)
dico['leader'] = leader_name
def get_leader(self, name): # pylint: disable=C0111
@@ -156,9 +154,7 @@ class Path:
dico = self._get_variable(name)
if not allow_source:
if dico['namespace'] not in [Config['variable_namespace'], 'services'] and current_namespace != dico['namespace']:
- raise DictConsistencyError(_('A variable located in the {} namespace '
- 'shall not be used in the {} namespace').format(
- dico['namespace'], current_namespace))
+ raise DictConsistencyError(_(f'A variable located in the "{dico["namespace"]}" namespace shall not be used in the "{current_namespace}" namespace'), 41)
if '.' in dico['name']:
value = dico['name']
else:
@@ -200,7 +196,7 @@ class Path:
if not with_suffix:
raise Exception('This option is dynamic, should use "with_suffix" attribute')
return variable, name[len(var_name):]
- raise DictConsistencyError(_('unknown option {}').format(name))
+ raise DictConsistencyError(_('unknown option {}').format(name), 42)
if with_suffix:
return self.variables[name], None
return self.variables[name]
diff --git a/src/rougail/xmlreflector.py b/src/rougail/xmlreflector.py
index a2ebcc90..d6352c71 100644
--- a/src/rougail/xmlreflector.py
+++ b/src/rougail/xmlreflector.py
@@ -37,7 +37,7 @@ class XMLReflector(object):
# document = parse(BytesIO(xmlfile), XMLParser(remove_blank_text=True))
document = parse(xmlfile)
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()
def load_xml_from_folders(self, xmlfolders):
diff --git a/tests/dictionaries/10autosave_hidden_frozenifin/makedict/base.json b/tests/dictionaries/10autosave_hidden_frozenifin/makedict/base.json
deleted file mode 100644
index 2a8f28f8..00000000
--- a/tests/dictionaries/10autosave_hidden_frozenifin/makedict/base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"rougail.general.mode_conteneur_actif": "non", "rougail.general.autosavevar": "oui"}
diff --git a/tests/dictionaries/10autosave_hidden_frozenifin/tiramisu/base.py b/tests/dictionaries/10autosave_hidden_frozenifin/tiramisu/base.py
deleted file mode 100644
index 00ac1625..00000000
--- a/tests/dictionaries/10autosave_hidden_frozenifin/tiramisu/base.py
+++ /dev/null
@@ -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])
diff --git a/tests/dictionaries/10autosave_hidden_frozenifin/__init__.py b/tests/dictionaries/51redefine_multi/errno_48
similarity index 100%
rename from tests/dictionaries/10autosave_hidden_frozenifin/__init__.py
rename to tests/dictionaries/51redefine_multi/errno_48
diff --git a/tests/dictionaries/10autosave_hidden_frozenifin/tiramisu/__init__.py b/tests/dictionaries/51redefine_type/errno_48
similarity index 100%
rename from tests/dictionaries/10autosave_hidden_frozenifin/tiramisu/__init__.py
rename to tests/dictionaries/51redefine_type/errno_48
diff --git a/tests/dictionaries/80fill_autofreeze/__init__.py b/tests/dictionaries/60extra_externalspace/errno_41
similarity index 100%
rename from tests/dictionaries/80fill_autofreeze/__init__.py
rename to tests/dictionaries/60extra_externalspace/errno_41
diff --git a/tests/dictionaries/60extra_externalspaceauto/errno_41 b/tests/dictionaries/60extra_externalspaceauto/errno_41
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/60extra_externalspacecondition2/errno_38 b/tests/dictionaries/60extra_externalspacecondition2/errno_38
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/60extra_externalspacecondition3/errno_12 b/tests/dictionaries/60extra_externalspacecondition3/errno_12
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80fill_autofreeze/00-base.xml b/tests/dictionaries/80auto_autofreeze/00-base.xml
similarity index 64%
rename from tests/dictionaries/80fill_autofreeze/00-base.xml
rename to tests/dictionaries/80auto_autofreeze/00-base.xml
index a63e8ddc..53f69a83 100644
--- a/tests/dictionaries/80fill_autofreeze/00-base.xml
+++ b/tests/dictionaries/80auto_autofreeze/00-base.xml
@@ -2,7 +2,10 @@
-
+
+ non
+
+
non
@@ -10,7 +13,7 @@
- value
+ oui
diff --git a/tests/dictionaries/80auto_autofreeze/__init__.py b/tests/dictionaries/80auto_autofreeze/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80auto_autofreeze/errno_50 b/tests/dictionaries/80auto_autofreeze/errno_50
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/10autosave_hidden_frozenifin/00-base.xml b/tests/dictionaries/80autosave_hidden_frozenifin/00-base.xml
similarity index 100%
rename from tests/dictionaries/10autosave_hidden_frozenifin/00-base.xml
rename to tests/dictionaries/80autosave_hidden_frozenifin/00-base.xml
diff --git a/tests/dictionaries/80autosave_hidden_frozenifin/__init__.py b/tests/dictionaries/80autosave_hidden_frozenifin/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80autosave_hidden_frozenifin/errno_51 b/tests/dictionaries/80autosave_hidden_frozenifin/errno_51
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80check_unknown/errno_1 b/tests/dictionaries/80check_unknown/errno_1
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80check_unknown_var/errno_2 b/tests/dictionaries/80check_unknown_var/errno_2
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80condition_itself/errno_11 b/tests/dictionaries/80condition_itself/errno_11
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80condition_not_exists_error/errno_12 b/tests/dictionaries/80condition_not_exists_error/errno_12
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80container_files_symlink_without_source/errno_34 b/tests/dictionaries/80container_files_symlink_without_source/errno_34
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80container_filesredefine_error/errno_45 b/tests/dictionaries/80container_filesredefine_error/errno_45
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80empty_param_number/errno_27 b/tests/dictionaries/80empty_param_number/errno_27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80empty_typeeole_eole/errno_27 b/tests/dictionaries/80empty_typeeole_eole/errno_27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80empty_typeeole_number/errno_27 b/tests/dictionaries/80empty_typeeole_number/errno_27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80extra_auto_freeze/00-base.xml b/tests/dictionaries/80extra_auto_freeze/00-base.xml
new file mode 100644
index 00000000..032f30d3
--- /dev/null
+++ b/tests/dictionaries/80extra_auto_freeze/00-base.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ non
+
+
+ non
+
+
+
+
+
diff --git a/tests/dictionaries/80extra_auto_freeze/__init__.py b/tests/dictionaries/80extra_auto_freeze/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80extra_auto_freeze/errno_49 b/tests/dictionaries/80extra_auto_freeze/errno_49
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80extra_auto_freeze/extra_dirs/extra/00-base.xml b/tests/dictionaries/80extra_auto_freeze/extra_dirs/extra/00-base.xml
new file mode 100644
index 00000000..7f4f6fe4
--- /dev/null
+++ b/tests/dictionaries/80extra_auto_freeze/extra_dirs/extra/00-base.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+ pre
+
+
+
+
diff --git a/tests/dictionaries/80family_change/errno_47 b/tests/dictionaries/80family_change/errno_47
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80family_changeaccent/errno_47 b/tests/dictionaries/80family_changeaccent/errno_47
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80family_several/errno_44 b/tests/dictionaries/80family_several/errno_44
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80fill_error/errno_24 b/tests/dictionaries/80fill_error/errno_24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80fill_multi/errno_24 b/tests/dictionaries/80fill_multi/errno_24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80hidden_if_in_filelist/errno_10 b/tests/dictionaries/80hidden_if_in_filelist/errno_10
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80leadership_auto_save/errno_29 b/tests/dictionaries/80leadership_auto_save/errno_29
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80leadership_autofreeze/00-base.xml b/tests/dictionaries/80leadership_autofreeze/00-base.xml
index 941c98b6..be26dc51 100644
--- a/tests/dictionaries/80leadership_autofreeze/00-base.xml
+++ b/tests/dictionaries/80leadership_autofreeze/00-base.xml
@@ -2,9 +2,10 @@
-
-
-
+
+
+
+
diff --git a/tests/dictionaries/80leadership_autofreeze/errno_30 b/tests/dictionaries/80leadership_autofreeze/errno_30
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80leadership_none_follower_between_follower/errno_33 b/tests/dictionaries/80leadership_none_follower_between_follower/errno_33
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80leadership_not_ordered/errno_33 b/tests/dictionaries/80leadership_not_ordered/errno_33
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80leadership_not_same_family/errno_31 b/tests/dictionaries/80leadership_not_same_family/errno_31
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80leadership_notexists/errno_42 b/tests/dictionaries/80leadership_notexists/errno_42
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80redefine_double_error/errno_48 b/tests/dictionaries/80redefine_double_error/errno_48
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80redefine_error/errno_45 b/tests/dictionaries/80redefine_error/errno_45
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80redefine_fillerror/errno_24 b/tests/dictionaries/80redefine_fillerror/errno_24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80redefine_notexists/errno_46 b/tests/dictionaries/80redefine_notexists/errno_46
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80separator_multi/errno_35 b/tests/dictionaries/80separator_multi/errno_35
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80separator_multi2/errno_35 b/tests/dictionaries/80separator_multi2/errno_35
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80separator_nonexists/errno_42 b/tests/dictionaries/80separator_nonexists/errno_42
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80unknown_type/errno_36 b/tests/dictionaries/80unknown_type/errno_36
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/88valid_enum_not_number/errno_13 b/tests/dictionaries/88valid_enum_not_number/errno_13
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/88valid_enum_numberdefaultstring/errno_15 b/tests/dictionaries/88valid_enum_numberdefaultstring/errno_15
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/test_1_flattener.py b/tests/test_1_flattener.py
index 1fe241fe..3d3e8c0c 100644
--- a/tests/test_1_flattener.py
+++ b/tests/test_1_flattener.py
@@ -71,13 +71,14 @@ def launch_flattener(test_dir, test_ok=False):
eolobj.space_visitor(eosfunc)
tiramisu_objects = eolobj.save()
tiramisu_dir = join(test_dir, 'tiramisu')
- tiramisu_file = join(tiramisu_dir, 'base.py')
- if not isfile(tiramisu_file) or debug:
- with open(tiramisu_file, 'w') as fh:
- fh.write(tiramisu_objects)
- with open(tiramisu_file, 'r') as fh:
- tiramisu_objects_ori = fh.read()
- assert tiramisu_objects == tiramisu_objects_ori
+ if isdir(tiramisu_dir):
+ tiramisu_file = join(tiramisu_dir, 'base.py')
+ if not isfile(tiramisu_file) or debug:
+ with open(tiramisu_file, 'w') as fh:
+ fh.write(tiramisu_objects)
+ with open(tiramisu_file, 'r') as fh:
+ tiramisu_objects_ori = fh.read()
+ assert tiramisu_objects == tiramisu_objects_ori
def fake_traduc(txt):
@@ -106,8 +107,15 @@ def test_dictionary(test_dir):
def test_error_dictionary(test_dir_error):
assert getcwd() == ORI_DIR
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)
+ assert err.value.errno == errno, f'expected errno: {errno}, errno: {err.value.errno}, value: {err.value}'
assert getcwd() == ORI_DIR