several corrections about dependency

This commit is contained in:
Emmanuel Garette 2017-09-17 15:55:32 +02:00
parent 635b71d291
commit 3567e18256
12 changed files with 225 additions and 78 deletions

View File

@ -15,6 +15,18 @@ from time import sleep, time
from py.test import raises from py.test import raises
global incr
incr = 0
def return_incr():
global incr
incr += 1
return incr
def return_value(val):
return val
def make_description(): def make_description():
u1 = IntOption('u1', '', multi=True) u1 = IntOption('u1', '', multi=True)
u2 = IntOption('u2', '') u2 = IntOption('u2', '')
@ -513,8 +525,7 @@ def test_cache_master_and_slaves_master():
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}}
cfg.val1.val1.append() cfg.val1.val1.append()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}, 'val1': {None: (set([]), None)}}
'val1.val1': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
cfg.cfgimpl_get_values().force_cache() cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
@ -527,10 +538,8 @@ def test_cache_master_and_slaves_master():
cfg.cfgimpl_get_values().force_cache() cfg.cfgimpl_get_values().force_cache()
cfg.val1.val2[1] = 'oui' cfg.val1.val2[1] = 'oui'
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}, 'val1': {None: (set([]), None)}}
'val1.val1': {None: (set(['empty']), None)}, assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
'val1.val2': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None, None], None)}}
cfg.cfgimpl_get_values().force_cache() cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}, 'val1': {None: (set([]), None)},
@ -557,8 +566,7 @@ def test_cache_master_callback():
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}}
cfg.val1.val1.append() cfg.val1.val1.append()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}, 'val1': {None: (set([]), None)}}
'val1.val1': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
cfg.cfgimpl_get_values().force_cache() cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
@ -644,3 +652,17 @@ def test_cache_global_properties():
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test']), None)}, assert c.cfgimpl_get_settings()._p_.get_cached(c) == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}} 'ip_address_service': {None: (set([]), None)}}
def test_callback_value_incr():
val1 = IntOption('val1', "", callback=return_incr)
val2 = IntOption('val2', "", callback=return_value, callback_params={'value': ((val1, False),)})
maconfig = OptionDescription('rootconfig', '', [val1, val2])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1 == 1
sleep(1)
assert cfg.val2 == 1
sleep(1)
assert cfg.val1 == 2
#assert cfg.val2 == 2

View File

@ -53,6 +53,10 @@ def is_config(config, **kwargs):
return 'no' return 'no'
def ret_from_config(config):
return config.val1
def return_raise(*arg): def return_raise(*arg):
raise Exception('test') raise Exception('test')
@ -273,6 +277,19 @@ def test_callback_with_error():
assert cfg.val1 == 'no' assert cfg.val1 == 'no'
def test_callback_with_context_value():
val1 = StrOption("val1", "")
val2 = StrOption("val2", "", callback=ret_from_config, callback_params={'': ((None,),)})
maconfig = OptionDescription('rootconfig', '', [val1, val2])
cfg = Config(maconfig)
cfg.val1 = 'yes'
assert cfg.val1 == 'yes'
assert cfg.val2 == 'yes'
cfg.val1 = 'no'
assert cfg.val1 == 'no'
assert cfg.val2 == 'no'
def test_callback_value(): def test_callback_value():
val1 = StrOption('val1', "", 'val') val1 = StrOption('val1', "", 'val')
val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)}) val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})

View File

@ -807,3 +807,27 @@ def test_consistency_network_netmask_mandatory():
c.read_only() c.read_only()
c.cfgimpl_get_settings().remove('mandatory') c.cfgimpl_get_settings().remove('mandatory')
c.make_dict() c.make_dict()
def test_consistency_has_dependency():
a = IPOption('a', '')
b = NetmaskOption('b', '')
od = OptionDescription('od', '', [a, b])
b.impl_add_consistency('ip_netmask', a)
c = Config(od)
assert c.cfgimpl_get_description().a.impl_has_dependency() is True
assert c.cfgimpl_get_description().b.impl_has_dependency() is True
assert c.cfgimpl_get_description().a.impl_has_dependency(False) is True
assert c.cfgimpl_get_description().b.impl_has_dependency(False) is True
def test_consistency_not_equal_has_dependency():
a = IntOption('a', '')
b = IntOption('b', '')
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', b)
c = Config(od)
assert c.cfgimpl_get_description().a.impl_has_dependency() is False
assert c.cfgimpl_get_description().b.impl_has_dependency() is False
assert c.cfgimpl_get_description().a.impl_has_dependency(False) is True
assert c.cfgimpl_get_description().b.impl_has_dependency(False) is True

