better dynoption support

This commit is contained in:
Emmanuel Garette 2018-04-09 21:37:49 +02:00
parent c3be5e82ba
commit 9ea373efdf
17 changed files with 810 additions and 924 deletions

View file

@ -1742,7 +1742,8 @@ def test_options(paths):
# if callback and default_multi:
# continue
# for default in (False,):
# for multi in (False,):
# for multi in (True,):
# print(meta, callback, consistency, require, default_multi, symlink, default, multi)
if multi is submulti and default:
continue
if multi is submulti and consistency:

View file

@ -210,7 +210,7 @@ def test_reset_cache():
api.option('u1').value.get()
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
c.cfgimpl_reset_cache()
c.cfgimpl_reset_cache(None, None, None)
assert 'u1' not in values._p_.get_cached()
assert 'u1' not in settings._p_.get_cached()
api.option('u1').value.get()
@ -222,7 +222,7 @@ def test_reset_cache():
assert 'u1' in settings._p_.get_cached()
assert 'u2' in values._p_.get_cached()
assert 'u2' in settings._p_.get_cached()
c.cfgimpl_reset_cache()
c.cfgimpl_reset_cache(None, None, None)
assert 'u1' not in values._p_.get_cached()
assert 'u1' not in settings._p_.get_cached()
assert 'u2' not in values._p_.get_cached()
@ -237,62 +237,62 @@ def test_reset_cache():
# values = c.cfgimpl_get_values()
# api.option('od1.u1').value.get()
# assert 'od1.u1' in values._p_.get_cached()
# c.od1.cfgimpl_reset_cache()
# c.od1.cfgimpl_reset_cache(None, None, None)
# assert 'od1.u1' not in values._p_.get_cached()
def test_reset_cache_only_expired():
od1 = make_description()
c = Config(od1)
api = getapi(c)
api.property.add('expire')
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
api.option('u1').value.get()
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
c.cfgimpl_reset_cache(True)
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
sleep(1)
api.option('u1').value.get()
sleep(1)
api.option('u2').value.get()
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
assert 'u2' in values._p_.get_cached()
assert 'u2' in settings._p_.get_cached()
c.cfgimpl_reset_cache(True)
assert 'u1' not in values._p_.get_cached()
assert 'u1' not in settings._p_.get_cached()
assert 'u2' in values._p_.get_cached()
assert 'u2' in settings._p_.get_cached()
#def test_reset_cache_only_expired():
# od1 = make_description()
# c = Config(od1)
# api = getapi(c)
# api.property.add('expire')
# values = c.cfgimpl_get_values()
# settings = c.cfgimpl_get_settings()
# api.option('u1').value.get()
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# c.cfgimpl_reset_cache(True)
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# sleep(1)
# api.option('u1').value.get()
# sleep(1)
# api.option('u2').value.get()
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# assert 'u2' in values._p_.get_cached()
# assert 'u2' in settings._p_.get_cached()
# c.cfgimpl_reset_cache(True)
# assert 'u1' not in values._p_.get_cached()
# assert 'u1' not in settings._p_.get_cached()
# assert 'u2' in values._p_.get_cached()
# assert 'u2' in settings._p_.get_cached()
def test_cache_not_expire():
od1 = make_description()
c = Config(od1)
api = getapi(c)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
#api.property.pop('expire')
api.option('u1').value.get()
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
c.cfgimpl_reset_cache(True)
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
sleep(1)
api.option('u2').value.get()
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
assert 'u2' in values._p_.get_cached()
assert 'u2' in settings._p_.get_cached()
c.cfgimpl_reset_cache(True)
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
assert 'u2' in values._p_.get_cached()
assert 'u2' in settings._p_.get_cached()
#def test_cache_not_expire():
# od1 = make_description()
# c = Config(od1)
# api = getapi(c)
# values = c.cfgimpl_get_values()
# settings = c.cfgimpl_get_settings()
# #api.property.pop('expire')
# api.option('u1').value.get()
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# c.cfgimpl_reset_cache(True)
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# sleep(1)
# api.option('u2').value.get()
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# assert 'u2' in values._p_.get_cached()
# assert 'u2' in settings._p_.get_cached()
# c.cfgimpl_reset_cache(True)
# assert 'u1' in values._p_.get_cached()
# assert 'u1' in settings._p_.get_cached()
# assert 'u2' in values._p_.get_cached()
# assert 'u2' in settings._p_.get_cached()
def test_cache_not_cache():

File diff suppressed because it is too large Load diff

View file

@ -604,3 +604,23 @@ def test_wrong_index():
raises(APIError, "api.option('od.ip_admin_eth0', 0).option.get()")
assert api.option('od').option.get()
raises(APIError, "api.option('od', 0).option.get()")
def test_without_master_or_slave():
raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [])")
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0])")
#empty optiondescription is allowed
OptionDescription('ip_admin_eth0', '', [])
def test_master_not_multi():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé")
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])")
def test_slave_not_multi():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])")

View file

@ -704,6 +704,19 @@ def test_callback_master_and_slaves_master_list():
assert api.option('val1.val2', 0).value.get() == None
def test_callback_master_and_slaves_master_slave_list():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_list)
interface1 = MasterSlaves('val1', '', [val1, val2])
#interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
api = getapi(Config(maconfig))
api.property.read_write()
assert api.option('val1.val1').value.get() == []
api.option('val1.val1').value.set(['val1'])
raises(SlaveError, "api.option('val1.val2', 0).value.get()")
def test_callback_master_and_slaves_slave():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_val)

View file

@ -429,8 +429,9 @@ class TiramisuOptionProperty(CommonTiramisuOption):
def reset(self):
"""reset all personalised properties"""
self._get_option()
self.settings.reset(opt=self.config_bag.option,
path=self.path)
self.settings.reset(self.config_bag.option,
self.path,
self.config_bag)
class TiramisuOptionPermissive(CommonTiramisuOption):
@ -470,12 +471,14 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
opt = self._opt
self.settings.setpermissive(opt=opt,
path=path,
config_bag=self.config_bag,
permissive=permissives)
else:
path = self.path
opt = self._get_option()
self.settings.setpermissive(opt=opt,
path=path,
config_bag=self.config_bag,
permissives=permissives)
@count
@ -815,7 +818,9 @@ class TiramisuContextProperty(TiramisuContext):
@count
def reset(self):
"""remove configuration properties"""
self.config_bag.config.cfgimpl_get_settings().reset()
self.config_bag.config.cfgimpl_get_settings().reset(None,
None,
None)
@count
def exportation(self):

View file

