reorganise

This commit is contained in:
Emmanuel Garette 2020-04-11 17:24:09 +02:00
parent 822483ab70
commit b0b44d4ee1
2 changed files with 222 additions and 113 deletions

View File

@ -1,5 +1,6 @@
# coding: utf-8 # coding: utf-8
from copy import copy from copy import copy
from typing import List
from collections import OrderedDict from collections import OrderedDict
from os.path import join, basename from os.path import join, basename
@ -184,7 +185,10 @@ class ServiceAnnotator:
family.name = '{}{}'.format(name, index) family.name = '{}{}'.format(name, index)
family.variable = variables family.variable = variables
family.mode = None family.mode = None
self.paths.append('family', subpath, 'services', creoleobj=family) self.paths.add_family('services',
subpath,
family,
)
families.append(family) families.append(family)
return families return families
@ -230,7 +234,11 @@ class ServiceAnnotator:
choices.append(choice) choices.append(choice)
variable.choice = choices variable.choice = choices
path = '{}.{}'.format(subpath, name) path = '{}.{}'.format(subpath, name)
self.paths.append('variable', path, 'services', 'service', variable) self.paths.add_variable('services',
path,
'service',
variable,
)
return variable return variable
def _update_file(self, file_, index, service_path): def _update_file(self, file_, index, service_path):
@ -327,7 +335,10 @@ class ServiceAnnotator:
family.name = '{}{}'.format(name, index) family.name = '{}{}'.format(name, index)
family.variable = variables family.variable = variables
family.mode = None family.mode = None
self.paths.append('family', subpath, 'services', creoleobj=family) self.paths.add_family('services',
subpath,
family,
)
families.append(family) families.append(family)
return families return families
@ -440,61 +451,105 @@ class SpaceAnnotator(object):
variable.help = hlp.text variable.help = hlp.text
del self.space.help del self.space.help
def manage_leader(self,
leader_space: 'Leadership',
leader_family_name: str,
leader_name: str,
namespace: str,
variable: 'Variable',
group: 'Group',
leader_fullname: str,
) -> None:
# manage leader's variable
if variable.multi is not True:
raise CreoleDictConsistencyError(_('the variable {} in a group must be multi').format(variable.name))
leader_space.variable = []
leader_space.name = leader_name
leader_space.hidden = variable.hidden
variable.hidden = None
if hasattr(group, 'description'):
leader_space.doc = group.description
else:
leader_space.doc = variable.description
leader_path = namespace + '.' + leader_family_name + '.' + leader_name
self.paths.add_family(namespace,
leader_path,
leader_space,
)
leader_family = self.space.variables[namespace].family[leader_family_name]
leader_family.variable[leader_name] = leader_space
leader_space.variable.append(variable)
self.paths.set_leader(namespace,
leader_family_name,
leader_name,
leader_name,
)
leader_space.path = leader_fullname
def manage_slave(self,
namespace: str,
leader_family_name: str,
variable: 'Variable',
leader_name: str,
follower_names: List[str],
leader_space: 'Leadership',
) -> None:
if variable.name != follower_names[0]:
raise CreoleDictConsistencyError(_('cannot found this follower {}').format(follower_names[0]))
follower_names.remove(variable.name)
# followers are multi
if not variable.multi:
raise CreoleDictConsistencyError(_('the variable {} in a group must be multi or submulti').format(variable.name))
leader_space.variable.append(variable) # pylint: disable=E1101
self.paths.set_leader(namespace,
leader_family_name,
variable.name,
leader_name,
)
def convert_groups(self): # pylint: disable=C0111 def convert_groups(self): # pylint: disable=C0111
if hasattr(self.space, 'constraints'): if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'group'):
if hasattr(self.space.constraints, 'group'):
for group in self.space.constraints.group: for group in self.space.constraints.group:
leader_fullname = group.master leader_fullname = group.master
follower_names = list(group.slave.keys()) follower_names = list(group.slave.keys())
leader_family_name = self.paths.get_variable_family_name(leader_fullname) leader_family_name = self.paths.get_variable_family_name(leader_fullname)
namespace = self.paths.get_variable_namespace(leader_fullname) namespace = self.paths.get_variable_namespace(leader_fullname)
leader_name = self.paths.get_variable_name(leader_fullname) leader_name = self.paths.get_variable_name(leader_fullname)
leader_family = self.space.variables[namespace].family[leader_family_name] ori_leader_family = self.space.variables[namespace].family[leader_family_name]
leader_path = namespace + '.' + leader_family_name has_a_leader = False
is_leader = False for variable in list(ori_leader_family.variable.values()):
for variable in list(leader_family.variable.values()):
if isinstance(variable, self.objectspace.Leadership): if isinstance(variable, self.objectspace.Leadership):
# append follower to an existed leadership # append follower to an existed leadership
if variable.name == leader_name: if variable.name == leader_name:
leader_space = variable leader_space = variable
is_leader = True has_a_leader = True
else: else:
if is_leader: if has_a_leader:
if variable.name == follower_names[0]: # it's a slave
# followers are multi self.manage_slave(namespace,
if not variable.multi: leader_family_name,
raise CreoleDictConsistencyError(_('the variable {} in a group must be multi or submulti').format(variable.name)) variable,
follower_names.remove(variable.name) leader_name,
leader_family.variable.pop(variable.name) follower_names,
leader_space.variable.append(variable) # pylint: disable=E1101 leader_space,
if namespace == 'creole': )
variable_fullpath = variable.name ori_leader_family.variable.pop(variable.name)
else:
variable_fullpath = leader_path + '.' + variable.name
self.paths.set_leader(variable_fullpath, leader_name)
if follower_names == []: if follower_names == []:
# no more slave
break break
else: elif variable.name == leader_name:
raise CreoleDictConsistencyError(_('cannot found this follower {}').format(follower_names[0])) # it's a leader
if is_leader is False and variable.name == leader_name:
leader_space = self.objectspace.Leadership() leader_space = self.objectspace.Leadership()
leader_space.variable = [] self.manage_leader(leader_space,
leader_space.name = leader_name leader_family_name,
leader_space.hidden = variable.hidden leader_name,
if hasattr(group, 'description'): namespace,
leader_space.doc = group.description variable,
else: group,
leader_space.doc = variable.description leader_fullname,
variable.hidden = None )
self.paths.append('family', leader_path + '.' + leader_name, namespace, creoleobj=leader_space) has_a_leader = True
# manage leader's variable
if variable.multi is not True:
raise CreoleDictConsistencyError(_('the variable {} in a group must be multi').format(variable.name))
leader_family.variable[leader_name] = leader_space
leader_space.variable.append(variable) # pylint: disable=E1101
self.paths.set_leader(leader_fullname, leader_name)
leader_space.path = leader_fullname
is_leader = True
else: else:
raise CreoleDictConsistencyError(_('cannot found followers {}').format(follower_names)) raise CreoleDictConsistencyError(_('cannot found followers {}').format(follower_names))
del self.space.constraints.group del self.space.constraints.group