View File

@ -87,6 +87,11 @@ def value_empty(value, empty, values):
raise ValueError('error') raise ValueError('error')
def valid_from_config(value, config):
if config.opt1 != u'yes':
raise ValueError("c'est une erreur")
def test_validator(): def test_validator():
opt1 = StrOption('opt1', '', validator=return_true, default='val') opt1 = StrOption('opt1', '', validator=return_true, default='val')
raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')") raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')")
@ -284,6 +289,17 @@ def test_validator_params_context():
assert 'validator' in cfg.cfgimpl_get_settings() assert 'validator' in cfg.cfgimpl_get_settings()
def test_validator_params_context_value():
opt1 = StrOption('opt1', '', 'yes')
opt2 = StrOption('opt2', '', validator=valid_from_config, validator_params={'': ((None,),)}, default='val')
root = OptionDescription('root', '', [opt1, opt2])
cfg = Config(root)
assert cfg.opt1 == 'yes'
assert cfg.opt2 == 'val'
cfg.opt1 = 'no'
raises(ValueError, "cfg.opt2")
def test_validator_params_key(): def test_validator_params_key():
opt1 = StrOption('opt1', '', validator=return_true, validator_params={'param': ('yes',)}, default='val') opt1 = StrOption('opt1', '', validator=return_true, validator_params={'param': ('yes',)}, default='val')
raises(ConfigError, "StrOption('opt2', '', validator=return_true, validator_params={'param_unknown': ('yes',)}, default='val')") raises(ConfigError, "StrOption('opt2', '', validator=return_true, validator_params={'param_unknown': ('yes',)}, default='val')")
@ -447,3 +463,21 @@ def test_validator_slave_param():
cfg.ip_admin_eth0.netmask_admin_eth0 = ['val'] cfg.ip_admin_eth0.netmask_admin_eth0 = ['val']
cfg.ip_admin_eth0.ip_admin_eth0 = ['yes', 'yes'] cfg.ip_admin_eth0.ip_admin_eth0 = ['yes', 'yes']
cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val' cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val'
def test_validator_dependencies():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise")
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
"masque du sous-reseau",
validator=return_true,
validator_params={'param': ((ip_admin_eth0, False),)})
opt2 = StrOption('opt2', '', validator=return_false)
root = OptionDescription('root', '', [ip_admin_eth0, netmask_admin_eth0, opt2])
cfg = Config(root)
assert cfg.cfgimpl_get_description().ip_admin_eth0.impl_has_dependency() is False
assert cfg.cfgimpl_get_description().netmask_admin_eth0.impl_has_dependency() is True
assert cfg.cfgimpl_get_description().opt2.impl_has_dependency() is False
#
assert cfg.cfgimpl_get_description().ip_admin_eth0.impl_has_dependency(False) is True
assert cfg.cfgimpl_get_description().netmask_admin_eth0.impl_has_dependency(False) is False
assert cfg.cfgimpl_get_description().opt2.impl_has_dependency(False) is False

View File

@ -145,3 +145,16 @@ def test_symlink_slaves():
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1 interface1
raises(ValueError, 'interface1.impl_set_group_type(groups.master)') raises(ValueError, 'interface1.impl_set_group_type(groups.master)')
#____________________________________________________________
def test_symlink_dependency():
boolopt = BoolOption("b", "", default=False)
linkopt = SymLinkOption("c", boolopt)
descr = OptionDescription("opt", "",
[linkopt, OptionDescription("s1", "", [boolopt])])
config = Config(descr)
assert config.cfgimpl_get_description().s1.b.impl_has_dependency() is False
assert config.cfgimpl_get_description().c.impl_has_dependency() is True
assert config.cfgimpl_get_description().s1.b.impl_has_dependency(False) is True
assert config.cfgimpl_get_description().c.impl_has_dependency(False) is False

View File

