remove group constrainte, it's now a normal group

This commit is contained in:
2021-04-13 19:05:01 +02:00
parent 65d40f494f
commit e5737cd572
2401 changed files with 23705 additions and 1454 deletions

View File

@ -164,13 +164,12 @@ class Annotator(TargetAnnotator, ParamAnnotator, Walk):
return target.name, [target.name]
# it's a leader, so apply property to leadership
family_name = self.objectspace.paths.get_variable_family_path(target.name.path)
family = self.objectspace.paths.get_family(family_name,
target.name.namespace,
)
return family, family.variable
# it's a family
variable = self.objectspace.paths.get_family(target.name.path,
target.namespace,
namespace = target.name.namespace
else:
family_name = target.name.path
namespace = target.namespace
variable = self.objectspace.paths.get_family(family_name,
namespace,
)
if hasattr(variable, 'variable'):
return variable, list(variable.variable.values())

View File

@ -137,10 +137,10 @@ class Annotator(Walk):
for variable in family.variable.values():
self.valid_mode(variable)
if isinstance(variable, self.objectspace.family):
if family_mode and not self._has_mode(variable):
self._set_auto_mode(variable, family_mode)
continue
if isinstance(variable, self.objectspace.leadership):
if not variable.leadership:
if family_mode and not self._has_mode(variable):
self._set_auto_mode(variable, family_mode)
continue
func = self._set_default_mode_leader
else:
func = self._set_default_mode_variable
@ -174,11 +174,12 @@ class Annotator(Walk):
obj.mode_auto = True
def _set_default_mode_leader(self,
leadership: 'self.objectspace.leadership',
leadership: 'self.objectspace.family',
family_mode: str,
) -> None:
leader_mode = None
for follower in leadership.variable:
leader = next(iter(leadership.variable.values()))
for follower in leadership.variable.values():
self.valid_mode(follower)
if follower.auto_save is True:
msg = _(f'leader/followers "{follower.name}" could not be auto_save')
@ -192,9 +193,9 @@ class Annotator(Walk):
else:
follower_mode = self.objectspace.rougailconfig['default_variable_mode']
if self.modes[leader_mode] > self.modes[follower_mode]:
if self._has_mode(follower) and not self._has_mode(leadership.variable[0]):
if self._has_mode(follower) and not self._has_mode(leader):
# if follower has mode but not the leader
self._set_auto_mode(leadership.variable[0], follower_mode)
self._set_auto_mode(leader, follower_mode)
else:
# leader's mode is minimum level
if self._has_mode(follower):
@ -206,12 +207,12 @@ class Annotator(Walk):
family_mode,
)
if leader_mode is None:
if hasattr(leadership.variable[0], 'mode'):
leader_mode = leadership.variable[0].mode
if hasattr(leader, 'mode'):
leader_mode = leader.mode
else:
leader_mode = self.objectspace.rougailconfig['default_variable_mode']
if hasattr(leadership.variable[0], 'mode'):
leader_mode = leadership.variable[0].mode
if hasattr(leader, 'mode'):
leader_mode = leader.mode
self._set_auto_mode(leadership, leader_mode)
def _change_family_mode(self,
@ -225,11 +226,14 @@ class Annotator(Walk):
# change variable mode, but not if variables are not in a family
if hasattr(family, 'variable'):
for variable in family.variable.values():
if not isinstance(variable, self.objectspace.family):
if isinstance(variable, self.objectspace.leadership):
if isinstance(variable, self.objectspace.family):
if variable.leadership:
func = self._change_variable_mode_leader
else:
func = self._change_variable_mode
func = None
else:
func = self._change_variable_mode
if func:
func(variable,
family_mode,
)
@ -268,11 +272,13 @@ class Annotator(Walk):
leadership,
family_mode: str,
) -> None:
for follower in leadership.variable:
for idx, follower in enumerate(leadership.variable.values()):
if idx == 0:
leader = follower
self._change_variable_mode(follower,
family_mode,
)
leadership.variable[0].mode = None
leader.mode = None
def dynamic_families(self):
"""link dynamic families to object

View File

@ -27,9 +27,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from rougail.i18n import _
from rougail.error import DictConsistencyError
from rougail.utils import normalize_family
from rougail.annotator.variable import Walk
class Annotator:
class Annotator(Walk):
"""Annotate group
"""
level = 10
@ -37,126 +38,37 @@ class Annotator:
objectspace,
*args,
):
self.objectspace = objectspace
if not hasattr(self.objectspace.space, 'constraints') or \
not hasattr(self.objectspace.space.constraints, 'group'):
if not hasattr(objectspace.space, 'variables'):
return
self.objectspace = objectspace
self.convert_groups()
def convert_groups(self): # pylint: disable=C0111
"""convert groups
"""
# store old leaders family name
cache_paths = {}
for group in self.objectspace.space.constraints.group:
if group.leader in cache_paths:
leader_fam_path = cache_paths[group.leader]
else:
leader_fam_path = self.objectspace.paths.get_variable_family_path(group.leader, group.xmlfiles)
cache_paths[group.leader] = leader_fam_path
follower_names = list(group.follower.keys())
leader = self.objectspace.paths.get_variable(group.leader)
if '.' not in leader_fam_path:
# it's a namespace
ori_leader_family = self.objectspace.space.variables[leader_fam_path]
else:
# it's a sub family
ori_leader_family = self.objectspace.paths.get_family(leader_fam_path,
leader.namespace,
)
has_a_leader = False
for variable in list(ori_leader_family.variable.values()):
if isinstance(variable, self.objectspace.leadership) and \
variable.variable[0].name == leader.name:
# append follower to an existed leadership
leader_space = variable
has_a_leader = True
elif variable.name == leader.name:
for family in self.get_families(with_leadership=True):
if not isinstance(family, self.objectspace.family):
continue
if not family.leadership:
continue
if hasattr(family, 'dynamic'):
msg = _(f'the family "{family.name}" cannot be leadership and dynamic together')
raise DictConsistencyError(msg, 31, family.xmlfiles)
family.doc = family.description
for idx, variable in enumerate(family.variable.values()):
if idx == 0:
# it's a leader
leader_space = self.manage_leader(variable,
group,
ori_leader_family,
)
has_a_leader = True
elif has_a_leader:
# it's should be a follower
self.manage_follower(follower_names.pop(0),
leader_fam_path,
variable,
leader_space,
)
# this variable is not more in ori_leader_family
ori_leader_family.variable.pop(normalize_family(variable.name))
if follower_names == []:
# no more follower
break
else:
joined = '", "'.join(follower_names)
msg = _(f'when parsing leadership, we espect to find those followers "{joined}"')
raise DictConsistencyError(msg, 31, variable.xmlfiles)
del self.objectspace.space.constraints.group
def manage_leader(self,
variable: 'Variable',
group: 'Group',
ori_leader_family,
) -> 'Leadership':
"""manage leader's variable
"""
if variable.multi is not True:
msg = _(f'the variable "{variable.name}" in a group must be multi')
raise DictConsistencyError(msg, 32, variable.xmlfiles)
if hasattr(group, 'name'):
ori_leadership_name = group.name
else:
ori_leadership_name = variable.name
leadership_name = normalize_family(ori_leadership_name)
leader_space = self.objectspace.leadership(variable.xmlfiles)
leader_space.variable = []
leader_space.name = leadership_name
leader_space.hidden = variable.hidden
if variable.hidden:
variable.frozen = True
variable.force_default_on_freeze = True
variable.hidden = None
if hasattr(group, 'description'):
leader_space.doc = group.description
elif variable.name == leadership_name and hasattr(variable, 'description'):
leader_space.doc = variable.description
else:
leader_space.doc = ori_leadership_name
leadership_path = ori_leader_family.path + '.' + leadership_name
self.objectspace.paths.add_leadership(variable.namespace,
leadership_path,
leader_space,
)
ori_leader_family.variable[normalize_family(variable.name)] = leader_space
leader_space.variable.append(variable)
self.objectspace.paths.set_leader(variable.namespace,
ori_leader_family.path,
leadership_name,
normalize_family(variable.name),
)
return leader_space
def manage_follower(self,
follower_name: str,
leader_family_name: str,
variable: 'Variable',
leader_space: 'Leadership',
) -> None:
"""manage follower
"""
if variable.name != follower_name:
msg = _('when parsing leadership, we expect to find the follower '
f'"{follower_name}" but we found "{variable.name}"')
raise DictConsistencyError(msg, 33, variable.xmlfiles)
self.objectspace.paths.set_leader(variable.namespace,
leader_family_name,
leader_space.name,
normalize_family(variable.name),
)
if leader_space.hidden:
variable.frozen = True
variable.force_default_on_freeze = True
leader_space.variable.append(variable)
if variable.multi is not True:
msg = _(f'the variable "{variable.name}" in a leadership must be multi')
raise DictConsistencyError(msg, 32, variable.xmlfiles)
family.hidden = variable.hidden
if variable.hidden:
variable.frozen = True
variable.force_default_on_freeze = True
variable.hidden = None
else:
# it's a follower
if family.hidden:
variable.frozen = True
variable.force_default_on_freeze = True

View File

@ -107,7 +107,7 @@ class Annotator(Walk):
"""convert variables
"""
for variable in self.get_variables(with_leadership=True):
if isinstance(variable, self.objectspace.leadership):
for follower in variable.variable:
if isinstance(variable, self.objectspace.family):
for follower in variable.variable.values():
self.convert_property(follower)
self.convert_property(variable)

View File

@ -46,9 +46,9 @@ class Annotator(Walk): # pylint: disable=R0903
"""convert value
"""
for variable in self.get_variables(with_leadership=True):
if isinstance(variable, self.objectspace.leadership):
if isinstance(variable, self.objectspace.family):
variable_type = 'leader'
for follower in variable.variable:
for follower in variable.variable.values():
self._convert_value(follower,
variable_type,
)
@ -82,19 +82,18 @@ class Annotator(Walk): # pylint: disable=R0903
return
if variable.value[0].type == 'calculation':
variable.default = variable.value[0]
elif variable.multi:
if variable_type != 'follower':
variable.default = [value.name for value in variable.value]
if variable_type != 'leader':
if variable.multi == 'submulti':
variable.default_multi = [value.name for value in variable.value]
else:
variable.default_multi = variable.value[0].name
else:
if variable.multi:
if variable_type != 'follower':
variable.default = [value.name for value in variable.value]
if variable_type != 'leader':
if variable.multi == 'submulti':
variable.default_multi = [value.name for value in variable.value]
else:
variable.default_multi = variable.value[0].name
else:
if len(variable.value) > 1:
msg = _(f'the non multi variable "{variable.name}" cannot have '
'more than one value')
raise DictConsistencyError(msg, 68, variable.xmlfiles)
variable.default = variable.value[0].name
if len(variable.value) > 1:
msg = _(f'the non multi variable "{variable.name}" cannot have '
'more than one value')
raise DictConsistencyError(msg, 68, variable.xmlfiles)
variable.default = variable.value[0].name
del variable.value

View File

@ -87,28 +87,30 @@ class Walk:
if hasattr(family, 'variable'):
for variable in family.variable.values():
if isinstance(variable, self.objectspace.family):
yield from self._get_variables(variable, with_leadership)
continue
if not with_leadership and isinstance(variable, self.objectspace.leadership):
for follower in variable.variable:
yield follower
continue
if variable.leadership is False:
yield from self._get_variables(variable, with_leadership)
continue
if not with_leadership:
for follower in variable.variable.values():
yield follower
continue
yield variable
def get_families(self):
def get_families(self, with_leadership=False):
"""Iter all families from the objectspace
"""
for family in self.objectspace.space.variables.values():
yield from self._get_families(family)
yield from self._get_families(family, with_leadership)
def _get_families(self,
family: 'self.objectspace.family',
with_leadership: bool,
):
yield family
if hasattr(family, 'variable'):
for fam in family.variable.values():
if isinstance(fam, self.objectspace.family):
yield from self._get_families(fam)
if isinstance(fam, self.objectspace.family) and (with_leadership or not fam.leadership):
yield from self._get_families(fam, with_leadership)
class Annotator(Walk): # pylint: disable=R0903
@ -133,10 +135,10 @@ class Annotator(Walk): # pylint: disable=R0903
"""convert variable
"""
for variable in self.get_variables(with_leadership=True):
if isinstance(variable, self.objectspace.leadership):
if isinstance(variable, self.objectspace.family):
# first variable is a leader, others are follower
variable_type = 'leader'
for follower in variable.variable:
for follower in variable.variable.values():
self._convert_variable(follower,
variable_type,
)

View File

@ -132,5 +132,3 @@
<!ELEMENT target (#PCDATA)>
<!ATTLIST target type (variable|family|servicelist|filelist|iplist) "variable">
<!ATTLIST target optional (True|False) "False">
<!ELEMENT follower (#PCDATA)>

View File

@ -38,9 +38,9 @@ FORCE_REDEFINABLES = ('family', 'follower', 'service', 'disknod', 'variables')
# RougailObjSpace's elements that shall be forced to the UnRedefinable type
FORCE_UNREDEFINABLES = ('value',)
# RougailObjSpace's elements that shall not be modify
UNREDEFINABLE = ('multi', 'type')
UNREDEFINABLE = ('multi', 'type', 'leadership')
# RougailObjSpace's elements that did not created automaticly
FORCE_ELEMENTS = ('choice', 'property_', 'leadership', 'information')
FORCE_ELEMENTS = ('choice', 'property_', 'information')
# XML text are convert has name
FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value',)
@ -474,11 +474,16 @@ class RougailObjSpace:
else:
family_name = namespace
if isinstance(space, self.family) and space.leadership:
leader = space.path
else:
leader = None
self.paths.add_variable(namespace,
variableobj.name,
space.path,
document.attrib.get('dynamic') is not None,
variableobj,
leader,
)
elif isinstance(variableobj, self.family): # pylint: disable=E1101
family_name = variableobj.name

View File

@ -77,19 +77,6 @@ class Path:
)
variableobj.path = full_name
def add_leadership(self,
namespace: str,
path: str,
variableobj: str,
) -> str: # pylint: disable=C0111
"""add a new leadership
"""
self.families[path] = dict(name=path,
namespace=namespace,
variableobj=variableobj,
)
variableobj.path = path
def get_family(self,
name: str,
current_namespace: str,
@ -109,26 +96,6 @@ class Path:
raise DictConsistencyError(msg, 38, [])
return dico['variableobj']
# Leadership
def set_leader(self,
namespace: str,
leader_family_name: str,
leadership_name: str,
name: str,
) -> None: # pylint: disable=C0111
"""set a variable a leadership member
"""
# need rebuild path and move object in new path
old_path = leader_family_name + '.' + name
leadership_path = leader_family_name + '.' + leadership_name
new_path = leadership_path + '.' + name
self.variables[new_path] = self.variables.pop(old_path)
self.variables[new_path]['leader'] = leadership_path
self.variables[new_path]['variableobj'].path = new_path
self.variables[new_path]['family'] = leadership_path
if namespace == self.variable_namespace:
self.full_paths_variables[name] = new_path
def is_leader(self, path): # pylint: disable=C0111
"""Is the variable is a leader
"""
@ -136,7 +103,7 @@ class Path:
if not variable['leader']:
return False
leadership = self.get_family(variable['leader'], variable['variableobj'].namespace)
return leadership.variable[0].path == path
return next(iter(leadership.variable.values())).path == path
def is_follower(self, path):
"""Is the variable is a follower
@ -145,7 +112,7 @@ class Path:
if not variable['leader']:
return False
leadership = self.get_family(variable['leader'], variable['variableobj'].namespace)
return leadership.variable[0].path != path
return next(iter(leadership.variable.values())).path != path
# Variable
def add_variable(self, # pylint: disable=R0913
@ -154,6 +121,7 @@ class Path:
family: str,
is_dynamic: bool,
variableobj,
leader: 'self.objectspace.family'=None,
) -> str: # pylint: disable=C0111
"""Add a new variable (with path)
"""
@ -169,7 +137,7 @@ class Path:
raise DictConsistencyError(msg, 57, variableobj.xmlfiles)
self.variables[full_path] = dict(name=name,
family=family,
leader=None,
leader=leader,
is_dynamic=is_dynamic,
variableobj=variableobj,
)

