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

View File

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

View File

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