@ -74,12 +74,15 @@ class SubConfig(object):
only_expired=False, only_expired=False,
only=('values', 'properties', 'permissives', 'settings'), only=('values', 'properties', 'permissives', 'settings'),
opt=None, opt=None,
path=None): path=None,
orig_opts=None):
"""reset all settings in cache """reset all settings in cache
:param only_expired: if True reset only expired cached values :param only_expired: if True reset only expired cached values
:type only_expired: boolean :type only_expired: boolean
""" """
if orig_opts is None:
orig_opts = set()
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
if 'values' in only: if 'values' in only:
values = context.cfgimpl_get_values() values = context.cfgimpl_get_values()
@ -117,11 +120,18 @@ class SubConfig(object):
spath2 = spath[-1] spath2 = spath[-1]
spath3 = None spath3 = None
except AttributeError: except AttributeError:
subpath = '.'.join(spath[:-3]) if len(spath) == 2:
dynsubopt = getattr(descr, subpath) subpath = '.'.join(spath)
spath1 = spath[-3] spath1 = spath[-2]
spath2 = spath[-2] spath2 = spath[-1]
spath3 = spath[-1] spath3 = None
dynsubopt = descr
else:
subpath = '.'.join(spath[:-3])
spath1 = spath[-3]
spath2 = spath[-2]
spath3 = spath[-1]
dynsubopt = getattr(descr, subpath)
dynopt = dynsubopt._getattr(spath1, context=context, dyn=False) dynopt = dynsubopt._getattr(spath1, context=context, dyn=False)
for suffix in dynopt._impl_get_suffixes(context): for suffix in dynopt._impl_get_suffixes(context):
path = subpath + '.' + spath1 + suffix + '.' + spath2 + suffix path = subpath + '.' + spath1 + suffix + '.' + spath2 + suffix
@ -140,16 +150,18 @@ class SubConfig(object):
settings._p_.delcache(path) settings._p_.delcache(path)
if 'settings' in only or 'permissives' in only: if 'settings' in only or 'permissives' in only:
settings._pp_.delcache(path) settings._pp_.delcache(path)
for option in getattr(opt, '_dependencies', []): for option in opt._get_dependencies(self):
if option in orig_opts:
continue
if 'values' in only: if 'values' in only:
option.reset_cache(opt, values, 'values') option.reset_cache(opt, values, 'values', orig_opts)
if 'settings' in only: if 'settings' in only:
option.reset_cache(opt, settings, 'settings') option.reset_cache(opt, settings, 'settings', orig_opts)
else: else:
if 'properties' in only: if 'properties' in only:
option.reset_cache(opt, settings, 'properties') option.reset_cache(opt, settings, 'properties', orig_opts)
if 'permissives' in only: if 'permissives' in only:
option.reset_cache(opt, settings, 'permissives') option.reset_cache(opt, settings, 'permissives', orig_opts)
else: else:
if 'values' in only: if 'values' in only:
values._p_.reset_all_cache() values._p_.reset_all_cache()
@ -655,8 +667,8 @@ class _CommonConfig(SubConfig):
def _impl_build_all_caches(self, force_store_values): def _impl_build_all_caches(self, force_store_values):
descr = self.cfgimpl_get_description() descr = self.cfgimpl_get_description()
if not descr.impl_already_build_caches(): if not descr.impl_already_build_caches():
descr.impl_build_cache_option() descr._build_cache_option()
descr.impl_build_cache(self) descr._build_cache(self)
descr.impl_build_force_store_values(self, force_store_values) descr.impl_build_force_store_values(self, force_store_values)
def read_only(self): def read_only(self):
@ -825,11 +837,14 @@ class GroupConfig(_CommonConfig):
only_expired=False, only_expired=False,
only=('values', 'settings'), only=('values', 'settings'),
opt=None, opt=None,
path=None): path=None,
orig_opts=set()):
if isinstance(self, MetaConfig): if isinstance(self, MetaConfig):
super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired, only=only, opt=opt, path=path) super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired, only=only,
opt=opt, path=path, orig_opts=orig_opts)
for child in self._impl_children: for child in self._impl_children:
child.cfgimpl_reset_cache(only_expired=only_expired, only=only, opt=opt, path=path) child.cfgimpl_reset_cache(only_expired=only_expired, only=only, opt=opt, path=path,
orig_opts=orig_opts)
def set_value(self, path, value, _commit=True): def set_value(self, path, value, _commit=True):
"""Setattr not in current GroupConfig, but in each children """Setattr not in current GroupConfig, but in each children