View File

@ -371,7 +371,7 @@ class Family(Common):
if hasattr(self.elt, 'suffixes'):
self.objectspace.has_dyn_option = True
self.object_type = 'ConvertDynOptionDescription'
elif isinstance(self.elt, self.objectspace.leadership):
elif hasattr(self.elt, 'leadership') and self.elt.leadership:
self.object_type = 'Leadership'
else:
self.object_type = 'OptionDescription'

View File

@ -31,10 +31,11 @@ from .i18n import _
from .error import UpgradeError
from .utils import normalize_family
from .config import RougailConfig
VERSIONS = {'creole': ['1'],
'rougail': ['0.9'],
'rougail': ['0.9', '0.10'],
}
@ -47,16 +48,24 @@ FUNCTION_VERSIONS = [(root, version, get_function_name(root, version)) for root,
class RougailUpgrade:
def __init__(self, test=False, upgrade_help=None):
def __init__(self,
test=False,
upgrade_help=None,
rougailconfig: RougailConfig=None,
) -> None:
self.test = test
if upgrade_help is None:
upgrade_help = {}
self.upgrade_help = upgrade_help
if rougailconfig is None:
rougailconfig = RougailConfig
self.rougailconfig = rougailconfig
def load_xml_from_folders(self,
srcfolder: str,
dstfolder: str,
namespace: str,
display: bool=True,
):
"""Loads all the XML files located in the xmlfolders' list
@ -77,7 +86,8 @@ class RougailUpgrade:
function_found = False
for root_name, version, function_version in FUNCTION_VERSIONS:
if function_found and hasattr(self, function_version):
print(f' - convert {filename} to version {version}')
if display:
print(f' - convert {filename} to version {version}')
upgrade_help = self.upgrade_help.get(function_version, {}).get(filename, {})
if upgrade_help.get('remove') is True:
continue
@ -95,6 +105,90 @@ class RougailUpgrade:
# yield xmlfile, document.getroot()
def update_rougail_0_10(self,
root: 'Element',
upgrade_help: dict,
namespace: str,
) -> 'Element':
variables = root.find('variables')
if variables is None:
return root
constraints = root.find('constraints')
if constraints is None:
return root
groups = []
for constraint in constraints:
if constraint.tag == 'group':
constraints.remove(constraint)
groups.append(constraint)
if not groups:
return root
paths = self._get_path_variables(variables,
namespace == self.rougailconfig['variable_namespace'],
namespace,
)
for group in groups:
if group.attrib['leader'] in paths:
leader_obj = paths[group.attrib['leader']]
#FIXME name peut avoir "." il faut le virer
#FIXME si extra c'est un follower !
if 'name' in group.attrib:
name = group.attrib['name']
if 'description' in group.attrib:
description = group.attrib['description']
else:
description = name
else:
name = leader_obj['variable'].attrib['name']
if '.' in name:
name = name.rsplit('.', 1)[-1]
if 'description' in group.attrib:
description = group.attrib['description']
elif 'description' in leader_obj['variable'].attrib:
description = leader_obj['variable'].attrib['description']
else:
description = name
family = SubElement(leader_obj['parent'], 'family', name=name, description=description, leadership="True")
leader_obj['parent'].remove(leader_obj['variable'])
family.append(leader_obj['variable'])
else:
# append in group
follower = next(iter(group))
leader_name = group.attrib['leader']
if '.' in leader_name:
leader_path = leader_name.rsplit('.', 1)[0]
follower_path = leader_path + '.' + follower.text
else:
follower_path = follower.text
obj = paths[follower_path]
family = SubElement(obj['parent'], 'family', name=leader_name, leadership="True")
for follower in group:
leader_name = group.attrib['leader']
if '.' in leader_name:
leader_path = leader_name.rsplit('.', 1)[0]
follower_path = leader_path + '.' + follower.text
else:
follower_path = follower.text
follower_obj = paths[follower_path]
follower_obj['parent'].remove(follower_obj['variable'])
family.append(follower_obj['variable'])
return root
def _get_path_variables(self, variables, is_variable_namespace, path, dico=None):
if dico is None:
dico = {}
for variable in variables:
if not is_variable_namespace and path:
subpath = path + '.'
else:
subpath = ''
subpath += variable.attrib['name']
if variable.tag == 'family':
self._get_path_variables(variable, is_variable_namespace, subpath, dico)
elif variable.tag == 'variable':
dico[subpath] = {'variable': variable, 'parent': variables}
return dico
def update_rougail_0_9(self,
root: 'Element',
upgrade_help: dict,
@ -146,7 +240,7 @@ class RougailUpgrade:
subsubsubelement.attrib['mandatory'] = 'True'
if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('type', {}):
subsubsubelement.attrib['type'] = upgrade_help.get('variables', {}).get('type', {})[subsubsubelement.attrib['name']]
if namespace == 'configuration':
if namespace == self.rougailconfig['variable_namespace']:
path = subsubsubelement.attrib['name']
npath = normalize_family(subsubsubelement.attrib['name'])
else: