From 911af90564cc1130d4bae096c71c82a630e18aee Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 29 Nov 2017 23:25:34 +0100 Subject: [PATCH] reorganise optiondescription --- tiramisu/config.py | 123 ++++++++++--------- tiramisu/option/optiondescription.py | 177 +++++++++++---------------- 2 files changed, 135 insertions(+), 165 deletions(-) diff --git a/tiramisu/config.py b/tiramisu/config.py index db7c908..54b9141 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -175,46 +175,45 @@ class SubConfig(object): force_permissive=force_permissive, validate_properties=validate_properties, setting_properties=setting_properties) - if isinstance(self, Exception): - return self, None return self, path[-1] # ______________________________________________________________________ - def __iter__(self, force_permissive=False): - """Pythonesque way of parsing group's ordered options. - iteration only on Options (not OptionDescriptions)""" - setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties() - for child in self.cfgimpl_get_description().impl_getchildren(context=self._cfgimpl_get_context()): - if not child.impl_is_optiondescription(): - try: - name = child.impl_getname() - yield name, self.getattr(name, - force_permissive=force_permissive, - setting_properties=setting_properties) - except GeneratorExit: # pragma: optional cover - if sys.version_info[0] < 3: - raise StopIteration - else: - raise GeneratorExit() - except PropertiesOptionError: # pragma: optional cover - pass # option with properties - - def iter_all(self, force_permissive=False): - """A way of parsing options **and** groups. - iteration on Options and OptionDescriptions.""" - for child in self.cfgimpl_get_description().impl_getchildren(): - try: - yield child.impl_getname(), self.getattr(child.impl_getname(), - force_permissive=force_permissive) - except GeneratorExit: # pragma: optional cover - if sys.version_info[0] < 3: - raise StopIteration - else: - raise GeneratorExit() - except PropertiesOptionError: # pragma: optional cover - pass # option with properties +# def __iter__(self, force_permissive=False): +# """Pythonesque way of parsing group's ordered options. +# iteration only on Options (not OptionDescriptions)""" +# setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties() +# for child in self.cfgimpl_get_description().impl_getchildren(context=self._cfgimpl_get_context()): +# if not child.impl_is_optiondescription(): +# try: +# name = child.impl_getname() +# yield name, self.getattr(name, +# force_permissive=force_permissive, +# setting_properties=setting_properties) +# except GeneratorExit: # pragma: optional cover +# if sys.version_info[0] < 3: +# raise StopIteration +# else: +# raise GeneratorExit() +# except PropertiesOptionError: # pragma: optional cover +# pass # option with properties +# +# def iter_all(self, force_permissive=False): +# """A way of parsing options **and** groups. +# iteration on Options and OptionDescriptions.""" +# for child in self.cfgimpl_get_description().impl_getchildren(): +# try: +# yield child.impl_getname(), self.getattr(child.impl_getname(), +# force_permissive=force_permissive) +# except GeneratorExit: # pragma: optional cover +# if sys.version_info[0] < 3: +# raise StopIteration +# else: +# raise GeneratorExit() +# except PropertiesOptionError: # pragma: optional cover +# pass # option with properties def iter_groups(self, + setting_properties, group_type=None, force_permissive=False): """iteration on groups objects only. @@ -230,7 +229,8 @@ class SubConfig(object): raise TypeError(_("unknown group_type: {0}").format(group_type)) context = self._cfgimpl_get_context() setting_properties = context.cfgimpl_get_settings().get_context_properties() - for child in self.cfgimpl_get_description().impl_getchildren(context=context): + for child in self.cfgimpl_get_description().impl_getchildren(context=context, + setting_properties=setting_properties): if child.impl_is_optiondescription(): try: if group_type is None or (group_type is not None and @@ -249,20 +249,20 @@ class SubConfig(object): pass # ______________________________________________________________________ - def __str__(self): - "Config's string representation" - lines = [] - for name, grp in self.iter_groups(): - lines.append("[{0}]".format(name)) - for name, value in self: - try: - lines.append("{0} = {1}".format(name, value)) - except UnicodeEncodeError: # pragma: optional cover - lines.append("{0} = {1}".format(name, - value.encode(default_encoding))) - return '\n'.join(lines) - - __repr__ = __str__ +# def __str__(self): +# "Config's string representation" +# lines = [] +# for name, grp in self.iter_groups(): +# lines.append("[{0}]".format(name)) +# for name, value in self: +# try: +# lines.append("{0} = {1}".format(name, value)) +# except UnicodeEncodeError: # pragma: optional cover +# lines.append("{0} = {1}".format(name, +# value.encode(default_encoding))) +# return '\n'.join(lines) +# +# __repr__ = __str__ def _cfgimpl_get_context(self): """context could be None, we need to test it @@ -315,8 +315,9 @@ class SubConfig(object): self, name = self.cfgimpl_get_home_by_path(name, force_permissive=force_permissive, setting_properties=setting_properties) - child = self.cfgimpl_get_description().__getattr__(name, - context=context) + child = self.cfgimpl_get_description().impl_getchild(name, + setting_properties, + context) if isinstance(child, (OptionDescription, SynDynOptionDescription)): raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover elif child.impl_is_symlinkoption() and \ @@ -347,8 +348,9 @@ class SubConfig(object): self, name = self.cfgimpl_get_home_by_path(name, force_permissive=force_permissive, setting_properties=setting_properties) - child = self.cfgimpl_get_description().__getattr__(name, - context=context) + child = self.cfgimpl_get_description().impl_getchild(name, + setting_properties, + context) if isinstance(child, (OptionDescription, SynDynOptionDescription)): raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover elif child.impl_is_symlinkoption() and \ @@ -408,8 +410,9 @@ class SubConfig(object): setting_properties=setting_properties) context = self._cfgimpl_get_context() - option = self.cfgimpl_get_description().__getattr__(name, - context=context) + option = self.cfgimpl_get_description().impl_getchild(name, + context, + setting_properties) if option.impl_is_symlinkoption() and isinstance(option, DynSymLinkOption): # FIXME peuvent-il vraiment etre le 2 ? # si non supprimer tout ces tests inutiles @@ -827,11 +830,9 @@ class _CommonConfig(SubConfig): force_permissive=force_permissive, validate_properties=validate_properties, setting_properties=setting_properties) - if isinstance(self, Exception): - return self - option = self.cfgimpl_get_description().__getattr__(path, - context=self._cfgimpl_get_context(), - setting_properties=setting_properties) + option = self.cfgimpl_get_description().impl_getchild(path, + setting_properties, + self._cfgimpl_get_context()) if not validate_properties: return option else: diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 6a77476..6530d6e 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -327,41 +327,24 @@ class OptionDescriptionWalk(CacheOptionDescription): return find_results return find_results - def _getattr(self, - name, - setting_properties, - suffix=undefined, - context=undefined, - dyn=True): - error = False - if suffix is not undefined: - if undefined in [suffix, context]: # pragma: no cover - raise ConfigError(_("suffix and context needed if " - "it's a dyn option")) - if name.endswith(suffix): - oname = name[:-len(suffix)] - child = self._children[1][self._children[0].index(oname)] - return self._impl_get_dynchild(child, suffix) - else: - error = True + def impl_getchild(self, + name, + setting_properties, + context=undefined, + dyn=True): + if name not in self._children[0]: + child = self._impl_search_dynchild(name, + context=context, + setting_properties=setting_properties) + if child: + return child else: - if name in self._children[0]: - child = self._children[1][self._children[0].index(name)] - if dyn and child.impl_is_dynoptiondescription(): - error = True - else: - return child - else: - child = self._impl_search_dynchild(name, - context=context, - setting_properties=setting_properties) - if child != []: - return child - error = True - if error: - raise AttributeError(_('unknown Option {0} ' - 'in OptionDescription {1}' - '').format(name, self.impl_getname())) + child = self._children[1][self._children[0].index(name)] + if not child.impl_is_dynoptiondescription(): + return child + raise AttributeError(_('unknown Option {0} ' + 'in OptionDescription {1}' + '').format(name, self.impl_getname())) def impl_get_opt_by_path(self, path): @@ -404,7 +387,6 @@ class OptionDescriptionWalk(CacheOptionDescription): name, context, setting_properties): - ret = [] for child in self._impl_st_getchildren(only_dyn=True): cname = child.impl_getname() if name.startswith(cname): @@ -414,7 +396,6 @@ class OptionDescriptionWalk(CacheOptionDescription): return SynDynOptionDescription(child, name, value) - return ret def __getattr__(self, name, @@ -423,16 +404,6 @@ class OptionDescriptionWalk(CacheOptionDescription): if name.startswith('_'): return object.__getattribute__(self, name) - if '.' in name: - path = name.split('.')[0] - subpath = '.'.join(name.split('.')[1:]) - return self.__getattr__(path, context=context).__getattr__(subpath, - context=context, - setting_properties=setting_properties) - return self._getattr(name, - context=context, - setting_properties=setting_properties) - def _impl_get_dynchild(self, child, suffix): @@ -464,7 +435,7 @@ class OptionDescription(OptionDescriptionWalk): """ if not isinstance(children, list): - raise ValueError(_('children in optiondescription "{}"must be a liste').format(name)) + raise ValueError(_('children in optiondescription "{}" must be a list').format(name)) super(OptionDescription, self).__init__(name, doc=doc, requires=requires, @@ -491,11 +462,10 @@ class OptionDescription(OptionDescriptionWalk): raise ConflictError(_('the option\'s name "{}" start as ' 'the dynoptiondescription\'s name "{}"').format(child, dynopt)) old = child - _setattr = object.__setattr__ - _setattr(self, '_children', (tuple(child_names), tuple(children))) - _setattr(self, '_cache_consistencies', None) + self._children = (tuple(child_names), tuple(children)) + self._cache_consistencies = None # the group_type is useful for filtering OptionDescriptions in a config - _setattr(self, '_group_type', groups.default) + self._group_type = groups.default def impl_getdoc(self): return self.impl_get_information('doc') @@ -508,8 +478,7 @@ class OptionDescription(OptionDescriptionWalk): # ____________________________________________________________ def impl_set_group_type(self, - group_type, - setting_properties): + group_type): """sets a given group object to an OptionDescription :param group_type: an instance of `GroupType` or `MasterGroupType` @@ -517,30 +486,14 @@ class OptionDescription(OptionDescriptionWalk): """ if self._group_type != groups.default: # pragma: optional cover raise TypeError(_('cannot change group_type if already set ' - '(old {0}, new {1})').format(self._group_type, - group_type)) - if isinstance(group_type, groups.GroupType): - self._group_type = group_type - if isinstance(group_type, groups.MasterGroupType): - raise Exception('please use MasterSlaves object instead of OptionDescription') - children = self.impl_getchildren(setting_properties) - for child in children: - if child.impl_is_symlinkoption(): # pragma: optional cover - raise ValueError(_("master group {0} shall not have " - "a symlinkoption").format(self.impl_getname())) - if not isinstance(child, Option): # pragma: optional cover - raise ValueError(_("master group {0} shall not have " - "a subgroup").format(self.impl_getname())) - if not child.impl_is_multi(): # pragma: optional cover - raise ValueError(_("not allowed option {0} " - "in group {1}" - ": this option is not a multi" - "").format(child.impl_getname(), self.impl_getname())) - #length of master change slaves length - MasterSlaves(self.impl_getname(), children) - else: # pragma: optional cover + '(old {0}, new {1})').format(self._group_type, + group_type)) + if not isinstance(group_type, groups.GroupType): raise ValueError(_('group_type: {0}' ' not allowed').format(group_type)) + if isinstance(group_type, groups.MasterGroupType): + raise ConfigError('please use MasterSlaves object instead of OptionDescription') + self._group_type = group_type def impl_get_group_type(self): return self._group_type @@ -588,7 +541,8 @@ class DynOptionDescription(OptionDescription): callback, callback_params): if callback is None: - raise ConfigError(_('callback is mandatory for dynoptiondescription')) + raise ConfigError(_('callback is mandatory for the dynoptiondescription "{}"' + '').format(self.impl_get_display_name())) def _impl_get_suffixes(self, context, @@ -599,33 +553,49 @@ class DynOptionDescription(OptionDescription): callback=callback, callback_params=callback_params, setting_properties=setting_properties) + if not isinstance(values, list): + raise ValueError(_('invalid suffix "{}" for option "{}", must be a list' + '').format(values, + self.impl_get_display_name())) if len(values) > len(set(values)): - raise ConfigError(_('DynOptionDescription callback return not unique value')) + raise ValueError(_('DynOptionDescription callback return not unique value')) for val in values: if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None: - raise ValueError(_("invalid suffix: {0} for option").format(val)) + raise ValueError(_('invalid suffix "{}" for option "{}"' + '').format(val, + self.impl_get_display_name())) return values class SynDynOptionDescription(object): - __slots__ = ('_opt', '_name', '_suffix') + __slots__ = ('_opt', + '_name', + '_suffix') + + def __init__(self, + opt, + name, + suffix): - def __init__(self, opt, name, suffix): self._opt = opt self._name = name self._suffix = suffix - def __getattr__(self, - name, - setting_properties=undefined, - context=undefined): - if name in dir(self._opt): - return getattr(self._opt, - name) - return self._opt._getattr(name, - setting_properties, - suffix=self._suffix, - context=context) + def __getattr__(self, name): + return getattr(self._opt, name) + + def impl_getchild(self, + name, + setting_properties, + context): + if name.endswith(self._suffix): + oname = name[:-len(self._suffix)] + child = self._children[1][self._children[0].index(oname)] + return self._impl_get_dynchild(child, + self._suffix) + raise AttributeError(_('unknown Option {0} ' + 'in SynDynOptionDescription {1}' + '').format(name, self.impl_getname())) def impl_getname(self): return self._name @@ -636,7 +606,8 @@ class SynDynOptionDescription(object): context=undefined): children = [] for child in self._opt.impl_getchildren(setting_properties): - yield(self._opt._impl_get_dynchild(child, self._suffix)) + yield(self._opt._impl_get_dynchild(child, + self._suffix)) def impl_getpath(self, context): path = self.impl_getopt().impl_getpath(context).split('.') @@ -737,7 +708,7 @@ class MasterSlaves(OptionDescription): c_opt = opt._opt else: c_opt = opt - return child in self._children[1] + return c_opt in self._children[1] def reset(self, opt, @@ -1018,17 +989,15 @@ class MasterSlaves(OptionDescription): type_, resetted_opts) - def _getattr(self, - name, - setting_properties, - suffix=undefined, - context=undefined, - dyn=True): - return super(MasterSlaves, self)._getattr(name, - setting_properties, - suffix, - context, - dyn) + def impl_getchild(self, + name, + setting_properties, + context=undefined, + dyn=True): + return super(MasterSlaves, self).impl_getchild(name, + setting_properties, + context, + dyn) def impl_validate(self, context,