View File

@ -67,7 +67,8 @@ def validate_callback(callback, callback_params, type_, callbackoption):
' not a {} for first argument' ' not a {} for first argument'
).format(type_, type(option))) ).format(type_, type(option)))
if cur_opt != callbackoption: if cur_opt != callbackoption:
cur_opt._add_dependencies(callbackoption) cur_opt._add_dependency(callbackoption)
callbackoption._has_dependency = True
def _validate_force_permissive(force_permissive): def _validate_force_permissive(force_permissive):
#validate force_permissive #validate force_permissive
@ -84,6 +85,8 @@ def validate_callback(callback, callback_params, type_, callbackoption):
raise ValueError(_('{0}_params with length of ' raise ValueError(_('{0}_params with length of '
'tuple as 1 must only have ' 'tuple as 1 must only have '
'None as first value').format(type_)) 'None as first value').format(type_))
if callbk == ((None,)):
callbackoption._has_calc_context = True
return return
elif len(callbk) != 2: elif len(callbk) != 2:
raise ValueError(_('{0}_params must only have 1 or 2 ' raise ValueError(_('{0}_params must only have 1 or 2 '
@ -126,6 +129,7 @@ class Base(object):
#other #other
'_has_dependency', '_has_dependency',
'_dependencies', '_dependencies',
'_has_calc_context',
'__weakref__' '__weakref__'
) )
@ -198,12 +202,26 @@ class Base(object):
validator_params[''] = tuple(params) validator_params[''] = tuple(params)
return validator_params return validator_params
def _set_has_dependency(self): def impl_has_dependency(self, self_is_dep=True):
if not self._is_symlinkoption(): if self_is_dep is True:
self._has_dependency = True if self.impl_is_master_slaves():
return True
return getattr(self, '_has_dependency', False)
else:
return hasattr(self, '_dependencies')
def impl_has_dependency(self): def _get_dependencies(self, context):
return getattr(self, '_has_dependency', False) if context:
od = context.cfgimpl_get_description()
if context and hasattr(od, '_dependencies'):
return set(od._dependencies) | set(getattr(self, '_dependencies', STATIC_TUPLE))
else:
return getattr(self, '_dependencies', STATIC_TUPLE)
def _add_dependency(self, option):
options = set(self._get_dependencies(None))
options.add(option)
self._dependencies = tuple(options)
def impl_set_callback(self, callback, callback_params=None, _init=False): def impl_set_callback(self, callback, callback_params=None, _init=False):
if callback is None and callback_params is not None: if callback is None and callback_params is not None:
@ -242,7 +260,7 @@ class Base(object):
def impl_getproperties(self): def impl_getproperties(self):
return self._properties return self._properties
def _set_readonly(self, has_extra): def _set_readonly(self):
if not self.impl_is_readonly(): if not self.impl_is_readonly():
_setattr = object.__setattr__ _setattr = object.__setattr__
dico = self._informations dico = self._informations
@ -252,10 +270,9 @@ class Base(object):
else: else:
dico = tuple([keys, tuple(dico.values())]) dico = tuple([keys, tuple(dico.values())])
_setattr(self, '_informations', dico) _setattr(self, '_informations', dico)
if has_extra: extra = getattr(self, '_extra', None)
extra = getattr(self, '_extra', None) if extra is not None:
if extra is not None: _setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
def _impl_setsubdyn(self, subdyn): def _impl_setsubdyn(self, subdyn):
self._subdyn = subdyn self._subdyn = subdyn
@ -385,13 +402,15 @@ class BaseOption(Base):
name = name.encode('utf8') name = name.encode('utf8')
return name return name
def reset_cache(self, opt, obj, type_): def reset_cache(self, opt, obj, type_, orig_opts):
context = obj._getcontext() context = obj._getcontext()
path = self.impl_getpath(context) path = self.impl_getpath(context)
obj._p_.delcache(path) obj._p_.delcache(path)
orig_opts.add(opt)
context.cfgimpl_reset_cache(only=(type_,), context.cfgimpl_reset_cache(only=(type_,),
opt=self, opt=self,
path=path) path=path,
orig_opts=orig_opts)
def _is_symlinkoption(self): def _is_symlinkoption(self):
return False return False
@ -410,14 +429,6 @@ def validate_requires_arg(new_option, multi, requires, name):
know more about know more about
the description of the requires dictionary the description of the requires dictionary
""" """
def set_dependency(option):
if not getattr(option, '_dependencies', None):
options = set()
else:
options = set(option._dependencies)
options.add(new_option)
option._dependencies = tuple(options)
def get_option(require): def get_option(require):
option = require['option'] option = require['option']
if not hasattr(option, '_is_symlinkoption'): if not hasattr(option, '_is_symlinkoption'):
@ -427,7 +438,7 @@ def validate_requires_arg(new_option, multi, requires, name):
raise ValueError(_('malformed requirements ' raise ValueError(_('malformed requirements '
'multi option must not set ' 'multi option must not set '
'as requires of non multi option {0}').format(name)) 'as requires of non multi option {0}').format(name))
set_dependency(option) option._add_dependency(new_option)
return option return option
def _set_expected(action, inverse, transitive, same_action, option, expected, operator): def _set_expected(action, inverse, transitive, same_action, option, expected, operator):
@ -453,7 +464,7 @@ def validate_requires_arg(new_option, multi, requires, name):
raise ValueError(_('malformed requirements expected must have ' raise ValueError(_('malformed requirements expected must have '
'option and value for option {0}').format(name)) 'option and value for option {0}').format(name))
option = exp['option'] option = exp['option']
set_dependency(option) option._add_dependency(new_option)
if option is not None: if option is not None:
err = option._validate(exp['value']) err = option._validate(exp['value'])
if err: if err:
@ -561,7 +572,13 @@ class SymLinkOption(OnlyOption):
_setattr = object.__setattr__ _setattr = object.__setattr__
_setattr(self, '_name', name) _setattr(self, '_name', name)
_setattr(self, '_opt', opt) _setattr(self, '_opt', opt)
opt._set_has_dependency() opt._add_dependency(self)
def impl_has_dependency(self, self_is_dep=True):
"""If self_is_dep is True, it has dependency (self._opt), so return True
if self_is_dep is False, cannot has validation or callback, so return False
"""
return self_is_dep is True
def _is_symlinkoption(self): def _is_symlinkoption(self):
return True return True

View File

@ -58,6 +58,9 @@ class MasterSlaves(object):
if add: if add:
for child in childs: for child in childs:
child._master_slaves = self child._master_slaves = self
if child != self.master:
child._add_dependency(self)
self.master._add_dependency(self)
def is_master(self, opt): def is_master(self, opt):
master = self.master.impl_getname() master = self.master.impl_getname()
@ -270,7 +273,9 @@ class MasterSlaves(object):
" which has {1} as master").format( " which has {1} as master").format(
name, self.getmaster(opt).impl_getname())) name, self.getmaster(opt).impl_getname()))
def reset_cache(self, opt, values, type_): def reset_cache(self, opt, values, type_, orig_opts):
path = self.getmaster(opt).impl_getpath(values._getcontext())
values._p_.delcache(path)
for slave in self.getslaves(opt): for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext()) slave_path = slave.impl_getpath(values._getcontext())
values._p_.delcache(slave_path) values._p_.delcache(slave_path)

View File

@ -28,6 +28,7 @@ from ..setting import log, undefined, debug
from ..autolib import carry_out_calculation from ..autolib import carry_out_calculation
from ..error import (ConfigError, ValueWarning, PropertiesOptionError, from ..error import (ConfigError, ValueWarning, PropertiesOptionError,
display_list) display_list)
from itertools import combinations
ALLOWED_CONST_LIST = ['_cons_not_equal'] ALLOWED_CONST_LIST = ['_cons_not_equal']
@ -93,7 +94,6 @@ class Option(OnlyOption):
else: else:
val_call = (validator, validator_params) val_call = (validator, validator_params)
self._val_call = (val_call, None) self._val_call = (val_call, None)
self._set_has_dependency()
if extra is not None: if extra is not None:
_setattr(self, '_extra', extra) _setattr(self, '_extra', extra)
if unique != undefined and not isinstance(unique, bool): if unique != undefined and not isinstance(unique, bool):
@ -131,11 +131,6 @@ class Option(OnlyOption):
def impl_is_multi(self): def impl_is_multi(self):
return getattr(self, '_multi', 1) != 1 return getattr(self, '_multi', 1) != 1
def _add_dependencies(self, option):
options = set(getattr(self, '_dependencies', tuple()))
options.add(option)
self._dependencies = tuple(options)
def _launch_consistency(self, current_opt, func, option, value, context, def _launch_consistency(self, current_opt, func, option, value, context,
index, submulti_index, opts, warnings_only, index, submulti_index, opts, warnings_only,
transitive): transitive):
@ -480,7 +475,7 @@ class Option(OnlyOption):
if init: if init:
# FIXME # FIXME
if func != 'not_equal': if func != 'not_equal':
opt._set_has_dependency() opt._has_dependency = True
def impl_add_consistency(self, func, *other_opts, **params): def impl_add_consistency(self, func, *other_opts, **params):
"""Add consistency means that value will be validate with other_opts """Add consistency means that value will be validate with other_opts
@ -517,7 +512,11 @@ class Option(OnlyOption):
opt._unique = True opt._unique = True
if func != '_cons_not_equal': if func != '_cons_not_equal':
#consistency could generate warnings or errors #consistency could generate warnings or errors
self._set_has_dependency() self._has_dependency = True
for opt in all_cons_opts:
if opt != self:
self._add_dependency(opt)
opt._add_dependency(self)
def _valid_consistency(self, option, value, context, index, submulti_idx, def _valid_consistency(self, option, value, context, index, submulti_idx,
display_warnings, display_error): display_warnings, display_error):

