reorganise optiondescription

This commit is contained in:
Emmanuel Garette 2017-11-29 23:25:34 +01:00
parent c44aab67b8
commit 911af90564
2 changed files with 135 additions and 165 deletions

View file

@ -175,46 +175,45 @@ class SubConfig(object):
force_permissive=force_permissive, force_permissive=force_permissive,
validate_properties=validate_properties, validate_properties=validate_properties,
setting_properties=setting_properties) setting_properties=setting_properties)
if isinstance(self, Exception):
return self, None
return self, path[-1] return self, path[-1]
# ______________________________________________________________________ # ______________________________________________________________________
def __iter__(self, force_permissive=False): # def __iter__(self, force_permissive=False):
"""Pythonesque way of parsing group's ordered options. # """Pythonesque way of parsing group's ordered options.
iteration only on Options (not OptionDescriptions)""" # iteration only on Options (not OptionDescriptions)"""
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties() # 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()): # for child in self.cfgimpl_get_description().impl_getchildren(context=self._cfgimpl_get_context()):
if not child.impl_is_optiondescription(): # if not child.impl_is_optiondescription():
try: # try:
name = child.impl_getname() # name = child.impl_getname()
yield name, self.getattr(name, # yield name, self.getattr(name,
force_permissive=force_permissive, # force_permissive=force_permissive,
setting_properties=setting_properties) # setting_properties=setting_properties)
except GeneratorExit: # pragma: optional cover # except GeneratorExit: # pragma: optional cover
if sys.version_info[0] < 3: # if sys.version_info[0] < 3:
raise StopIteration # raise StopIteration
else: # else:
raise GeneratorExit() # raise GeneratorExit()
except PropertiesOptionError: # pragma: optional cover # except PropertiesOptionError: # pragma: optional cover
pass # option with properties # pass # option with properties
#
def iter_all(self, force_permissive=False): # def iter_all(self, force_permissive=False):
"""A way of parsing options **and** groups. # """A way of parsing options **and** groups.
iteration on Options and OptionDescriptions.""" # iteration on Options and OptionDescriptions."""
for child in self.cfgimpl_get_description().impl_getchildren(): # for child in self.cfgimpl_get_description().impl_getchildren():
try: # try:
yield child.impl_getname(), self.getattr(child.impl_getname(), # yield child.impl_getname(), self.getattr(child.impl_getname(),
force_permissive=force_permissive) # force_permissive=force_permissive)
except GeneratorExit: # pragma: optional cover # except GeneratorExit: # pragma: optional cover
if sys.version_info[0] < 3: # if sys.version_info[0] < 3:
raise StopIteration # raise StopIteration
else: # else:
raise GeneratorExit() # raise GeneratorExit()
except PropertiesOptionError: # pragma: optional cover # except PropertiesOptionError: # pragma: optional cover
pass # option with properties # pass # option with properties
def iter_groups(self, def iter_groups(self,
setting_properties,
group_type=None, group_type=None,
force_permissive=False): force_permissive=False):
"""iteration on groups objects only. """iteration on groups objects only.
@ -230,7 +229,8 @@ class SubConfig(object):
raise TypeError(_("unknown group_type: {0}").format(group_type)) raise TypeError(_("unknown group_type: {0}").format(group_type))
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
setting_properties = context.cfgimpl_get_settings().get_context_properties() 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(): if child.impl_is_optiondescription():
try: try:
if group_type is None or (group_type is not None and if group_type is None or (group_type is not None and
@ -249,20 +249,20 @@ class SubConfig(object):
pass pass
# ______________________________________________________________________ # ______________________________________________________________________
def __str__(self): # def __str__(self):
"Config's string representation" # "Config's string representation"
lines = [] # lines = []
for name, grp in self.iter_groups(): # for name, grp in self.iter_groups():
lines.append("[{0}]".format(name)) # lines.append("[{0}]".format(name))
for name, value in self: # for name, value in self:
try: # try:
lines.append("{0} = {1}".format(name, value)) # lines.append("{0} = {1}".format(name, value))
except UnicodeEncodeError: # pragma: optional cover # except UnicodeEncodeError: # pragma: optional cover
lines.append("{0} = {1}".format(name, # lines.append("{0} = {1}".format(name,
value.encode(default_encoding))) # value.encode(default_encoding)))
return '\n'.join(lines) # return '\n'.join(lines)
#
__repr__ = __str__ # __repr__ = __str__
def _cfgimpl_get_context(self): def _cfgimpl_get_context(self):
"""context could be None, we need to test it """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, self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties) setting_properties=setting_properties)
child = self.cfgimpl_get_description().__getattr__(name, child = self.cfgimpl_get_description().impl_getchild(name,
context=context) setting_properties,
context)
if isinstance(child, (OptionDescription, SynDynOptionDescription)): if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
elif child.impl_is_symlinkoption() and \ elif child.impl_is_symlinkoption() and \
@ -347,8 +348,9 @@ class SubConfig(object):
self, name = self.cfgimpl_get_home_by_path(name, self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties) setting_properties=setting_properties)
child = self.cfgimpl_get_description().__getattr__(name, child = self.cfgimpl_get_description().impl_getchild(name,
context=context) setting_properties,
context)
if isinstance(child, (OptionDescription, SynDynOptionDescription)): if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
elif child.impl_is_symlinkoption() and \ elif child.impl_is_symlinkoption() and \
@ -408,8 +410,9 @@ class SubConfig(object):
setting_properties=setting_properties) setting_properties=setting_properties)
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
option = self.cfgimpl_get_description().__getattr__(name, option = self.cfgimpl_get_description().impl_getchild(name,
context=context) context,
setting_properties)
if option.impl_is_symlinkoption() and isinstance(option, DynSymLinkOption): if option.impl_is_symlinkoption() and isinstance(option, DynSymLinkOption):
# FIXME peuvent-il vraiment etre le 2 ? # FIXME peuvent-il vraiment etre le 2 ?
# si non supprimer tout ces tests inutiles # si non supprimer tout ces tests inutiles
@ -827,11 +830,9 @@ class _CommonConfig(SubConfig):
force_permissive=force_permissive, force_permissive=force_permissive,
validate_properties=validate_properties, validate_properties=validate_properties,
setting_properties=setting_properties) setting_properties=setting_properties)
if isinstance(self, Exception): option = self.cfgimpl_get_description().impl_getchild(path,
return self setting_properties,
option = self.cfgimpl_get_description().__getattr__(path, self._cfgimpl_get_context())
context=self._cfgimpl_get_context(),
setting_properties=setting_properties)
if not validate_properties: if not validate_properties:
return option return option
else: else:

View file

@ -327,41 +327,24 @@ class OptionDescriptionWalk(CacheOptionDescription):
return find_results return find_results
return find_results return find_results
def _getattr(self, def impl_getchild(self,
name, name,
setting_properties, setting_properties,
suffix=undefined, context=undefined,
context=undefined, dyn=True):
dyn=True): if name not in self._children[0]:
error = False child = self._impl_search_dynchild(name,
if suffix is not undefined: context=context,
if undefined in [suffix, context]: # pragma: no cover setting_properties=setting_properties)
raise ConfigError(_("suffix and context needed if " if child:
"it's a dyn option")) return child
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
else: else:
if name in self._children[0]: child = self._children[1][self._children[0].index(name)]
child = self._children[1][self._children[0].index(name)] if not child.impl_is_dynoptiondescription():
if dyn and child.impl_is_dynoptiondescription(): return child
error = True raise AttributeError(_('unknown Option {0} '
else: 'in OptionDescription {1}'
return child '').format(name, self.impl_getname()))
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()))
def impl_get_opt_by_path(self, def impl_get_opt_by_path(self,
path): path):
@ -404,7 +387,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
name, name,
context, context,
setting_properties): setting_properties):
ret = []
for child in self._impl_st_getchildren(only_dyn=True): for child in self._impl_st_getchildren(only_dyn=True):
cname = child.impl_getname() cname = child.impl_getname()
if name.startswith(cname): if name.startswith(cname):
@ -414,7 +396,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
return SynDynOptionDescription(child, return SynDynOptionDescription(child,
name, name,
value) value)
return ret
def __getattr__(self, def __getattr__(self,
name, name,
@ -423,16 +404,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
if name.startswith('_'): if name.startswith('_'):
return object.__getattribute__(self, return object.__getattribute__(self,
name) 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, def _impl_get_dynchild(self,
child, child,
suffix): suffix):
@ -464,7 +435,7 @@ class OptionDescription(OptionDescriptionWalk):
""" """
if not isinstance(children, list): 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, super(OptionDescription, self).__init__(name,
doc=doc, doc=doc,
requires=requires, requires=requires,
@ -491,11 +462,10 @@ class OptionDescription(OptionDescriptionWalk):
raise ConflictError(_('the option\'s name "{}" start as ' raise ConflictError(_('the option\'s name "{}" start as '
'the dynoptiondescription\'s name "{}"').format(child, dynopt)) 'the dynoptiondescription\'s name "{}"').format(child, dynopt))
old = child old = child
_setattr = object.__setattr__ self._children = (tuple(child_names), tuple(children))
_setattr(self, '_children', (tuple(child_names), tuple(children))) self._cache_consistencies = None
_setattr(self, '_cache_consistencies', None)
# the group_type is useful for filtering OptionDescriptions in a config # 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): def impl_getdoc(self):
return self.impl_get_information('doc') return self.impl_get_information('doc')
@ -508,8 +478,7 @@ class OptionDescription(OptionDescriptionWalk):
# ____________________________________________________________ # ____________________________________________________________
def impl_set_group_type(self, def impl_set_group_type(self,
group_type, group_type):
setting_properties):
"""sets a given group object to an OptionDescription """sets a given group object to an OptionDescription
:param group_type: an instance of `GroupType` or `MasterGroupType` :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 if self._group_type != groups.default: # pragma: optional cover
raise TypeError(_('cannot change group_type if already set ' raise TypeError(_('cannot change group_type if already set '
'(old {0}, new {1})').format(self._group_type, '(old {0}, new {1})').format(self._group_type,
group_type)) group_type))
if isinstance(group_type, groups.GroupType): if not 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
raise ValueError(_('group_type: {0}' raise ValueError(_('group_type: {0}'
' not allowed').format(group_type)) ' 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): def impl_get_group_type(self):
return self._group_type return self._group_type
@ -588,7 +541,8 @@ class DynOptionDescription(OptionDescription):
callback, callback,
callback_params): callback_params):
if callback is None: 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, def _impl_get_suffixes(self,
context, context,
@ -599,33 +553,49 @@ class DynOptionDescription(OptionDescription):
callback=callback, callback=callback,
callback_params=callback_params, callback_params=callback_params,
setting_properties=setting_properties) 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)): 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: for val in values:
if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None: 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 return values
class SynDynOptionDescription(object): 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._opt = opt
self._name = name self._name = name
self._suffix = suffix self._suffix = suffix
def __getattr__(self, def __getattr__(self, name):
name, return getattr(self._opt, name)
setting_properties=undefined,
context=undefined): def impl_getchild(self,
if name in dir(self._opt): name,
return getattr(self._opt, setting_properties,
name) context):
return self._opt._getattr(name, if name.endswith(self._suffix):
setting_properties, oname = name[:-len(self._suffix)]
suffix=self._suffix, child = self._children[1][self._children[0].index(oname)]
context=context) 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): def impl_getname(self):
return self._name return self._name
@ -636,7 +606,8 @@ class SynDynOptionDescription(object):
context=undefined): context=undefined):
children = [] children = []
for child in self._opt.impl_getchildren(setting_properties): 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): def impl_getpath(self, context):
path = self.impl_getopt().impl_getpath(context).split('.') path = self.impl_getopt().impl_getpath(context).split('.')
@ -737,7 +708,7 @@ class MasterSlaves(OptionDescription):
c_opt = opt._opt c_opt = opt._opt
else: else:
c_opt = opt c_opt = opt
return child in self._children[1] return c_opt in self._children[1]
def reset(self, def reset(self,
opt, opt,
@ -1018,17 +989,15 @@ class MasterSlaves(OptionDescription):
type_, type_,
resetted_opts) resetted_opts)
def _getattr(self, def impl_getchild(self,
name, name,
setting_properties, setting_properties,
suffix=undefined, context=undefined,
context=undefined, dyn=True):
dyn=True): return super(MasterSlaves, self).impl_getchild(name,
return super(MasterSlaves, self)._getattr(name, setting_properties,
setting_properties, context,
suffix, dyn)
context,
dyn)
def impl_validate(self, def impl_validate(self,
context, context,