add test for master/slave and callback
This commit is contained in:
@ -65,7 +65,8 @@ class CacheOptionDescription(BaseOption):
|
||||
else:
|
||||
init = False
|
||||
|
||||
for option in self._impl_getchildren(dyn=False):
|
||||
for option in self.impl_getchildren(setting_properties=undefined,
|
||||
dyn=False):
|
||||
cache_option.append(option)
|
||||
if path == '':
|
||||
subpath = option.impl_getname()
|
||||
@ -199,7 +200,8 @@ class CacheOptionDescription(BaseOption):
|
||||
if cache_path is None:
|
||||
cache_path = []
|
||||
cache_option = []
|
||||
for option in self._impl_getchildren(dyn=False):
|
||||
for option in self.impl_getchildren(setting_properties=undefined,
|
||||
dyn=False):
|
||||
attr = option.impl_getname()
|
||||
path = str('.'.join(_currpath + [attr]))
|
||||
cache_option.append(option)
|
||||
@ -223,7 +225,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
byname,
|
||||
_subpath,
|
||||
only_first,
|
||||
context):
|
||||
context,
|
||||
setting_properties):
|
||||
find_results = []
|
||||
|
||||
def _rebuild_dynpath(path,
|
||||
@ -251,8 +254,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
found = False
|
||||
if byname.startswith(name):
|
||||
subdyn = option._subdyn()
|
||||
for suffix in subdyn._impl_get_suffixes(
|
||||
context):
|
||||
for suffix in subdyn._impl_get_suffixes(context,
|
||||
setting_properties):
|
||||
if byname == name + suffix:
|
||||
found = True
|
||||
path = _rebuild_dynpath(path,
|
||||
@ -278,8 +281,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
if byname is None:
|
||||
if option._is_subdyn():
|
||||
name = option.impl_getname()
|
||||
for suffix in option._subdyn._impl_get_suffixes(
|
||||
context):
|
||||
for suffix in option._subdyn._impl_get_suffixes(context,
|
||||
setting_properties):
|
||||
spath = _rebuild_dynpath(path,
|
||||
suffix,
|
||||
option._subdyn)
|
||||
@ -299,22 +302,22 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
return _filter_by_name(path, option)
|
||||
|
||||
opts, paths = self._cache_paths
|
||||
for index in xrange(0, len(paths)):
|
||||
for index, path in enumerate(paths):
|
||||
option = opts[index]
|
||||
if option.impl_is_optiondescription():
|
||||
continue
|
||||
path = paths[index]
|
||||
if _subpath is not None and not path.startswith(_subpath + '.'):
|
||||
continue
|
||||
if bytype == byname is None:
|
||||
if option._is_subdyn():
|
||||
name = option.impl_getname()
|
||||
for suffix in option._subdyn._impl_get_suffixes(
|
||||
context):
|
||||
spath = _rebuild_dynpath(path, suffix,
|
||||
for suffix in option._subdyn._impl_get_suffixes(context,
|
||||
setting_properties):
|
||||
spath = _rebuild_dynpath(path,
|
||||
suffix,
|
||||
option._subdyn)
|
||||
find_results.append((spath, option._impl_to_dyn(
|
||||
name + suffix, spath)))
|
||||
find_results.append((spath, option._impl_to_dyn(name + suffix,
|
||||
spath)))
|
||||
else:
|
||||
find_results.append((path, option))
|
||||
else:
|
||||
@ -324,15 +327,9 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
return find_results
|
||||
return find_results
|
||||
|
||||
def _impl_st_getchildren(self,
|
||||
context,
|
||||
only_dyn=False):
|
||||
for child in self._children[1]:
|
||||
if only_dyn is False or child.impl_is_dynoptiondescription():
|
||||
yield(child)
|
||||
|
||||
def _getattr(self,
|
||||
name,
|
||||
setting_properties,
|
||||
suffix=undefined,
|
||||
context=undefined,
|
||||
dyn=True):
|
||||
@ -356,7 +353,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
return child
|
||||
else:
|
||||
child = self._impl_search_dynchild(name,
|
||||
context=context)
|
||||
context=context,
|
||||
setting_properties=setting_properties)
|
||||
if child != []:
|
||||
return child
|
||||
error = True
|
||||
@ -365,16 +363,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
'in OptionDescription {1}'
|
||||
'').format(name, self.impl_getname()))
|
||||
|
||||
def impl_getpaths(self,
|
||||
include_groups=False,
|
||||
_currpath=None):
|
||||
"""returns a list of all paths in self, recursively
|
||||
_currpath should not be provided (helps with recursion)
|
||||
"""
|
||||
return _impl_getpaths(self,
|
||||
include_groups,
|
||||
_currpath)
|
||||
|
||||
def impl_get_opt_by_path(self,
|
||||
path):
|
||||
if getattr(self, '_cache_paths', None) is None:
|
||||
@ -391,25 +379,47 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
raise AttributeError(_('no option {0} found').format(opt))
|
||||
return self._cache_paths[1][self._cache_paths[0].index(opt)]
|
||||
|
||||
def _impl_getchildren(self,
|
||||
dyn=True,
|
||||
context=undefined):
|
||||
for child in self._impl_st_getchildren(context):
|
||||
def impl_getchildren(self,
|
||||
setting_properties,
|
||||
dyn=True,
|
||||
context=undefined):
|
||||
for child in self._impl_st_getchildren():
|
||||
cname = child.impl_getname()
|
||||
if dyn and child.impl_is_dynoptiondescription():
|
||||
for value in child._impl_get_suffixes(context):
|
||||
for value in child._impl_get_suffixes(context,
|
||||
setting_properties):
|
||||
yield SynDynOptionDescription(child,
|
||||
cname + value,
|
||||
value)
|
||||
else:
|
||||
yield child
|
||||
|
||||
def impl_getchildren(self):
|
||||
return list(self._impl_getchildren())
|
||||
def _impl_st_getchildren(self,
|
||||
only_dyn=False):
|
||||
for child in self._children[1]:
|
||||
if only_dyn is False or child.impl_is_dynoptiondescription():
|
||||
yield child
|
||||
|
||||
def _impl_search_dynchild(self,
|
||||
name,
|
||||
context,
|
||||
setting_properties):
|
||||
ret = []
|
||||
for child in self._impl_st_getchildren(only_dyn=True):
|
||||
cname = child.impl_getname()
|
||||
if name.startswith(cname):
|
||||
for value in child._impl_get_suffixes(context,
|
||||
setting_properties):
|
||||
if name == cname + value:
|
||||
return SynDynOptionDescription(child,
|
||||
name,
|
||||
value)
|
||||
return ret
|
||||
|
||||
def __getattr__(self,
|
||||
name,
|
||||
context=undefined):
|
||||
context=undefined,
|
||||
setting_properties=undefined):
|
||||
if name.startswith('_'):
|
||||
return object.__getattribute__(self,
|
||||
name)
|
||||
@ -417,24 +427,11 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||
path = name.split('.')[0]
|
||||
subpath = '.'.join(name.split('.')[1:])
|
||||
return self.__getattr__(path, context=context).__getattr__(subpath,
|
||||
context=context)
|
||||
context=context,
|
||||
setting_properties=setting_properties)
|
||||
return self._getattr(name,
|
||||
context=context)
|
||||
|
||||
def _impl_search_dynchild(self,
|
||||
name,
|
||||
context):
|
||||
ret = []
|
||||
for child in self._impl_st_getchildren(context,
|
||||
only_dyn=True):
|
||||
cname = child.impl_getname()
|
||||
if name.startswith(cname):
|
||||
for value in child._impl_get_suffixes(context):
|
||||
if name == cname + value:
|
||||
return SynDynOptionDescription(child,
|
||||
name,
|
||||
value)
|
||||
return ret
|
||||
context=context,
|
||||
setting_properties=setting_properties)
|
||||
|
||||
def _impl_get_dynchild(self,
|
||||
child,
|
||||
@ -466,6 +463,8 @@ class OptionDescription(OptionDescriptionWalk):
|
||||
:param children: a list of options (including optiondescriptions)
|
||||
|
||||
"""
|
||||
if not isinstance(children, list):
|
||||
raise ValueError(_('children in optiondescription "{}"must be a liste').format(name))
|
||||
super(OptionDescription, self).__init__(name,
|
||||
doc=doc,
|
||||
requires=requires,
|
||||
@ -509,7 +508,8 @@ class OptionDescription(OptionDescriptionWalk):
|
||||
|
||||
# ____________________________________________________________
|
||||
def impl_set_group_type(self,
|
||||
group_type):
|
||||
group_type,
|
||||
setting_properties):
|
||||
"""sets a given group object to an OptionDescription
|
||||
|
||||
:param group_type: an instance of `GroupType` or `MasterGroupType`
|
||||
@ -523,7 +523,7 @@ class OptionDescription(OptionDescriptionWalk):
|
||||
self._group_type = group_type
|
||||
if isinstance(group_type, groups.MasterGroupType):
|
||||
raise Exception('please use MasterSlaves object instead of OptionDescription')
|
||||
children = self.impl_getchildren()
|
||||
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 "
|
||||
@ -545,23 +545,6 @@ class OptionDescription(OptionDescriptionWalk):
|
||||
def impl_get_group_type(self):
|
||||
return self._group_type
|
||||
|
||||
def __getstate__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _impl_get_suffixes(self,
|
||||
context):
|
||||
callback, callback_params = self.impl_get_callback()
|
||||
values = carry_out_calculation(self,
|
||||
context=context,
|
||||
callback=callback,
|
||||
callback_params=callback_params)
|
||||
if len(values) > len(set(values)):
|
||||
raise ConfigError(_('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))
|
||||
return values
|
||||
|
||||
def impl_validate_value(self,
|
||||
option,
|
||||
value,
|
||||
@ -570,6 +553,7 @@ class OptionDescription(OptionDescriptionWalk):
|
||||
|
||||
|
||||
class DynOptionDescription(OptionDescription):
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
doc,
|
||||
@ -584,18 +568,20 @@ class DynOptionDescription(OptionDescription):
|
||||
children,
|
||||
requires,
|
||||
properties)
|
||||
# check children + set relation to this dynoptiondescription
|
||||
for child in children:
|
||||
if isinstance(child, OptionDescription):
|
||||
if child.impl_get_group_type() != groups.master:
|
||||
raise ConfigError(_('cannot set optiondescription in a '
|
||||
'dynoptiondescription'))
|
||||
for chld in child._impl_getchildren():
|
||||
for chld in child.impl_getchildren(setting_properties=undefined):
|
||||
chld._impl_setsubdyn(self)
|
||||
if child.impl_is_symlinkoption():
|
||||
raise ConfigError(_('cannot set symlinkoption in a '
|
||||
'dynoptiondescription'))
|
||||
child._impl_setsubdyn(self)
|
||||
self.impl_set_callback(callback,
|
||||
# add callback
|
||||
self.impl_set_callback(callback,
|
||||
callback_params)
|
||||
|
||||
def _validate_callback(self,
|
||||
@ -604,6 +590,22 @@ class DynOptionDescription(OptionDescription):
|
||||
if callback is None:
|
||||
raise ConfigError(_('callback is mandatory for dynoptiondescription'))
|
||||
|
||||
def _impl_get_suffixes(self,
|
||||
context,
|
||||
setting_properties):
|
||||
callback, callback_params = self.impl_get_callback()
|
||||
values = carry_out_calculation(self,
|
||||
context=context,
|
||||
callback=callback,
|
||||
callback_params=callback_params,
|
||||
setting_properties=setting_properties)
|
||||
if len(values) > len(set(values)):
|
||||
raise ConfigError(_('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))
|
||||
return values
|
||||
|
||||
|
||||
class SynDynOptionDescription(object):
|
||||
__slots__ = ('_opt', '_name', '_suffix')
|
||||
@ -615,36 +617,33 @@ class SynDynOptionDescription(object):
|
||||
|
||||
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 impl_getname(self):
|
||||
return self._name
|
||||
|
||||
def _impl_getchildren(self,
|
||||
dyn=True,
|
||||
context=undefined):
|
||||
def impl_getchildren(self,
|
||||
setting_properties,
|
||||
dyn=True,
|
||||
context=undefined):
|
||||
children = []
|
||||
for child in self._opt._impl_getchildren():
|
||||
for child in self._opt.impl_getchildren(setting_properties):
|
||||
yield(self._opt._impl_get_dynchild(child, self._suffix))
|
||||
|
||||
def impl_getchildren(self):
|
||||
return self._impl_getchildren()
|
||||
|
||||
def impl_getpath(self, context):
|
||||
path = self.impl_getopt().impl_getpath(context).split('.')
|
||||
path[-1] += self._suffix
|
||||
path.append(self._name)
|
||||
return '.'.join(path)
|
||||
|
||||
def impl_getpaths(self, include_groups=False, _currpath=None):
|
||||
return _impl_getpaths(self, include_groups, _currpath)
|
||||
|
||||
def impl_getopt(self):
|
||||
return self._opt
|
||||
|
||||
@ -667,6 +666,8 @@ class MasterSlaves(OptionDescription):
|
||||
self._group_type = groups.master
|
||||
slaves = []
|
||||
master = children[0]
|
||||
if not children:
|
||||
raise ValueError(_('children is mandatory in masterslaves "{}"').format(name))
|
||||
for child in children[1:]:
|
||||
if child.impl_getdefault() != []:
|
||||
raise ValueError(_("not allowed default value for option {0} "
|
||||
@ -758,15 +759,19 @@ class MasterSlaves(OptionDescription):
|
||||
opt,
|
||||
path,
|
||||
values,
|
||||
index):
|
||||
index,
|
||||
setting_properties,
|
||||
force_permissive=False):
|
||||
|
||||
for slave in self.getslaves(opt):
|
||||
slave_path = slave.impl_getpath(values._getcontext())
|
||||
slavelen = values._p_.get_max_length(slave_path)
|
||||
if not values.is_default_owner(slave,
|
||||
validate_properties=False,
|
||||
slave_path,
|
||||
setting_properties,
|
||||
validate_meta=False,
|
||||
index=index):
|
||||
index=index,
|
||||
force_permissive=force_permissive):
|
||||
#FIXME # just for raise if needed
|
||||
#multi = values.get_cached_value(slave,
|
||||
# validate=False,
|
||||
@ -834,11 +839,9 @@ class MasterSlaves(OptionDescription):
|
||||
path=path,
|
||||
validate=validate,
|
||||
force_permissive=force_permissive,
|
||||
validate_properties=validate_properties,
|
||||
self_properties=self_properties,
|
||||
index=index,
|
||||
setting_properties=setting_properties,
|
||||
check_frozen=check_frozen)
|
||||
setting_properties=setting_properties)
|
||||
|
||||
def _getslave(self, values, opt, path, validate, force_permissive,
|
||||
trusted_cached_properties, validate_properties, setting_properties,
|
||||
@ -976,7 +979,12 @@ class MasterSlaves(OptionDescription):
|
||||
return value
|
||||
return len(value)
|
||||
|
||||
def validate_slave_length(self, masterlen, valuelen, name, opt, setitem=False):
|
||||
def validate_slave_length(self,
|
||||
masterlen,
|
||||
valuelen,
|
||||
name,
|
||||
opt,
|
||||
setitem=False):
|
||||
if valuelen > masterlen or (valuelen < masterlen and setitem):
|
||||
if debug: # pragma: no cover
|
||||
log.debug('validate_slave_length: masterlen: {0}, valuelen: {1}, '
|
||||
@ -987,19 +995,49 @@ class MasterSlaves(OptionDescription):
|
||||
" which has {1} as master").format(
|
||||
name, opt.impl_getname()))
|
||||
|
||||
def reset_cache(self, opt, obj, type_, resetted_opts):
|
||||
def reset_cache(self,
|
||||
opt,
|
||||
path,
|
||||
obj,
|
||||
type_,
|
||||
resetted_opts):
|
||||
context = obj._getcontext()
|
||||
#FIXME pb avec dyn, devrait etre une option
|
||||
mopt = self.getmaster(None)
|
||||
mopt.reset_cache(mopt, obj, type_, resetted_opts)
|
||||
mpath = mopt.impl_getpath(context)
|
||||
mopt.reset_cache(mopt,
|
||||
mpath,
|
||||
obj,
|
||||
type_,
|
||||
resetted_opts)
|
||||
for slave in self.getslaves(mopt):
|
||||
slave.reset_cache(slave, obj, type_, resetted_opts)
|
||||
spath = slave.impl_getpath(context)
|
||||
slave.reset_cache(slave,
|
||||
spath,
|
||||
obj,
|
||||
type_,
|
||||
resetted_opts)
|
||||
|
||||
def _getattr(self, name, suffix=undefined, context=undefined, dyn=True):
|
||||
return super(MasterSlaves, self)._getattr(name, suffix, context, dyn)
|
||||
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_validate(self, context, force_permissive, setting_properties, masterlen=None,
|
||||
slavelen=None, opt=None, setitem=False):
|
||||
def impl_validate(self,
|
||||
context,
|
||||
force_permissive,
|
||||
setting_properties,
|
||||
masterlen=None,
|
||||
slavelen=None,
|
||||
opt=None,
|
||||
setitem=False):
|
||||
values = context.cfgimpl_get_values()
|
||||
if masterlen is None:
|
||||
master = self.getmaster(opt)
|
||||
@ -1021,27 +1059,11 @@ class MasterSlaves(OptionDescription):
|
||||
slavelen = values._p_.get_max_length(slave_path)
|
||||
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), master)
|
||||
|
||||
def impl_validate_value(self, option, value, context):
|
||||
def impl_validate_value(self,
|
||||
option,
|
||||
value,
|
||||
context):
|
||||
if option.impl_is_master_slaves('master') and isinstance(value, list):
|
||||
if len(value) < context._impl_length:
|
||||
return ValueError(_('cannot reduce length of master "{}"'
|
||||
'').format(option.impl_get_display_name()))
|
||||
|
||||
|
||||
def _impl_getpaths(klass, include_groups, _currpath):
|
||||
"""returns a list of all paths in klass, recursively
|
||||
_currpath should not be provided (helps with recursion)
|
||||
"""
|
||||
if _currpath is None:
|
||||
_currpath = []
|
||||
paths = []
|
||||
for option in klass._impl_getchildren():
|
||||
attr = option.impl_getname()
|
||||
if option.impl_is_optiondescription():
|
||||
if include_groups:
|
||||
paths.append('.'.join(_currpath + [attr]))
|
||||
paths += option.impl_getpaths(include_groups=include_groups,
|
||||
_currpath=_currpath + [attr])
|
||||
else:
|
||||
paths.append('.'.join(_currpath + [attr]))
|
||||
return paths
|
||||
|
Reference in New Issue
Block a user