View File

@ -42,10 +42,12 @@ del(sys)
class CacheOptionDescription(BaseOption): class CacheOptionDescription(BaseOption):
__slots__ = ('_cache_paths', '_cache_consistencies', '_cache_force_store_values') __slots__ = ('_cache_paths', '_cache_consistencies', '_cache_force_store_values')
def impl_build_cache(self, config, path='', _consistencies=None, def _build_cache(self, config, path='', _consistencies=None,
cache_option=None, force_store_values=None): cache_option=None, force_store_values=None,
_dependencies=None):
"""validate duplicate option and set option has readonly option """validate duplicate option and set option has readonly option
""" """
# cache_option is None only when we start to build cache
if cache_option is None: if cache_option is None:
if self.impl_is_readonly(): if self.impl_is_readonly():
raise ConfigError(_('option description seems to be part of an other ' raise ConfigError(_('option description seems to be part of an other '
@ -54,8 +56,10 @@ class CacheOptionDescription(BaseOption):
_consistencies = {} _consistencies = {}
cache_option = [] cache_option = []
force_store_values = [] force_store_values = []
_dependencies = []
else: else:
init = False init = False
for option in self._impl_getchildren(dyn=False): for option in self._impl_getchildren(dyn=False):
cache_option.append(option) cache_option.append(option)
if path == '': if path == '':
@ -63,19 +67,14 @@ class CacheOptionDescription(BaseOption):
else: else:
subpath = path + '.' + option.impl_getname() subpath = path + '.' + option.impl_getname()
if isinstance(option, OptionDescription): if isinstance(option, OptionDescription):
option._set_readonly(False) option._set_readonly()
option.impl_build_cache(config, subpath, _consistencies, option._build_cache(config, subpath, _consistencies,
cache_option, force_store_values) cache_option, force_store_values,
#cannot set multi option as OptionDescription requires _dependencies)
else: else:
if option.impl_is_master_slaves('master'): if option.impl_is_master_slaves('master'):
if not getattr(option, '_dependencies', None): option._add_dependency(option.impl_get_master_slaves())
options = set() option._set_readonly()
else:
options = set(option._dependencies)
options.add(option.impl_get_master_slaves())
option._dependencies = tuple(options)
option._set_readonly(True)
is_multi = option.impl_is_multi() is_multi = option.impl_is_multi()
if not option._is_symlinkoption() and 'force_store_value' in option.impl_getproperties(): if not option._is_symlinkoption() and 'force_store_value' in option.impl_getproperties():
force_store_values.append((subpath, option)) force_store_values.append((subpath, option))
@ -102,6 +101,9 @@ class CacheOptionDescription(BaseOption):
[]).append((func, []).append((func,
all_cons_opts, all_cons_opts,
params)) params))
# if context is set to callback, must be reset each time a value change
if hasattr(option, '_has_calc_context'):
_dependencies.append(option)
is_slave = None is_slave = None
if is_multi: if is_multi:
all_requires = option.impl_getrequires() all_requires = option.impl_getrequires()
@ -142,7 +144,9 @@ class CacheOptionDescription(BaseOption):
opt.impl_getname())) opt.impl_getname()))
self._cache_consistencies[opt] = tuple(cons) self._cache_consistencies[opt] = tuple(cons)
self._cache_force_store_values = force_store_values self._cache_force_store_values = force_store_values
self._set_readonly(False) if _dependencies:
self._dependencies = tuple(_dependencies)
self._set_readonly()
def impl_already_build_caches(self): def impl_already_build_caches(self):
return getattr(self, '_cache_paths', None) is not None return getattr(self, '_cache_paths', None) is not None
@ -171,7 +175,7 @@ class CacheOptionDescription(BaseOption):
if value_set: if value_set:
config._impl_values._p_.commit() config._impl_values._p_.commit()
def impl_build_cache_option(self, _currpath=None, cache_path=None, def _build_cache_option(self, _currpath=None, cache_path=None,
cache_option=None): cache_option=None):
if self.impl_is_readonly() or (_currpath is None and getattr(self, '_cache_paths', None) is not None): if self.impl_is_readonly() or (_currpath is None and getattr(self, '_cache_paths', None) is not None):
@ -192,7 +196,7 @@ class CacheOptionDescription(BaseOption):
cache_path.append(path) cache_path.append(path)
if option.impl_is_optiondescription(): if option.impl_is_optiondescription():
_currpath.append(attr) _currpath.append(attr)
option.impl_build_cache_option(_currpath, cache_path, option._build_cache_option(_currpath, cache_path,
cache_option) cache_option)
_currpath.pop() _currpath.pop()
if save: if save:
@ -471,7 +475,6 @@ class OptionDescription(OptionDescriptionWalk):
": this option is not a multi" ": this option is not a multi"
"").format(child.impl_getname(), self.impl_getname())) "").format(child.impl_getname(), self.impl_getname()))
#length of master change slaves length #length of master change slaves length
self._set_has_dependency()
MasterSlaves(self.impl_getname(), children) MasterSlaves(self.impl_getname(), children)
else: # pragma: optional cover else: # pragma: optional cover
raise ValueError(_('group_type: {0}' raise ValueError(_('group_type: {0}'

View File

@ -131,8 +131,6 @@ class Settings(Cache, SqlAlchemyBase):
def delete_session(session_id, session): def delete_session(session_id, session):
print session.query(_Property).all()
print session.query(_Permissive).all()
settings_id = session.query(Settings).filter_by(session_id=session_id).first().id settings_id = session.query(Settings).filter_by(session_id=session_id).first().id
for val in session.query(_Property).filter_by(settings=settings_id).all(): for val in session.query(_Property).filter_by(settings=settings_id).all():
session.delete(val) session.delete(val)

View File

@ -83,8 +83,8 @@ class Storage(object):
values_table = 'CREATE TABLE IF NOT EXISTS value(path TEXT, ' values_table = 'CREATE TABLE IF NOT EXISTS value(path TEXT, '
values_table += 'value TEXT, owner TEXT, idx INTEGER, session_id TEXT NOT NULL, '\ values_table += 'value TEXT, owner TEXT, idx INTEGER, session_id TEXT NOT NULL, '\
'PRIMARY KEY (path, idx, session_id))' 'PRIMARY KEY (path, idx, session_id))'
informations_table = 'CREATE TABLE IF NOT EXISTS information(key TEXT ' informations_table = 'CREATE TABLE IF NOT EXISTS information(key TEXT,'
informations_table += 'KEY, value TEXT, session_id TEXT NOT NULL, ' informations_table += 'value TEXT, session_id TEXT NOT NULL, '
informations_table += 'PRIMARY KEY (key, session_id))' informations_table += 'PRIMARY KEY (key, session_id))'
self.execute(values_table, commit=False) self.execute(values_table, commit=False)
self.execute(informations_table, commit=False) self.execute(informations_table, commit=False)