object in target

This commit is contained in:
Emmanuel Garette 2021-01-17 17:15:58 +01:00
parent 3e2d221cc4
commit 06e7196280
5 changed files with 69 additions and 98 deletions

View file

@ -6,7 +6,6 @@ from typing import List, Any
from .variable import CONVERT_OPTION from .variable import CONVERT_OPTION
from ..i18n import _ from ..i18n import _
from ..utils import normalize_family
from ..error import DictConsistencyError from ..error import DictConsistencyError
from ..config import Config from ..config import Config
@ -61,7 +60,7 @@ class ConstrainteAnnotator:
if hasattr(self.objectspace.space.constraints, 'condition'): if hasattr(self.objectspace.space.constraints, 'condition'):
self.convert_condition_target() self.convert_condition_target()
self.convert_xxxlist_to_variable() self.convert_xxxlist_to_variable()
self.check_condition_fallback_optional() self.check_condition_fallback()
self.convert_condition_source() self.convert_condition_source()
self.check_choice_option_condition() self.check_choice_option_condition()
self.remove_condition_with_empty_target() self.remove_condition_with_empty_target()
@ -271,18 +270,17 @@ class ConstrainteAnnotator:
target, target,
): ):
if target.type == 'variable': if target.type == 'variable':
variable = self.objectspace.paths.get_variable_obj(target.name) if not self.objectspace.paths.is_leader(target.name.path):
return target.name, [target.name]
# it's a leader, so apply property to leadership # it's a leader, so apply property to leadership
if self.objectspace.paths.is_leader(target.name): family_name = self.objectspace.paths.get_variable_family_path(target.name.path)
family_name = self.objectspace.paths.get_variable_family_path(target.name) family = self.objectspace.paths.get_family(family_name,
family = self.objectspace.paths.get_family(target.name.rsplit('.', 1)[0], target.name.namespace,
variable.namespace, )
) return family, family.variable
return family, family.variable
return variable, [variable]
# it's a family # it's a family
variable = self.objectspace.paths.get_family(target.name, variable = self.objectspace.paths.get_family(target.name.path,
None, target.namespace,
) )
return variable, list(variable.variable.values()) return variable, list(variable.variable.values())
@ -295,40 +293,36 @@ class ConstrainteAnnotator:
msg = _(f'target is mandatory in a condition for source "{condition.source}" ' msg = _(f'target is mandatory in a condition for source "{condition.source}" '
f'in {xmlfiles}') f'in {xmlfiles}')
raise DictConsistencyError(msg, 9) raise DictConsistencyError(msg, 9)
for target in condition.target: remove_targets = []
if target.type == 'variable': for index, target in enumerate(condition.target):
if condition.source == target.name: try:
msg = f'target name and source name must be different: {condition.source}' if target.type == 'variable':
raise DictConsistencyError(_(msg), 11) if condition.source == target.name:
target_names = '.'.join([normalize_family(name) \ msg = f'target name and source name must be different: {condition.source}'
for name in target.name.split('.')]) raise DictConsistencyError(_(msg), 11)
try: target.name = self.objectspace.paths.get_variable_obj(target.name)
target.name, suffix = self.objectspace.paths.get_variable_path(target_names, elif target.type == 'family':
condition.namespace, target.name = self.objectspace.paths.get_family(target.name,
) condition.namespace,
if suffix: )
xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles) elif target.type.endswith('list') and \
msg = _(f'the target "{target.name}" in condition cannot be a dynamic ' condition.name not in ['disabled_if_in', 'disabled_if_not_in']:
f'variable in {xmlfiles}') xmlfiles = self.objectspace.display_xmlfiles(target.xmlfiles)
raise DictConsistencyError(msg, 21) msg = _(f'target "{target.type}" not allow in condition "{condition.name}" '
except DictConsistencyError as err: f'in {xmlfiles}')
# for optional variable raise DictConsistencyError(msg, 10)
if not target.optional or err.errno != 42: except DictConsistencyError as err:
raise err if err.errno != 42:
elif target.type == 'family': raise err
target_path = '.'.join([normalize_family(name) \ # for optional variable
for name in target.name.split('.')]) if not target.optional:
if not self.objectspace.paths.family_is_defined(target_path, xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles)
condition.namespace, raise DictConsistencyError(_(f'cannot found target "{target.name}" in the condition in {xmlfiles}'), 12)
): remove_targets.append(index)
raise DictConsistencyError(_(f'cannot found family {target.name}'), 12) remove_targets.sort(reverse=True)
target.name = target_path for index in remove_targets:
elif target.type.endswith('list') and \ condition.target.pop(index)
condition.name not in ['disabled_if_in', 'disabled_if_not_in']:
xmlfiles = self.objectspace.display_xmlfiles(target.xmlfiles)
msg = _(f'target "{target.type}" not allow in condition "{condition.name}" '
f'in {xmlfiles}')
raise DictConsistencyError(msg, 10)
def convert_xxxlist_to_variable(self): def convert_xxxlist_to_variable(self):
"""transform *list to variable or family """transform *list to variable or family
@ -343,9 +337,8 @@ class ConstrainteAnnotator:
{}).get(target.name) {}).get(target.name)
if listvars: if listvars:
for listvar in listvars: for listvar in listvars:
variable = self.objectspace.paths.get_variable_obj(listvar)
type_ = 'variable' type_ = 'variable'
new_target = self.objectspace.target(variable.xmlfiles) new_target = self.objectspace.target(listvar.xmlfiles)
new_target.type = type_ new_target.type = type_
new_target.name = listvar new_target.name = listvar
new_targets.append(new_target) new_targets.append(new_target)
@ -355,7 +348,7 @@ class ConstrainteAnnotator:
condition.target.pop(target_idx) condition.target.pop(target_idx)
condition.target.extend(new_targets) condition.target.extend(new_targets)
def check_condition_fallback_optional(self): def check_condition_fallback(self):
"""a condition with a fallback **and** the source variable doesn't exist """a condition with a fallback **and** the source variable doesn't exist
""" """
remove_conditions = [] remove_conditions = []
@ -371,18 +364,6 @@ class ConstrainteAnnotator:
remove_conditions.append(idx) remove_conditions.append(idx)
if apply_action: if apply_action:
self.force_actions_to_variable(condition) self.force_actions_to_variable(condition)
continue
remove_targets = []
# optional
for index, target in enumerate(condition.target):
if target.optional is True and \
not self.objectspace.paths.path_is_defined(target.name):
remove_targets.append(index)
remove_targets = list(set(remove_targets))
remove_targets.sort(reverse=True)
for index in remove_targets:
condition.target.pop(index)
remove_conditions = list(set(remove_conditions)) remove_conditions = list(set(remove_conditions))
remove_conditions.sort(reverse=True) remove_conditions.sort(reverse=True)
for idx in remove_conditions: for idx in remove_conditions:

View file

@ -84,6 +84,7 @@ class ServiceAnnotator:
and build elements and its attributes (the `Options` in tiramisu terms) and build elements and its attributes (the `Options` in tiramisu terms)
""" """
families = [] families = []
listname = '{}list'.format(elttype)
for elt in elts: for elt in elts:
# try to launch _update_xxxx() function # try to launch _update_xxxx() function
update_elt = '_update_' + elttype update_elt = '_update_' + elttype
@ -99,17 +100,21 @@ class ServiceAnnotator:
elt.xmlfiles, elt.xmlfiles,
) )
family.variable = [] family.variable = []
activate_path = '.'.join([subpath, 'activate']) activate_obj = self._generate_element('boolean',
'activate',
True,
elt.xmlfiles,
'.'.join([subpath, 'activate']),
)
for key in dir(elt): for key in dir(elt):
if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES: if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES:
continue continue
value = getattr(elt, key) value = getattr(elt, key)
listname = '{}list'.format(elttype)
if key == listname: if key == listname:
self.objectspace.list_conditions.setdefault(listname, self.objectspace.list_conditions.setdefault(listname,
{}).setdefault( {}).setdefault(
value, value,
[]).append(activate_path) []).append(activate_obj)
continue continue
family.variable.append(self._generate_element(self._get_type(key, family.variable.append(self._generate_element(self._get_type(key,
elttype, elttype,
@ -122,12 +127,7 @@ class ServiceAnnotator:
)) ))
# FIXME ne devrait pas etre True par défaut # FIXME ne devrait pas etre True par défaut
# devrait etre un calcule # devrait etre un calcule
family.variable.append(self._generate_element('boolean', family.variable.append(activate_obj)
'activate',
True,
elt.xmlfiles,
activate_path,
))
families.append(family) families.append(family)
return families return families
@ -146,8 +146,11 @@ class ServiceAnnotator:
if idx: if idx:
c_name += f'_{idx}' c_name += f'_{idx}'
subpath = '{}.{}'.format(path, c_name) subpath = '{}.{}'.format(path, c_name)
if not self.objectspace.paths.family_is_defined(subpath, 'services'): try:
return c_name, subpath self.objectspace.paths.get_family(subpath, 'services')
except DictConsistencyError as err:
if err.errno == 42:
return c_name, subpath
idx += 1 idx += 1
def _gen_family(self, def _gen_family(self,

View file

@ -1,6 +1,7 @@
from .i18n import _ from .i18n import _
from .error import DictConsistencyError from .error import DictConsistencyError
from .config import Config from .config import Config
from .utils import normalize_family
class Path: class Path:
@ -48,33 +49,19 @@ class Path:
) )
variableobj.path = path variableobj.path = path
def _get_family(self,
name: str,
namespace: str=None,
):
# if main namespace, get full_path
if '.' not in name and namespace in [None, Config['variable_namespace']] and name in self.full_paths_families:
name = self.full_paths_families[name]
dico = self.families[name]
if namespace and dico['namespace'] != Config['variable_namespace'] and namespace != dico['namespace']:
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(self, def get_family(self,
name: str, name: str,
namespace: str, current_namespace: str,
) -> 'Family': # pylint: disable=C0111 ) -> 'Family': # pylint: disable=C0111
return self._get_family(name, namespace)['variableobj'] name = '.'.join([normalize_family(subname) for subname in name.split('.')])
if name not in self.families and name in self.full_paths_families:
def family_is_defined(self, name = self.full_paths_families[name]
name: str, if name not in self.families:
namespace: str, raise DictConsistencyError(_('unknown option {}').format(name), 42)
) -> str: # pylint: disable=C0111 dico = self.families[name]
try: if current_namespace not in [Config['variable_namespace'], 'services'] and current_namespace != dico['namespace']:
self._get_family(name, namespace) raise DictConsistencyError(_(f'A family located in the "{dico["namespace"]}" namespace shall not be used in the "{current_namespace}" namespace'), 38)
return True return dico['variableobj']
except KeyError:
return False
# Leadership # Leadership
def set_leader(self, def set_leader(self,
@ -142,13 +129,12 @@ class Path:
def get_variable_path(self, def get_variable_path(self,
name: str, name: str,
current_namespace: str, current_namespace: str,
allow_variable_namespace: str=False,
) -> str: # pylint: disable=C0111 ) -> str: # pylint: disable=C0111
dico, suffix = self._get_variable(name, dico, suffix = self._get_variable(name,
with_suffix=True, with_suffix=True,
) )
namespace = dico['variableobj'].namespace namespace = dico['variableobj'].namespace
if not allow_variable_namespace and namespace not in [Config['variable_namespace'], 'services'] and current_namespace != namespace: if namespace not in [Config['variable_namespace'], 'services'] and current_namespace != namespace:
raise DictConsistencyError(_(f'A variable located in the "{namespace}" namespace shall not be used in the "{current_namespace}" namespace'), 41) raise DictConsistencyError(_(f'A variable located in the "{namespace}" namespace shall not be used in the "{current_namespace}" namespace'), 41)
return dico['variableobj'].path, suffix return dico['variableobj'].path, suffix
@ -168,6 +154,7 @@ class Path:
name: str, name: str,
with_suffix: bool=False, with_suffix: bool=False,
) -> str: ) -> str:
name = '.'.join([normalize_family(subname) for subname in name.split('.')])
if name not in self.variables: if name not in self.variables:
if '.' not in name and name in self.full_paths_variables: if '.' not in name and name in self.full_paths_variables:
name = self.full_paths_variables[name] name = self.full_paths_variables[name]