@ -149,7 +149,7 @@ def carry_out_calculation(option,
# if callback_params has a callback, launch several time calculate()
master_slave = False
# multi's option should have same value for all option
if option._is_subdyn():
if option.issubdyn():
kwargs['suffix'] = option.impl_getsuffix()
for key, callbacks in callback_params.items():
for callbk in callbacks:
@ -167,7 +167,7 @@ def carry_out_calculation(option,
else:
# callbk is something link (opt, True|False)
opt, force_permissive = callbk
if opt._is_subdyn():
if opt.issubdyn():
opt = DynSymLinkOption(opt,
option._rootpath,
option.impl_getsuffix())
@ -224,18 +224,18 @@ def carry_out_calculation(option,
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
option.impl_is_master_slaves('slave'):
if args or kwargs:
raise SlaveError(_('function "{}" return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
ret,
option.impl_getname()))
else:
raise SlaveError(_('function "{}" with arguments "{}" and "{}" '
'return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
args,
kwargs,
value,
ret,
option.impl_get_display_name()))
else:
raise SlaveError(_('function "{}" return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
ret,
option.impl_getname()))
return ret

View file

@ -83,59 +83,77 @@ class SubConfig(object):
return self._impl_length
def reset_one_option_cache(self,
desc,
values,
settings,
resetted_opts,
config_bag,
opt,
path):
opt.reset_cache(opt,
path,
if path in resetted_opts:
return
resetted_opts.append(path)
for woption in opt._get_dependencies(self):
option = woption()
if option.impl_is_dynoptiondescription():
for doption in option.get_syndynoptiondescriptions(config_bag):
doption_path = doption.impl_getpath(self)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
doption,
doption_path)
elif option.issubdyn():
for doption in desc.build_dynoptions(option, config_bag):
doption_path = doption.impl_getpath(self)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
doption,
doption_path)
else:
option_path = option.impl_getpath(self)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
option,
option_path)
del option
opt.reset_cache(path,
values,
settings,
resetted_opts)
for woption in opt._get_dependencies(self):
option = woption()
option_path = option.impl_getpath(self)
if option_path in resetted_opts:
continue
self.reset_one_option_cache(values,
settings,
resetted_opts,
option,
option_path)
del option
def cfgimpl_reset_cache(self,
only_expired=False,
opt=None,
path=None,
opt,
path,
config_bag,
resetted_opts=None):
"""reset all settings in cache
:param only_expired: if True reset only expired cached values
:type only_expired: boolean
"""
if resetted_opts is None:
resetted_opts = []
context = self.cfgimpl_get_context()
desc = context.cfgimpl_get_description()
values = context.cfgimpl_get_values()
settings = context.cfgimpl_get_settings()
if not None in (opt, path):
if path not in resetted_opts:
self.reset_one_option_cache(values,
settings,
resetted_opts,
opt,
path)
elif only_expired:
# reset cache for expired cache value ony
datetime = int(time())
values._p_.reset_expired_cache(datetime)
settings._p_.reset_expired_cache(datetime)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
opt,
path)
else:
values._p_.reset_all_cache()
settings._p_.reset_all_cache()
@ -862,21 +880,25 @@ class GroupConfig(_CommonConfig):
return self._impl_children
def cfgimpl_reset_cache(self,
only_expired=False,
opt=None,
path=None,
opt,
path,
config_bag,
resetted_opts=None):
if resetted_opts is None:
resetted_opts = []
if isinstance(self, MetaConfig):
super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired,
opt=opt,
path=path,
super(GroupConfig, self).cfgimpl_reset_cache(opt,
path,
config_bag=config_bag,
resetted_opts=copy(resetted_opts))
for child in self._impl_children:
child.cfgimpl_reset_cache(only_expired=only_expired,
opt=opt,
path=path,
if config_bag is None:
nconfig_bag = config_bag
else:
nconfig_bag = config_bag.copy('nooption')
child.cfgimpl_reset_cache(opt,
path,
config_bag=nconfig_bag,
resetted_opts=copy(resetted_opts))
def set_value(self,

View file

@ -369,10 +369,16 @@ class Base(object):
if extra is not None:
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
def _impl_setsubdyn(self,
subdyn):
def _setsubdyn(self,
subdyn):
self._subdyn = weakref.ref(subdyn)
def issubdyn(self):
return getattr(self, '_subdyn', None) is not None
def getsubdyn(self):
return self._subdyn()
def impl_getrequires(self):
return getattr(self, '_requires', STATIC_TUPLE)
@ -477,9 +483,6 @@ class BaseOption(Base):
"to know if a callback has been defined or not"
return self.impl_get_callback()[0] is not None
def _is_subdyn(self):
return getattr(self, '_subdyn', None) is not None
def _impl_valid_string(self,
value):
if not isinstance(value, str):
@ -496,18 +499,14 @@ class BaseOption(Base):
return name
def reset_cache(self,
opt,
path,
values,
settings,
resetted_opts):
if opt in resetted_opts:
return
settings._p_.delcache(path)
settings._pp_.delcache(path)
if not opt.impl_is_optiondescription():
if not self.impl_is_optiondescription():
values._p_.delcache(path)
resetted_opts.append(path)
def impl_is_symlinkoption(self):
return False

View file

@ -26,6 +26,7 @@ from .optiondescription import OptionDescription
from ..setting import groups, undefined
from ..error import ConfigError
from ..autolib import carry_out_calculation
from .syndynoptiondescription import SynDynOptionDescription
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
@ -42,11 +43,11 @@ class DynOptionDescription(OptionDescription):
callback=None,
callback_params=None):
super(DynOptionDescription, self).__init__(name,
doc,
children,
requires,
properties)
super().__init__(name,
doc,
children,
requires,
properties)
# check children + set relation to this dynoptiondescription
for child in children:
if isinstance(child, OptionDescription):
@ -54,11 +55,11 @@ class DynOptionDescription(OptionDescription):
raise ConfigError(_('cannot set optiondescription in a '
'dynoptiondescription'))
for chld in child.impl_getchildren(config_bag=undefined):
chld._impl_setsubdyn(self)
chld._setsubdyn(self)
if child.impl_is_symlinkoption():
raise ConfigError(_('cannot set symlinkoption in a '
'dynoptiondescription'))
child._impl_setsubdyn(self)
child._setsubdyn(self)
# add callback
self.impl_set_callback(callback,
callback_params)
@ -91,3 +92,10 @@ class DynOptionDescription(OptionDescription):
'').format(val,
self.impl_get_display_name()))
return values
def get_syndynoptiondescriptions(self, config_bag):
subpath = self.impl_getpath(config_bag.config).rsplit('.', 1)[0]
for suffix in self._impl_get_suffixes(config_bag):
yield SynDynOptionDescription(self,
subpath,
suffix)