View File

@ -194,7 +194,11 @@ class CreoleObjSpace(object):
if 'variable' not in vars(family): if 'variable' not in vars(family):
family.variable = OrderedDict() family.variable = OrderedDict()
family.variable[name] = variable_obj family.variable[name] = variable_obj
self.paths.append('variable', name, namespace, family.name, variable_obj) self.paths.add_variable(namespace,
name,
family.name,
variable_obj,
)
return variable_obj return variable_obj
def remove_check(self, name): # pylint: disable=C0111 def remove_check(self, name): # pylint: disable=C0111
@ -425,7 +429,9 @@ class CreoleObjSpace(object):
if not isinstance(space, self.help): # pylint: disable=E1101 if not isinstance(space, self.help): # pylint: disable=E1101
if child.tag == 'variable': if child.tag == 'variable':
family_name = normalize_family(document.attrib['name']) family_name = normalize_family(document.attrib['name'])
self.paths.append('variable', child.attrib['name'], namespace, family_name, self.paths.add_variable(namespace,
child.attrib['name'],
family_name,
creoleobj) creoleobj)
if child.attrib.get('redefine', 'False') == 'True': if child.attrib.get('redefine', 'False') == 'True':
if namespace == 'creole': if namespace == 'creole':
@ -438,7 +444,10 @@ class CreoleObjSpace(object):
family_name = normalize_family(child.attrib['name']) family_name = normalize_family(child.attrib['name'])
if namespace != 'creole': if namespace != 'creole':
family_name = namespace + '.' + family_name family_name = namespace + '.' + family_name
self.paths.append('family', family_name, namespace, creoleobj=creoleobj) self.paths.add_family(namespace,
family_name,
creoleobj,
)
creoleobj.path = self.paths.get_family_path(family_name, namespace) creoleobj.path = self.paths.get_family_path(family_name, namespace)
def create_or_populate_from_xml(self, namespace, xmlfolders, from_zephir=None): def create_or_populate_from_xml(self, namespace, xmlfolders, from_zephir=None):
@ -575,7 +584,7 @@ class CreoleObjSpace(object):
self._sub_xml_export(name, node, node_name, subspace, space) self._sub_xml_export(name, node, node_name, subspace, space)
class Path(object): class Path:
"""Helper class to handle the `path` attribute of a CreoleObjSpace """Helper class to handle the `path` attribute of a CreoleObjSpace
instance. instance.
@ -585,28 +594,27 @@ class Path(object):
self.variables = {} self.variables = {}
self.families = {} self.families = {}
def append(self, pathtype, name, namespace, family=None, creoleobj=None): # pylint: disable=C0111 # Family
if pathtype == 'family': def add_family(self,
self.families[name] = dict(name=name, namespace=namespace, creoleobj=creoleobj) namespace: str,
elif pathtype == 'variable': name: str,
if namespace == 'creole': creoleobj: str,
varname = name ) -> str: # pylint: disable=C0111
else: self.families[name] = dict(name=name,
if '.' in name: namespace=namespace,
varname = name creoleobj=creoleobj,
else: )
varname = '.'.join([namespace, family, name])
self.variables[varname] = dict(name=name, family=family, namespace=namespace,
leader=None, creoleobj=creoleobj)
else: # pragma: no cover
raise Exception('unknown pathtype {}'.format(pathtype))
def get_family_path(self, name, current_namespace): # pylint: disable=C0111 def get_family_path(self,
name: str,
current_namespace: str,
) -> str: # pylint: disable=C0111
if current_namespace is None: # pragma: no cover if current_namespace is None: # pragma: no cover
raise CreoleOperationError('current_namespace must not be None') raise CreoleOperationError('current_namespace must not be None')
dico = self.families[normalize_family(name, dico = self.families[normalize_family(name,
check_name=False, check_name=False,
allow_dot=True)] allow_dot=True,
)]
if dico['namespace'] != 'creole' and current_namespace != dico['namespace']: if dico['namespace'] != 'creole' and current_namespace != dico['namespace']:
raise CreoleDictConsistencyError(_('A family located in the {} namespace ' raise CreoleDictConsistencyError(_('A family located in the {} namespace '
'shall not be used in the {} namespace').format( 'shall not be used in the {} namespace').format(
@ -616,41 +624,100 @@ class Path(object):
path = '.'.join([dico['namespace'], path]) path = '.'.join([dico['namespace'], path])
return path return path
def get_family_namespace(self, name): # pylint: disable=C0111 def get_family_namespace(self,
name: str,
) -> str: # pylint: disable=C0111
dico = self.families[name] dico = self.families[name]
if dico['namespace'] is None: if dico['namespace'] is None:
return dico['name'] return dico['name']
return dico['namespace'] return dico['namespace']
def get_family_obj(self, name): # pylint: disable=C0111 def get_family_obj(self,
name: str,
) -> 'Family': # pylint: disable=C0111
if name not in self.families: if name not in self.families:
raise CreoleDictConsistencyError(_('unknown family {}').format(name)) raise CreoleDictConsistencyError(_('unknown family {}').format(name))
dico = self.families[name] dico = self.families[name]
return dico['creoleobj'] return dico['creoleobj']
def get_variable_name(self, name): # pylint: disable=C0111 # Leadership
def set_leader(self,
namespace: str,
leader_family_name: str,
name: str,
leader_name: str,
) -> None: # pylint: disable=C0111
if namespace != 'creole':
# need rebuild path and move object in new path
old_path = namespace + '.' + leader_family_name + '.' + name
dico = self._get_variable(old_path)
del self.variables[old_path]
new_path = namespace + '.' + leader_family_name + '.' + leader_name + '.' + name
self.add_variable(namespace,
new_path,
family=dico['family'],
creoleobj=dico['creoleobj'])
name = new_path
dico = self._get_variable(name) dico = self._get_variable(name)
return dico['name'] if dico['leader'] != None:
raise CreoleDictConsistencyError(_('Already defined leader {} for variable'
' {}'.format(dico['leader'], name)))
dico['leader'] = leader_name
def get_variable_obj(self, name): # pylint: disable=C0111 def get_leader(self, name): # pylint: disable=C0111
dico = self._get_variable(name) return self._get_variable(name)['leader']
return dico['creoleobj']
def get_variable_family_name(self, name): # pylint: disable=C0111 # Variable
dico = self._get_variable(name) def add_variable(self,
return dico['family'] namespace: str,
name: str,
family: str=None,
creoleobj=None,
) -> str: # pylint: disable=C0111
if namespace == 'creole' or '.' in name:
varname = name
else:
varname = '.'.join([namespace, family, name])
self.variables[varname] = dict(name=name,
family=family,
namespace=namespace,
leader=None,
creoleobj=creoleobj)
def get_variable_family_path(self, name): # pylint: disable=C0111 def get_variable_name(self,
name,
): # pylint: disable=C0111
return self._get_variable(name)['name']
def get_variable_obj(self,
name:str,
) -> 'Variable': # pylint: disable=C0111
return self._get_variable(name)['creoleobj']
def get_variable_family_name(self,
name: str,
) -> str: # pylint: disable=C0111
return self._get_variable(name)['family']
def get_variable_family_path(self,
name: str,
) -> str: # pylint: disable=C0111
dico = self._get_variable(name) dico = self._get_variable(name)
list_path = [dico['namespace'], dico['family']] list_path = [dico['namespace'], dico['family']]
if dico['leader'] is not None: if dico['leader'] is not None:
list_path.append(dico['leader']) list_path.append(dico['leader'])
return '.'.join(list_path) return '.'.join(list_path)
def get_variable_namespace(self, name): # pylint: disable=C0111 def get_variable_namespace(self,
name: str,
) -> str: # pylint: disable=C0111
return self._get_variable(name)['namespace'] return self._get_variable(name)['namespace']
def get_variable_path(self, name, current_namespace, allow_source=False): # pylint: disable=C0111 def get_variable_path(self,
name: str,
current_namespace: str,
allow_source: str=False,
) -> str: # pylint: disable=C0111
if current_namespace is None: # pragma: no cover if current_namespace is None: # pragma: no cover
raise CreoleOperationError('current_namespace must not be None') raise CreoleOperationError('current_namespace must not be None')
dico = self._get_variable(name) dico = self._get_variable(name)
@ -667,30 +734,17 @@ class Path(object):
list_path.append(dico['name']) list_path.append(dico['name'])
return '.'.join(list_path) return '.'.join(list_path)
def path_is_defined(self, name): # pylint: disable=C0111 def path_is_defined(self,
name: str,
) -> str: # pylint: disable=C0111
return name in self.variables return name in self.variables
def set_leader(self, name, leader): # pylint: disable=C0111 def _get_variable(self,
dico = self._get_variable(name) name: str,
namespace = dico['namespace'] ) -> str:
if dico['leader'] != None:
raise CreoleDictConsistencyError(_('Already defined leader {} for variable'
' {}'.format(dico['leader'], name)))
dico['leader'] = leader
if namespace != 'creole':
new_path = self.get_variable_path(name, namespace)
self.append('variable', new_path, namespace, family=dico['family'], creoleobj=dico['creoleobj'])
self.variables[new_path]['leader'] = leader
del self.variables[name]
def _get_variable(self, name):
if name not in self.variables: if name not in self.variables:
if name.startswith('creole.'): if name.startswith('creole.'):
name = name.split('.')[-1] name = name.split('.')[-1]
if name not in self.variables: if name not in self.variables:
raise CreoleDictConsistencyError(_('unknown option {}').format(name)) raise CreoleDictConsistencyError(_('unknown option {}').format(name))
return self.variables[name] return self.variables[name]
def get_leader(self, name): # pylint: disable=C0111
dico = self._get_variable(name)
return dico['leader']