diff --git a/src/rougail/annotator/constrainte.py b/src/rougail/annotator/constrainte.py index fedc78e3..6a53f56d 100644 --- a/src/rougail/annotator/constrainte.py +++ b/src/rougail/annotator/constrainte.py @@ -268,13 +268,17 @@ class ConstrainteAnnotator: ): if target.type == 'variable': variable = self.objectspace.paths.get_variable_obj(target.name) - family = self.objectspace.paths.get_family_obj(target.name.rsplit('.', 1)[0]) + family = self.objectspace.paths.get_family(target.name.rsplit('.', 1)[0], + variable.namespace, + ) # it's a leader, so apply property to leadership - if isinstance(family, self.objectspace.leadership) and family.name == variable.name: + if isinstance(family, self.objectspace.leadership) and family.variable[0].name == variable.name: return family, family.variable return variable, [variable] # it's a family - variable = self.objectspace.paths.get_family_obj(target.name) + variable = self.objectspace.paths.get_family(target.name, + None, + ) return variable, list(variable.variable.values()) def convert_condition_target(self): @@ -302,14 +306,13 @@ class ConstrainteAnnotator: if not target.optional or err.errno != 42: raise err elif target.type == 'family': - target_names = '.'.join([normalize_family(name) \ + target_path = '.'.join([normalize_family(name) \ for name in target.name.split('.')]) - try: - target.name = self.objectspace.paths.get_family_path(target_names, - condition.namespace, - ) - except KeyError: + if not self.objectspace.paths.family_is_defined(target_path, + condition.namespace, + ): raise DictConsistencyError(_(f'cannot found family {target.name}'), 12) + target.name = target_path elif target.type.endswith('list') and \ condition.name not in ['disabled_if_in', 'disabled_if_not_in']: xmlfiles = self.objectspace.display_xmlfiles(target.xmlfiles) diff --git a/src/rougail/annotator/family.py b/src/rougail/annotator/family.py index 7951127e..adab5131 100644 --- a/src/rougail/annotator/family.py +++ b/src/rougail/annotator/family.py @@ -169,14 +169,10 @@ class FamilyAnnotator: for family in families.family.values(): if 'dynamic' not in vars(family): continue - namespace = self.objectspace.paths.get_variable_namespace(family.dynamic) - varpath = self.objectspace.paths.get_variable_path(family.dynamic, - namespace, - ) - obj = self.objectspace.paths.get_variable_obj(varpath) + obj = self.objectspace.paths.get_variable_obj(family.dynamic) if not obj.multi: xmlfiles = self.objectspace.display_xmlfiles(family.xmlfiles) msg = _(f'dynamic family "{family.name}" must be linked ' f'to multi variable in {xmlfiles}') raise DictConsistencyError(msg, 16) - family.dynamic = varpath + family.dynamic = obj.path diff --git a/src/rougail/annotator/group.py b/src/rougail/annotator/group.py index 4662d717..b00767ee 100644 --- a/src/rougail/annotator/group.py +++ b/src/rougail/annotator/group.py @@ -3,6 +3,7 @@ from typing import List from ..i18n import _ +from ..config import Config from ..error import DictConsistencyError @@ -23,15 +24,16 @@ class GroupAnnotator: """ for group in self.objectspace.space.constraints.group: leader_fullname = group.leader + leader = self.objectspace.paths.get_variable_obj(leader_fullname) leader_family_name = self.objectspace.paths.get_variable_family_name(leader_fullname) - leader_name = self.objectspace.paths.get_variable_name(leader_fullname) - namespace = self.objectspace.paths.get_variable_namespace(leader_fullname) if '.' not in leader_fullname: - leader_fullname = '.'.join([namespace, leader_family_name, leader_fullname]) + leader_fullname = '.'.join([leader.namespace, leader_family_name, leader_fullname]) follower_names = list(group.follower.keys()) - has_a_leader = False leader_family = leader_fullname.rsplit('.', 1)[0] - ori_leader_family = self.objectspace.paths.get_family_obj(leader_family) + ori_leader_family = self.objectspace.paths.get_family(leader_family, + leader.namespace, + ) + has_a_leader = False for variable in list(ori_leader_family.variable.values()): if has_a_leader: # it's a follower @@ -48,7 +50,7 @@ class GroupAnnotator: if follower_names == []: # no more follower break - elif variable.name == leader_name: + elif variable.name == leader.name: # it's a leader if isinstance(variable, self.objectspace.leadership): # append follower to an existed leadership @@ -60,11 +62,11 @@ class GroupAnnotator: if hasattr(group, 'name'): leadership_name = group.name else: - leadership_name = leader_name + leadership_name = leader.name leader_is_hidden = self.manage_leader(leader_space, leader_family_name, leadership_name, - leader_name, + leader.name, variable, group, ) @@ -104,16 +106,16 @@ class GroupAnnotator: variable.hidden = None if hasattr(group, 'description'): leader_space.doc = group.description - elif hasattr(variable, 'description'): + elif variable.name == leadership_name and hasattr(variable, 'description'): leader_space.doc = variable.description else: - leader_space.doc = variable.name + leader_space.doc = leadership_name namespace = variable.namespace leadership_path = namespace + '.' + leader_family_name + '.' + leadership_name - self.objectspace.paths.add_family(namespace, - leadership_path, - leader_space, - ) + self.objectspace.paths.add_leadership(namespace, + leadership_path, + leader_space, + ) leader_family = self.objectspace.space.variables[namespace].family[leader_family_name] leader_family.variable[leader_name] = leader_space leader_space.variable.append(variable) diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py index 66f2902a..5721161d 100644 --- a/src/rougail/annotator/service.py +++ b/src/rougail/annotator/service.py @@ -146,7 +146,7 @@ class ServiceAnnotator: if idx: c_name += f'_{idx}' subpath = '{}.{}'.format(path, c_name) - if not self.objectspace.paths.family_is_defined(subpath): + if not self.objectspace.paths.family_is_defined(subpath, 'services'): return c_name, subpath idx += 1 @@ -187,6 +187,7 @@ class ServiceAnnotator: val.type = type_ val.name = value variable.value = [val] + variable.namespace = 'services' self.objectspace.paths.add_variable('services', path, 'service', diff --git a/src/rougail/objspace.py b/src/rougail/objspace.py index 7853ef2a..09381f66 100644 --- a/src/rougail/objspace.py +++ b/src/rougail/objspace.py @@ -312,9 +312,7 @@ class RougailObjSpace: name = space.path + '.' + name if not self.paths.path_is_defined(name): return None - old_family_name = self.paths.get_variable_family_name(name) - if namespace != Config['variable_namespace']: - old_family_name = namespace + '.' + old_family_name + old_family_name = namespace + '.' + self.paths.get_variable_family_name(name) if space.path != old_family_name: xmlfiles = self.display_xmlfiles(space.xmlfiles) msg = _(f'Variable was previously create in family "{old_family_name}", ' @@ -451,7 +449,6 @@ class RougailObjSpace: family_name, variableobj, ) - variableobj.path = self.paths.get_family_path(family_name, namespace) @staticmethod def add_to_tree_structure(variableobj, diff --git a/src/rougail/path.py b/src/rougail/path.py index cb9212fa..6a1edc14 100644 --- a/src/rougail/path.py +++ b/src/rougail/path.py @@ -21,17 +21,30 @@ class Path: name: str, variableobj: str, ) -> str: # pylint: disable=C0111 - if '.' not in name and namespace == Config['variable_namespace']: + if namespace == Config['variable_namespace']: full_name = '.'.join([namespace, name]) self.full_paths_families[name] = full_name else: full_name = name - if full_name in self.families and self.families[full_name]['variableobj'] != variableobj: # pragma: no cover + if full_name in self.families and \ + self.families[full_name]['variableobj'] != variableobj: # pragma: no cover raise DictConsistencyError(_(f'Duplicate family name "{name}"'), 37) self.families[full_name] = dict(name=name, namespace=namespace, variableobj=variableobj, ) + variableobj.path = full_name + + def add_leadership(self, + namespace: str, + path: str, + variableobj: str, + ) -> str: # pylint: disable=C0111 + self.families[path] = dict(name=path, + namespace=namespace, + variableobj=variableobj, + ) + variableobj.path = path def _get_family(self, name: str, @@ -45,24 +58,18 @@ class Path: raise DictConsistencyError(_(f'A family located in the "{dico["namespace"]}" namespace shall not be used in the "{namespace}" namespace'), 38) return dico - def get_family_path(self, - name: str, - namespace: str, - ) -> str: # pylint: disable=C0111 - return self._get_family(name, - namespace, - )['name'] - - def get_family_obj(self, - name: str, - ) -> 'Family': # pylint: disable=C0111 - return self._get_family(name)['variableobj'] + def get_family(self, + name: str, + namespace: str, + ) -> 'Family': # pylint: disable=C0111 + return self._get_family(name, namespace)['variableobj'] def family_is_defined(self, name: str, + namespace: str, ) -> str: # pylint: disable=C0111 try: - self._get_family(name) + self._get_family(name, namespace) return True except KeyError: return False @@ -109,11 +116,6 @@ class Path: variableobj=variableobj, ) - def get_variable_name(self, - name: str, - ): # pylint: disable=C0111 - return self._get_variable(name)['name'] - def get_variable_obj(self, name: str, ) -> 'Variable': # pylint: disable=C0111 @@ -124,11 +126,6 @@ class Path: ) -> str: # pylint: disable=C0111 return self._get_variable(name)['family'] - def get_variable_namespace(self, - name: str, - ) -> str: # pylint: disable=C0111 - return self._get_variable(name)['namespace'] - def get_variable_path(self, name: str, current_namespace: str, diff --git a/src/rougail/xmlreflector.py b/src/rougail/xmlreflector.py index a920e337..0e366a7d 100644 --- a/src/rougail/xmlreflector.py +++ b/src/rougail/xmlreflector.py @@ -1,9 +1,10 @@ -# coding: utf-8 +"""load XML file from directory +""" from typing import List from os.path import join, isfile from os import listdir -from lxml.etree import DTD, parse, XMLSyntaxError +from lxml.etree import DTD, parse, XMLSyntaxError # pylint: disable=E0611 from .i18n import _ from .error import DictConsistencyError @@ -39,18 +40,20 @@ class XMLReflector: except XMLSyntaxError as err: raise DictConsistencyError(_(f'{xmlfile} is not an XML file: {err}'), 52) if not self.dtd.validate(document): - raise DictConsistencyError(_(f'"{xmlfile}" not a valid XML file: {self.dtd.error_log.filter_from_errors()[0]}'), 43) + dtd_error = self.dtd.error_log.filter_from_errors()[0] + msg = _(f'"{xmlfile}" not a valid XML file: {dtd_error}') + raise DictConsistencyError(msg, 43) return document.getroot() - def load_xml_from_folders(self, - xmlfolders: List[str], - ): + @staticmethod + def load_xml_from_folders(xmlfolders: List[str]): """Loads all the XML files located in the xmlfolders' list :param xmlfolders: list of full folder's name """ for xmlfolder in xmlfolders: - filenames = [join(xmlfolder, filename) for filename in listdir(xmlfolder) if filename.endswith('.xml')] + filenames = [join(xmlfolder, filename) for filename in listdir(xmlfolder) if \ + filename.endswith('.xml')] filenames.sort() for xmlfile in filenames: yield xmlfile diff --git a/tests/dictionaries/10leadership_leader_hidden_if_in_name/00-base.xml b/tests/dictionaries/10leadership_leader_hidden_if_in_name/00-base.xml new file mode 100644 index 00000000..1136506a --- /dev/null +++ b/tests/dictionaries/10leadership_leader_hidden_if_in_name/00-base.xml @@ -0,0 +1,26 @@ + + + + + + non + + + + + + + + + + + + follower1 + follower2 + + + non + leader + + + diff --git a/tests/dictionaries/10leadership_leader_hidden_if_in_name/__init__.py b/tests/dictionaries/10leadership_leader_hidden_if_in_name/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/10leadership_leader_hidden_if_in_name/makedict/base.json b/tests/dictionaries/10leadership_leader_hidden_if_in_name/makedict/base.json new file mode 100644 index 00000000..553ab0b0 --- /dev/null +++ b/tests/dictionaries/10leadership_leader_hidden_if_in_name/makedict/base.json @@ -0,0 +1 @@ +{"rougail.general.mode_conteneur_actif": "non", "rougail.leadermode.other.leader": []} diff --git a/tests/dictionaries/10leadership_leader_hidden_if_in_name/tiramisu/__init__.py b/tests/dictionaries/10leadership_leader_hidden_if_in_name/tiramisu/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/dictionaries/10leadership_leader_hidden_if_in_name/tiramisu/base.py b/tests/dictionaries/10leadership_leader_hidden_if_in_name/tiramisu/base.py new file mode 100644 index 00000000..9c7565f4 --- /dev/null +++ b/tests/dictionaries/10leadership_leader_hidden_if_in_name/tiramisu/base.py @@ -0,0 +1,19 @@ +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 = StrOption(properties=frozenset({'expert', 'mandatory'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non') +option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'expert'}), children=[option_3]) +option_6 = StrOption(properties=frozenset({Calculation(calc_value, Params(ParamValue('frozen'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')})), Calculation(calc_value, Params(ParamValue('force_default_on_freeze'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')}))}), name='leader', doc='leader', multi=True) +option_7 = StrOption(properties=frozenset({'normal', Calculation(calc_value, Params(ParamValue('frozen'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')})), Calculation(calc_value, Params(ParamValue('force_default_on_freeze'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')}))}), name='follower1', doc='follower1', multi=True) +option_8 = StrOption(properties=frozenset({'normal', Calculation(calc_value, Params(ParamValue('frozen'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')})), Calculation(calc_value, Params(ParamValue('force_default_on_freeze'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')}))}), name='follower2', doc='follower2', multi=True) +option_5 = Leadership(name='other', doc='other', properties=frozenset({'normal', Calculation(calc_value, Params(ParamValue('hidden'), kwargs={'condition': ParamOption(option_3, todict=True), 'expected': ParamValue('non')}))}), children=[option_6, option_7, option_8]) +option_4 = OptionDescription(name='leadermode', doc='leadermode', properties=frozenset({'normal'}), children=[option_5]) +option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4]) +option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1]) diff --git a/tests/dictionaries/10load_leadership_name/makedict/base.json b/tests/dictionaries/10load_leadership_name/makedict/base.json index 9e804f6a..df80fe56 100644 --- a/tests/dictionaries/10load_leadership_name/makedict/base.json +++ b/tests/dictionaries/10load_leadership_name/makedict/base.json @@ -1 +1 @@ -{"rougail.general.mode_conteneur_actif": "non", "rougail.general1.leader.leader": []} +{"rougail.general.mode_conteneur_actif": "non", "rougail.general1.other_name.leader": []} diff --git a/tests/dictionaries/10load_leadership_name/tiramisu/base.py b/tests/dictionaries/10load_leadership_name/tiramisu/base.py index e27f5030..a8120ab9 100644 --- a/tests/dictionaries/10load_leadership_name/tiramisu/base.py +++ b/tests/dictionaries/10load_leadership_name/tiramisu/base.py @@ -13,7 +13,7 @@ option_2 = OptionDescription(name='general', doc='general', properties=frozenset option_6 = StrOption(name='leader', doc='leader', multi=True) option_7 = StrOption(properties=frozenset({'normal'}), name='follower1', doc='follower1', multi=True, default=Calculation(func.calc_val, Params((), kwargs={'valeur': ParamValue("valfill")}))) option_8 = StrOption(properties=frozenset({'normal'}), name='follower2', doc='follower2', multi=True, default=Calculation(func.calc_val, Params((ParamOption(option_7, notraisepropertyerror=False, todict=False)), kwargs={}))) -option_5 = Leadership(name='other_name', doc='leader', properties=frozenset({'normal'}), children=[option_6, option_7, option_8]) +option_5 = Leadership(name='other_name', doc='other_name', properties=frozenset({'normal'}), children=[option_6, option_7, option_8]) option_4 = OptionDescription(name='general1', doc='general1', properties=frozenset({'normal'}), children=[option_5]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4]) option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])