View file

@ -23,7 +23,7 @@ import weakref
from ..i18n import _
from ..setting import groups, undefined, log, debug
from ..setting import groups, undefined
from .optiondescription import OptionDescription
from .option import Option
from ..error import SlaveError, PropertiesOptionError
@ -46,15 +46,10 @@ class MasterSlaves(OptionDescription):
properties=properties)
self._group_type = groups.master
slaves = []
if len(children) < 2:
raise ValueError(_('a master and a slave and mandatory in masterslaves "{}"').format(name))
master = children[0]
if not children:
raise ValueError(_('children is mandatory in masterslaves "{}"').format(name))
for idx, child in enumerate(children):
if idx != 0 and child.impl_getdefault() != []:
raise ValueError(_('not allowed default value for option "{0}" '
'in master/slave object "{1}"'
'').format(child.impl_get_display_name(),
self.impl_get_display_name()))
if child.impl_is_symlinkoption(): # pragma: optional cover
raise ValueError(_('master group "{0}" shall not have '
"a symlinkoption").format(self.impl_get_display_name()))
@ -62,9 +57,12 @@ class MasterSlaves(OptionDescription):
raise ValueError(_('master group "{0}" shall not have '
'a subgroup').format(self.impl_get_display_name()))
if not child.impl_is_multi(): # pragma: optional cover
raise ValueError(_('not allowed option "{0}" '
'in group "{1}"'
': this option is not a multi'
raise ValueError(_('only multi option allowed in master group "{0}" but option '
'"{1}" is not a multi').format(self.impl_get_display_name(),
child.impl_get_display_name()))
if idx != 0 and child.impl_getdefault() != []:
raise ValueError(_('not allowed default value for option "{0}" '
'in master/slave object "{1}"'
'').format(child.impl_get_display_name(),
self.impl_get_display_name()))
# no empty property for save
@ -144,27 +142,37 @@ class MasterSlaves(OptionDescription):
idx)
def reset_cache(self,
opt,
path,
values,
settings,
resetted_opts):
master = self.getmaster()
slaves = self.getslaves()
self._reset_cache(master,
slaves,
values,
settings,
resetted_opts)
def _reset_cache(self,
master,
slaves,
values,
settings,
resetted_opts):
context = values._getcontext()
#FIXME pb avec dyn, devrait etre une option
mopt = self.getmaster()
mpath = mopt.impl_getpath(context)
mopt.reset_cache(mopt,
mpath,
values,
settings,
resetted_opts)
for slave in self.getslaves():
mpath = master.impl_getpath(context)
master.reset_cache(mpath,
values,
settings,
None)
for slave in slaves:
spath = slave.impl_getpath(context)
slave.reset_cache(slave,
spath,
slave.reset_cache(spath,
values,
settings,
resetted_opts)
None)
resetted_opts.append(spath)
def impl_validate_value(self,
option,

View file

@ -375,8 +375,8 @@ class Option(OnlyOption):
other_opts,
init=True,
func=None):
if self._is_subdyn():
dynod = self._subdyn()
if self.issubdyn():
dynod = self.getsubdyn()
else:
dynod = None
if self.impl_is_submulti():
@ -389,11 +389,11 @@ class Option(OnlyOption):
raise ConfigError(_('cannot add consistency with submulti option'))
if not isinstance(opt, Option):
raise ConfigError(_('consistency must be set with an option, not {}').format(opt))
if opt._is_subdyn():
if opt.issubdyn():
if dynod is None:
raise ConfigError(_('almost one option in consistency is '
'in a dynoptiondescription but not all'))
subod = opt._subdyn()
subod = opt.getsubdyn()
if dynod != subod:
raise ConfigError(_('option in consistency must be in same'
' dynoptiondescription'))

View file

@ -23,7 +23,7 @@ from copy import copy
from ..i18n import _
from ..setting import ConfigBag, groups, undefined, owners
from .baseoption import BaseOption
from .baseoption import BaseOption, OnlyOption
from .option import ALLOWED_CONST_LIST, DynSymLinkOption
from .syndynoptiondescription import SynDynOptionDescription
from ..error import ConfigError, ConflictError
@ -172,7 +172,7 @@ class CacheOptionDescription(BaseOption):
# problem with index
raise ConfigError(_('a slave ({0}) cannot have '
'force_store_value property').format(subpath))
if option._is_subdyn():
if option.issubdyn():
raise ConfigError(_('a dynoption ({0}) cannot have '
'force_store_value property').format(subpath))
if not values._p_.hasvalue(subpath):
@ -225,6 +225,31 @@ class CacheOptionDescription(BaseOption):
class OptionDescriptionWalk(CacheOptionDescription):
__slots__ = ('_children',)
def build_dynoptions(self,
option,
config_bag):
dynopt = option.getsubdyn()
rootpath = self.impl_get_path_by_opt(dynopt)
if rootpath == '':
ori_index = 0
else:
ori_index = len(rootpath) + 1
subpaths = option.impl_getpath(config_bag.config)[ori_index:].split('.')[:-1]
if subpaths != ['']:
subpaths = [rootpath] + subpaths
else:
subpaths = [rootpath]
for suffix in dynopt._impl_get_suffixes(config_bag):
subpath = '.'.join([subp + suffix for subp in subpaths])
if isinstance(option, OnlyOption):
yield DynSymLinkOption(option,
subpath,
suffix)
else:
yield SynDynOptionDescription(option,
subpath,
suffix)
def impl_get_options_paths(self,
bytype,
byname,
@ -233,51 +258,24 @@ class OptionDescriptionWalk(CacheOptionDescription):
config_bag):
find_results = []
def _rebuild_dynpath(path,
suffix,
dynopt):
found = False
spath = path.split('.')
for length in range(1, len(spath)):
subpath = '.'.join(spath[0:length])
subopt = self.impl_get_opt_by_path(subpath)
if dynopt == subopt:
found = True
break
if not found: # pragma: no cover
raise ConfigError(_('cannot find dynpath'))
subpath = subpath + suffix
for slength in range(length, len(spath)):
subpath = subpath + '.' + spath[slength] + suffix
return subpath
def _filter_by_name(path,
option):
name = option.impl_getname()
if option._is_subdyn():
if option.issubdyn():
found = False
if byname.startswith(name):
subdyn = option._subdyn()
for suffix in subdyn._impl_get_suffixes(config_bag):
if byname == name + suffix:
for doption in self.build_dynoptions(option, config_bag):
if byname == doption.impl_getname():
dpath = doption.impl_getpath(config_bag.config)
find_results.append((dpath, doption))
found = True
path = _rebuild_dynpath(path,
suffix,
subdyn)
if '.' in path:
subpath = path.rsplit('.', 1)[0]
else:
subpath = ''
option = DynSymLinkOption(option,
subpath,
suffix)
break
if not found:
return False
else:
if not byname == name:
return False
find_results.append((path, option))
find_results.append((path, option))
return True
def _filter_by_type(path,
@ -287,20 +285,10 @@ class OptionDescriptionWalk(CacheOptionDescription):
#if byname is not None, check option byname in _filter_by_name
#not here
if byname is None:
if option._is_subdyn():
name = option.impl_getname()
for suffix in option._subdyn._impl_get_suffixes(config_bag):
path = _rebuild_dynpath(path,
suffix,
option._subdyn)
if '.' in path:
subpath = path.rsplit('.', 1)[0]
else:
subpath = ''
doption = DynSymLinkOption(option,
subpath,
suffix)
find_results.append((subpath, doption))
if option.issubdyn():
for doption in self.build_dynoptions(option, config_bag):
dpath = doption.impl_getname(config_bag.config)
find_results.append((dpath, doption))
else:
find_results.append((path, option))
return True
@ -322,22 +310,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
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(config_bag):
path = _rebuild_dynpath(path,
suffix,
option._subdyn)
if '.' in path:
subpath = path.rsplit('.', 1)[0]
else:
subpath = ''
doption = DynSymLinkOption(option,
subpath,
suffix)
find_results.append((path, doption))
if option.issubdyn():
for doption in self.build_dynoptions(option, config_bag):
dpath = doption.impl_getpath(config_bag.config)
find_results.append((dpath, doption))
else:
find_results.append((path, option))
find_results.append((dpath, option))
else:
if _filter(path, option) is False:
continue
@ -381,24 +359,23 @@ class OptionDescriptionWalk(CacheOptionDescription):
def impl_getchildren(self,
config_bag,
context=None,
dyn=True):
cname = None
subpath = None
for child in self._impl_st_getchildren():
if dyn and child.impl_is_dynoptiondescription():
if context is None:
if config_bag.config is None:
raise ConfigError(_('need context'))
if cname is None:
if context.cfgimpl_get_description() == self:
cname = ''
if subpath is None:
if config_bag.config.cfgimpl_get_description() == self:
subpath = ''
else:
cname = self.impl_getpath(context)
subpath = self.impl_getpath(config_bag.config)
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = child
for value in child._impl_get_suffixes(sconfig_bag):
for suffix in child._impl_get_suffixes(sconfig_bag):
yield SynDynOptionDescription(child,
cname,
value)
subpath,
suffix)
else:
yield child

View file

@ -55,37 +55,12 @@ class SymLinkOption(OnlyOption):
def impl_getopt(self):
return self._opt
#def impl_get_information(self,
# key,
# default=undefined):
# return self._opt.impl_get_information(key, default)
def impl_is_readonly(self):
return True
#def impl_getproperties(self):
# return self._opt.impl_getproperties()
#def impl_get_callback(self):
# return self._opt.impl_get_callback()
#def impl_has_callback(self):
# "to know if a callback has been defined or not"
# return self._opt.impl_has_callback()
#def impl_is_multi(self):
# return self._opt.impl_is_multi()
#def _is_subdyn(self):
# return getattr(self._opt, '_subdyn', None) is not None
def get_consistencies(self):
return ()
def _has_consistencies(self,
context):
return option._opt._has_consistencies(context)
class DynSymLinkOption(object):
__slots__ = ('_rootpath',
@ -110,7 +85,6 @@ class DynSymLinkOption(object):
return self._opt == left._opt and \
self._rootpath == left._rootpath and \
self._suffix == left._suffix
return True
def impl_getname(self):
return self._opt.impl_getname() + self._suffix
@ -126,8 +100,6 @@ class DynSymLinkOption(object):
def impl_getpath(self,
context):
if self._rootpath == '':
return self.impl_getname()
return self._rootpath + '.' + self.impl_getname()
def impl_validate(self,

View file

@ -19,7 +19,7 @@
# the whole pypy projet is under MIT licence
# ____________________________________________________________
from ..i18n import _
from ..setting import undefined
from ..setting import groups, undefined
from .symlinkoption import DynSymLinkOption
@ -32,7 +32,6 @@ class SynDynOptionDescription(object):
opt,
subpath,
suffix):
self._opt = opt
self._subpath = subpath
self._suffix = suffix
@ -68,13 +67,13 @@ class SynDynOptionDescription(object):
config_bag,
dyn=True):
children = []
subpath = self.impl_getpath()
subpath = self.impl_getpath(config_bag.config)
for child in self._opt.impl_getchildren(config_bag):
yield(self._opt._impl_get_dynchild(child,
self._suffix,
subpath))
def impl_getpath(self):
def impl_getpath(self, context):
subpath = self._subpath
if subpath != '':
subpath += '.'
@ -83,16 +82,35 @@ class SynDynOptionDescription(object):
def getmaster(self):
master = self._opt.getmaster()
return DynSymLinkOption(master,
self.impl_getpath(),
self.impl_getpath(None),
self._suffix)
def getslaves(self):
subpath = self.impl_getpath()
subpath = self.impl_getpath(None)
for slave in self._opt.getslaves():
yield DynSymLinkOption(slave,
subpath,
self._suffix)
def reset_cache(self,
path,
values,
settings,
resetted_opts):
if self.impl_get_group_type() == groups.master:
master = self.getmaster()
slaves = self.getslaves()
self._reset_cache(master,
slaves,
values,
settings,
resetted_opts)
else:
self._opt.reset_cache(path,
values,
settings,
resetted_opts)
def pop(self,
*args,
**kwargs):

View file

@ -600,15 +600,21 @@ class Settings(object):
self._p_.setproperties(path,
properties)
#values too because of slave values could have a PropertiesOptionError has value
self._getcontext().cfgimpl_reset_cache(opt=opt,
path=path)
self._getcontext().cfgimpl_reset_cache(opt,
path,
config_bag)
def set_context_permissive(self, permissive):
self.setpermissive(None, None, permissive)
def set_context_permissive(self,
permissive):
self.setpermissive(None,
None,
None,
permissive)
def setpermissive(self,
opt,
path,
config_bag,
permissives):
"""
enables us to put the permissives in the storage
@ -631,15 +637,17 @@ class Settings(object):
raise ConfigError(_('cannot add those permissives: {0}').format(
' '.join(forbidden_permissives)))
self._pp_.setpermissive(path, permissives)
self._getcontext().cfgimpl_reset_cache(opt=opt,
path=path)
self._getcontext().cfgimpl_reset_cache(opt,
path,
config_bag)
#____________________________________________________________
# reset methods
def reset(self,
opt=None,
path=None,
opt,
path,
config_bag,
all_properties=False):
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig'))
@ -655,8 +663,9 @@ class Settings(object):
if opt is not None and path is None:
path = opt.impl_getpath(self._getcontext())
self._p_.delproperties(path)
self._getcontext().cfgimpl_reset_cache(opt=opt,
path=path)
self._getcontext().cfgimpl_reset_cache(opt,
path,
config_bag)
#____________________________________________________________
# validate properties

View file

@ -205,8 +205,9 @@ class Values(object):
if is_cache and cache_value == _value:
return
# calculated value is a new value, so reset cache
context.cfgimpl_reset_cache(opt=opt,
path=path)
context.cfgimpl_reset_cache(opt,
path,
config_bag)
if opt.impl_is_master_slaves('slave'):
index_ = index
@ -409,8 +410,9 @@ class Values(object):
config_bag,
commit=True):
self._getcontext().cfgimpl_reset_cache(opt=config_bag.option,
path=path)
self._getcontext().cfgimpl_reset_cache(config_bag.option,
path,
config_bag)
if isinstance(value, list):
# copy
value = list(value)
@ -601,8 +603,9 @@ class Values(object):
else:
self._p_.resetvalue(path,
_commit)
context.cfgimpl_reset_cache(opt=opt,
path=path)
context.cfgimpl_reset_cache(config_bag.option,
path,
config_bag)
def reset_slave(self,
path,
@ -627,8 +630,9 @@ class Values(object):
value,
config_bag)
self._p_.resetvalue_index(path, index)
context.cfgimpl_reset_cache(opt=config_bag.option,
path=path)
context.cfgimpl_reset_cache(config_bag.option,
path,
config_bag)
def reset_master(self,
subconfig,