This commit is contained in:
Emmanuel Garette 2019-06-12 08:45:56 +02:00
parent 4df36a5548
commit 620e8bbf2e
10 changed files with 231 additions and 219 deletions

View File

@ -709,7 +709,7 @@ def test_groups_with_leader_importation():
maconfig = OptionDescription('toto', '', [interface1]) maconfig = OptionDescription('toto', '', [interface1])
api = Config(maconfig) api = Config(maconfig)
api.property.read_write() api.property.read_write()
api.value.importation((('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0',), (None, (0, 1)), (('192.168.1.1', '192.168.1.0'), ('255.255.255.255', '255.255.255.0')), ('user', ('user', 'user')))) api.value.importation([['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'], [None, [0, 1]], [['192.168.1.1', '192.168.1.0'], ['255.255.255.255', '255.255.255.0']], ['user', ['user', 'user']]])
api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.1', '192.168.1.0'] api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.1', '192.168.1.0']
api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.255' api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.255'
api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.0' api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.0'

View File

@ -101,7 +101,7 @@ class CommonTiramisu(TiramisuHelp):
raise APIError('index must be set only with a follower option') raise APIError('index must be set only with a follower option')
self._length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag) self._length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
if index >= self._length: if index >= self._length:
raise LeadershipError(_('index "{}" is higher than the leadership length "{}" ' raise LeadershipError(_('index "{}" is greater than the leadership length "{}" '
'for option "{}"').format(index, 'for option "{}"').format(index,
self._length, self._length,
option.impl_get_display_name())) option.impl_get_display_name()))
@ -118,7 +118,8 @@ class CommonTiramisuOption(CommonTiramisu):
def __init__(self, def __init__(self,
name: str, name: str,
subconfig: Union[KernelConfig, SubConfig], subconfig: Union[KernelConfig, SubConfig],
option_bag: OptionBag) -> None: option_bag: OptionBag,
config: 'Config'=None) -> None:
self._option_bag = option_bag self._option_bag = option_bag
self._name = name self._name = name
self._subconfig = subconfig self._subconfig = subconfig
@ -136,7 +137,7 @@ class CommonTiramisuOption(CommonTiramisu):
raise APIError(_('index must be set with the follower option "{}"').format(self._option_bag.path)) raise APIError(_('index must be set with the follower option "{}"').format(self._option_bag.path))
def __getattr__(self, name): def __getattr__(self, name):
raise APIError(_('unknown method {}').format(name)) raise APIError(_('unknown method {} in {}').format(name, self.__class__.__name__))
class _TiramisuOptionOptionDescription(CommonTiramisuOption): class _TiramisuOptionOptionDescription(CommonTiramisuOption):
@ -144,6 +145,14 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption):
_allow_optiondescription = True _allow_optiondescription = True
_follower_need_index = False _follower_need_index = False
def __init__(self,
name: str,
subconfig: Union[KernelConfig, SubConfig],
option_bag: OptionBag,
config: "Subconfig") -> None:
super().__init__(name, subconfig, option_bag)
self._config = config
def get(self): def get(self):
"""Get Tiramisu option""" """Get Tiramisu option"""
return self._option_bag.option return self._option_bag.option
@ -195,27 +204,22 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption):
only_raises=False): only_raises=False):
"""Get properties for an option""" """Get properties for an option"""
settings = self._option_bag.config_bag.context.cfgimpl_get_settings() settings = self._option_bag.config_bag.context.cfgimpl_get_settings()
properties = settings.getproperties(self._option_bag,
apply_requires=False)
if not only_raises: if not only_raises:
return properties return settings.getproperties(self._option_bag,
apply_requires=False)
# do not check cache properties/permissives which are not save (unrestraint, ...) # do not check cache properties/permissives which are not save (unrestraint, ...)
return settings.calc_raises_properties(properties, return settings.calc_raises_properties(self._option_bag,
settings.get_context_properties(), apply_requires=False)
settings.get_context_properties())
def __call__(self, def __call__(self,
path: str, name: str,
index: Optional[int]=None) -> 'TiramisuOption': index: Optional[int]=None) -> 'TiramisuOption':
"""Select an option by path""" """Select an option by path"""
subpath = self._option_bag.option.impl_getname() + '.' + path path = self._option_bag.path + '.' + name
subconfig, name = self._subconfig.cfgimpl_get_home_by_path(subpath,
self._option_bag.config_bag)
path = self._option_bag.path + '.' + path
return TiramisuOption(name, return TiramisuOption(name,
path, path,
index, index,
subconfig, self._config,
self._option_bag.config_bag) self._option_bag.config_bag)
@ -288,18 +292,18 @@ class TiramisuOptionOption(CommonTiramisuOption):
def __new__(cls, def __new__(cls,
name, name,
subconfig, subconfig,
option_bag): option_bag,
option = subconfig.cfgimpl_get_description().get_child(name, config):
option_bag.config_bag, if option_bag.option.impl_is_optiondescription():
subconfig.cfgimpl_get_path())
if option.impl_is_optiondescription():
return _TiramisuOptionOptionDescription(name=name, return _TiramisuOptionOptionDescription(name=name,
subconfig=subconfig, subconfig=subconfig,
option_bag=option_bag) option_bag=option_bag,
config=config)
else: else:
return _TiramisuOptionOption(name=name, return _TiramisuOptionOption(name=name,
subconfig=subconfig, subconfig=subconfig,
option_bag=option_bag) option_bag=option_bag,
config=config)
class TiramisuOptionOwner(CommonTiramisuOption): class TiramisuOptionOwner(CommonTiramisuOption):
@ -309,7 +313,8 @@ class TiramisuOptionOwner(CommonTiramisuOption):
def __init__(self, def __init__(self,
name: str, name: str,
subconfig: Union[KernelConfig, SubConfig], subconfig: Union[KernelConfig, SubConfig],
option_bag: OptionBag) -> None: option_bag: OptionBag,
config: Optional['SubConfig']) -> None:
super().__init__(name, super().__init__(name,
subconfig, subconfig,
@ -348,7 +353,8 @@ class TiramisuOptionProperty(CommonTiramisuOption):
def __init__(self, def __init__(self,
name: str, name: str,
subconfig: Union[KernelConfig, SubConfig], subconfig: Union[KernelConfig, SubConfig],
option_bag: OptionBag) -> None: option_bag: OptionBag,
config: Optional['SubConfig']) -> None:
super().__init__(name, super().__init__(name,
subconfig, subconfig,
option_bag) option_bag)
@ -360,13 +366,10 @@ class TiramisuOptionProperty(CommonTiramisuOption):
"""Get properties for an option""" """Get properties for an option"""
option = self._option_bag.option option = self._option_bag.option
self._test_follower_index() self._test_follower_index()
properties = self._option_bag.properties
if not only_raises: if not only_raises:
return properties return self._option_bag.properties
# do not check cache properties/permissives which are not save (unrestraint, ...) # do not check cache properties/permissives which are not save (unrestraint, ...)
return self._settings.calc_raises_properties(properties, return self._settings.calc_raises_properties(self._option_bag)
self._settings.get_context_properties(),
self._settings.get_context_properties())
def add(self, prop): def add(self, prop):
"""Add new property for an option""" """Add new property for an option"""
@ -406,7 +409,8 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
def __init__(self, def __init__(self,
name: str, name: str,
subconfig: Union[KernelConfig, SubConfig], subconfig: Union[KernelConfig, SubConfig],
option_bag: OptionBag) -> None: option_bag: OptionBag,
config: Optional['SubConfig']) -> None:
super().__init__(name, super().__init__(name,
subconfig, subconfig,
option_bag) option_bag)
@ -554,6 +558,7 @@ class _TiramisuOptionValueChoiceOption:
class _TiramisuOptionValueOptionDescription: class _TiramisuOptionValueOptionDescription:
def dict(self, def dict(self,
flatten=False, flatten=False,
withvalue=undefined, withvalue=undefined,
@ -583,18 +588,15 @@ class TiramisuOptionValue(CommonTiramisuOption):
def __new__(cls, def __new__(cls,
name, name,
subconfig, subconfig,
option_bag): option_bag,
if subconfig is not None: config):
types = [CommonTiramisuOption]
if option_bag.option and option_bag.option.impl_is_optiondescription():
types.append(_TiramisuOptionValueOptionDescription)
elif subconfig is not None:
option = subconfig.cfgimpl_get_description().get_child(name, option = subconfig.cfgimpl_get_description().get_child(name,
option_bag.config_bag, option_bag.config_bag,
subconfig.cfgimpl_get_path()) subconfig.cfgimpl_get_path())
else:
option = None
types = [CommonTiramisuOption]
if option:
if option.impl_is_optiondescription():
types.append(_TiramisuOptionValueOptionDescription)
else:
types.append(_TiramisuOptionValueOption) types.append(_TiramisuOptionValueOption)
if isinstance(option, ChoiceOption): if isinstance(option, ChoiceOption):
types.append(_TiramisuOptionValueChoiceOption) types.append(_TiramisuOptionValueChoiceOption)
@ -606,6 +608,12 @@ class TiramisuOptionValue(CommonTiramisuOption):
types.append(_TiramisuOptionValueGroup) types.append(_TiramisuOptionValueGroup)
new_type_dict = {'_allow_optiondescription': cls._allow_optiondescription, new_type_dict = {'_allow_optiondescription': cls._allow_optiondescription,
'_follower_need_index': cls._follower_need_index} '_follower_need_index': cls._follower_need_index}
if option_bag.option and option_bag.option.impl_is_optiondescription():
new_type = type('TiramisuOptionValue', tuple(types), new_type_dict)(name=name,
subconfig=subconfig,
option_bag=option_bag,
config=config)
else:
new_type = type('TiramisuOptionValue', tuple(types), new_type_dict)(name=name, new_type = type('TiramisuOptionValue', tuple(types), new_type_dict)(name=name,
subconfig=subconfig, subconfig=subconfig,
option_bag=option_bag) option_bag=option_bag)
@ -642,14 +650,31 @@ class _TiramisuOption(CommonTiramisu):
self._option_bag.index = self._index self._option_bag.index = self._index
self._option_bag.config_bag = self._config_bag self._option_bag.config_bag = self._config_bag
self._tiramisu_dict = None self._tiramisu_dict = None
self._config = None
if not self._registers: if not self._registers:
_registers(self._registers, 'TiramisuOption') _registers(self._registers, 'TiramisuOption')
def _get_config(self):
if self._config is None and self._subconfig is not None:
self._config = self._subconfig.get_subconfig(self._option_bag)
return self._config
def __getattr__(self, subfunc: str) -> Any: def __getattr__(self, subfunc: str) -> Any:
if subfunc in self._registers: if subfunc in self._registers:
subconfig = self._subconfig
if subconfig:
option_bag = self._option_bag
option = self._get_option()
if option.impl_is_optiondescription() and subfunc == 'option':
config = self._get_config()
else:
config = None
else:
config = None
return self._registers[subfunc](self._name, return self._registers[subfunc](self._name,
self._subconfig, subconfig,
self._option_bag) self._option_bag,
config)
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) # pragma: no cover raise APIError(_('please specify a valid sub function ({})').format(subfunc)) # pragma: no cover
@ -1240,7 +1265,7 @@ class _TiramisuContextConfigReset():
"""Remove all datas to current config (informations, values, properties, ...)""" """Remove all datas to current config (informations, values, properties, ...)"""
# Option's values # Option's values
context_owner = self._config_bag.context.cfgimpl_get_values().get_context_owner() context_owner = self._config_bag.context.cfgimpl_get_values().get_context_owner()
self._config_bag.context.cfgimpl_get_values()._p_.importation((tuple(), tuple(), tuple(), tuple())) self._config_bag.context.cfgimpl_get_values()._p_.importation(([], [], [], []))
self._config_bag.context.cfgimpl_get_values()._p_.setvalue(None, self._config_bag.context.cfgimpl_get_values()._p_.setvalue(None,
None, None,
context_owner, context_owner,

View File

@ -254,18 +254,20 @@ def carry_out_calculation(option,
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \ if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
option.impl_is_follower(): option.impl_is_follower():
if args or kwargs: if args or kwargs:
raise LeadershipError(_('function "{}" with arguments "{}" and "{}" ' raise LeadershipError(_('the "{}" function with positional arguments "{}" '
'return the list "{}" for the follower option "{}"' 'and keyword arguments "{}" must not return '
'a list ("{}") for the follower option "{}"'
'').format(callback.__name__, '').format(callback.__name__,
args, args,
kwargs, kwargs,
ret, ret,
option.impl_get_display_name())) option.impl_get_display_name()))
else: else:
raise LeadershipError(_('function "{}" return the list "{}" for the follower option "{}"' raise LeadershipError(_('the "{}" function must not return a list ("{}") '
'for the follower option "{}"'
'').format(callback.__name__, '').format(callback.__name__,
ret, ret,
option.impl_getname())) option.impl_get_display_name()))
return ret return ret

View File

@ -281,7 +281,8 @@ class SubConfig(object):
def getattr(self, def getattr(self,
name, name,
option_bag): option_bag,
from_follower=False):
""" """
attribute notation mechanism for accessing the value of an option attribute notation mechanism for accessing the value of an option
:param name: attribute name :param name: attribute name
@ -310,14 +311,15 @@ class SubConfig(object):
return context.getattr(soption_bag.path, return context.getattr(soption_bag.path,
soption_bag) soption_bag)
if not from_follower or option_bag.option.impl_getrequires():
self.cfgimpl_get_settings().validate_properties(option_bag) self.cfgimpl_get_settings().validate_properties(option_bag)
if option.impl_is_follower(): if option.impl_is_follower() and not from_follower:
length = self.cfgimpl_get_length_leadership(option_bag) length = self.cfgimpl_get_length_leadership(option_bag)
follower_len = self.cfgimpl_get_values()._p_.get_max_length(option_bag.path) follower_len = self.cfgimpl_get_values()._p_.get_max_length(option_bag.path)
if follower_len > length: if follower_len > length:
raise LeadershipError(_('follower option "{}" has higher length "{}" than the leader ' raise LeadershipError(_('the follower option "{}" has greater length ({}) than the leader '
'length "{}"').format(option.impl_get_display_name(), 'length ({})').format(option.impl_get_display_name(),
follower_len, follower_len,
length, length,
option_bag.index)) option_bag.index))
@ -332,7 +334,8 @@ class SubConfig(object):
soption_bag.fromconsistency = option_bag.fromconsistency.copy() soption_bag.fromconsistency = option_bag.fromconsistency.copy()
try: try:
value.append(self.getattr(name, value.append(self.getattr(name,
soption_bag)) soption_bag,
from_follower=True))
except PropertiesOptionError as err: except PropertiesOptionError as err:
value.append(err) value.append(err)
else: else:

View File

@ -54,7 +54,7 @@ class BroadcastOption(Option):
warnings_only, warnings_only,
context): context):
if len(vals) != 3: if len(vals) != 3:
raise ConfigError(_('invalid len for vals')) raise ConfigError(_('invalid broadcast consistency, a network and a netmask are needed'))
if None in vals: if None in vals:
return return
broadcast, network, netmask = vals broadcast, network, netmask = vals

View File

@ -121,6 +121,7 @@ class OptionBag:
'config_bag', 'config_bag',
'ori_option', # original option (for example useful for symlinkoption) 'ori_option', # original option (for example useful for symlinkoption)
'properties', # properties of current option 'properties', # properties of current option
'properties_setted',
'apply_requires', # apply requires or not for this option 'apply_requires', # apply requires or not for this option
'fromconsistency' # history for consistency 'fromconsistency' # history for consistency
) )
@ -151,8 +152,15 @@ class OptionBag:
return self.option return self.option
elif key == 'apply_requires': elif key == 'apply_requires':
return True return True
elif key == 'properties_setted':
return False
raise KeyError('unknown key {} for OptionBag'.format(key)) # pragma: no cover raise KeyError('unknown key {} for OptionBag'.format(key)) # pragma: no cover
def __setattr__(self, key, val):
super().__setattr__(key, val)
if key == 'properties':
self.properties_setted = True
def __delattr__(self, key): def __delattr__(self, key):
if key in ['properties', 'permissives']: if key in ['properties', 'permissives']:
try: try:
@ -379,7 +387,7 @@ class Settings(object):
# get properties and permissive methods # get properties and permissive methods
def get_context_properties(self): def get_context_properties(self):
is_cached, props = self._p_.getcache(None, is_cached, props, validated = self._p_.getcache(None,
None, None,
None, None,
{}, {},
@ -392,7 +400,8 @@ class Settings(object):
None, None,
props, props,
{}, {},
props) props,
True)
return props return props
def getproperties(self, def getproperties(self,
@ -410,7 +419,7 @@ class Settings(object):
if apply_requires: if apply_requires:
props = config_bag.properties props = config_bag.properties
is_cached, props = self._p_.getcache(path, is_cached, props, validated = self._p_.getcache(path,
config_bag.expiration_time, config_bag.expiration_time,
index, index,
props, props,
@ -431,7 +440,8 @@ class Settings(object):
index, index,
props, props,
props, props,
config_bag.properties) config_bag.properties,
True)
return props return props
def get_context_permissives(self): def get_context_permissives(self):
@ -744,13 +754,18 @@ class Settings(object):
#____________________________________________________________ #____________________________________________________________
# validate properties # validate properties
def calc_raises_properties(self, def calc_raises_properties(self,
option_properties, option_bag,
config_properties, apply_requires=True):
config_permissives): raises_properties = option_bag.config_bag.properties - SPECIAL_PROPERTIES
properties = option_properties & config_properties - SPECIAL_PROPERTIES
# remove global permissive properties # remove global permissive properties
if properties and ('permissive' in config_properties): if raises_properties and ('permissive' in raises_properties):
properties -= config_permissives raises_properties -= option_bag.config_bag.permissives
if apply_requires and option_bag.properties_setted:
option_properties = option_bag.properties
else:
option_properties = self.getproperties(option_bag,
apply_requires=apply_requires)
properties = option_properties & raises_properties
# at this point an option should not remain in properties # at this point an option should not remain in properties
return properties return properties
@ -764,11 +779,9 @@ class Settings(object):
was present was present
""" """
config_bag = option_bag.config_bag config_bag = option_bag.config_bag
if not config_bag.properties: # pragma: no cover if not config_bag.properties or config_bag.properties == frozenset(['cache']): # pragma: no cover
return return
properties = self.calc_raises_properties(option_bag.properties, properties = self.calc_raises_properties(option_bag)
config_bag.properties,
config_bag.permissives)
if properties != frozenset(): if properties != frozenset():
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(option_bag,
properties, properties,

View File

@ -22,8 +22,8 @@ class Cache(object):
def __init__(self): def __init__(self):
self._cache = {} self._cache = {}
def _setcache(self, path, index, val, time): def _setcache(self, path, index, val, time, validated):
self._cache.setdefault(path, {})[index] = (val, int(time)) self._cache.setdefault(path, {})[index] = (val, int(time), validated)
def _getcache(self, path, index): def _getcache(self, path, index):
values = self._cache.get(path) values = self._cache.get(path)

View File

@ -20,6 +20,8 @@ from ...setting import undefined
from ...i18n import _ from ...i18n import _
from ...log import log from ...log import log
from copy import deepcopy
class Values(Cache): class Values(Cache):
__slots__ = ('_values', __slots__ = ('_values',
@ -30,7 +32,7 @@ class Values(Cache):
"""init plugin means create values storage """init plugin means create values storage
""" """
#(('path1',), (index1,), (value1,), ('owner1')) #(('path1',), (index1,), (value1,), ('owner1'))
self._values = (tuple(), tuple(), tuple(), tuple()) self._values = ([], [], [], [])
self._informations = {} self._informations = {}
# should init cache too # should init cache too
super(Values, self).__init__(storage) super(Values, self).__init__(storage)
@ -38,33 +40,30 @@ class Values(Cache):
def commit(self): def commit(self):
pass pass
def _setvalue_info(self, nb, idx, value, values, index, vidx): def _setvalue_info(self, nb, idx, value, index, follower_idx=None):
lst = list(self._values[nb]) lst = self._values[nb]
if idx is None:
if index is None or nb == 0:
lst.append(value)
else:
lst.append((value,))
else:
if index is None or nb == 0: if index is None or nb == 0:
# not follower or path
lst[idx] = value lst[idx] = value
else: else:
if nb == 1: # follower
if index in lst[idx]: if nb == 1 and index in lst[idx]:
vidx = lst[idx].index(index) follower_idx = lst[idx].index(index)
else:
vidx = None
if vidx is None:
tval = list(lst[idx]) tval = list(lst[idx])
if follower_idx is None:
tval.append(value) tval.append(value)
lst[idx] = tuple(tval) else:
elif nb != 1: tval[follower_idx] = value
tval = list(lst[idx]) lst[idx] = tval
tval[vidx] = value return follower_idx
lst[idx] = tuple(tval)
lst[idx] = tuple(lst[idx]) def _add_new_value(self, index, nb, value):
values.append(tuple(lst)) if index is None or nb == 0:
return vidx # not follower or path
self._values[nb].append(value)
else:
# follower
self._values[nb].append([value])
# value # value
def setvalue(self, def setvalue(self,
@ -77,20 +76,20 @@ class Values(Cache):
a specified value must be associated to an owner a specified value must be associated to an owner
""" """
log.debug('setvalue %s %s %s %s %s', path, value, owner, index, id(self)) log.debug('setvalue %s %s %s %s %s', path, value, owner, index, id(self))
values = []
vidx = None
#if isinstance(value, list):
# value = value
if path in self._values[0]: if path in self._values[0]:
idx = self._values[0].index(path) idx = self._values[0].index(path)
self._setvalue_info(0, idx, path, index)
follower_idx = self._setvalue_info(1, idx, index, index)
self._setvalue_info(2, idx, value, index, follower_idx)
self._setvalue_info(3, idx, owner, index, follower_idx)
else: else:
idx = None self._add_new_value(index, 0, path)
vidx = self._setvalue_info(0, idx, path, values, index, vidx) self._add_new_value(index, 1, index)
vidx = self._setvalue_info(1, idx, index, values, index, vidx) self._add_new_value(index, 2, value)
if isinstance(value, list): self._add_new_value(index, 3, owner)
value = tuple(value)
vidx = self._setvalue_info(2, idx, value, values, index, vidx)
self._setvalue_info(3, idx, owner, values, index, vidx)
self._values = tuple(values)
def hasvalue(self, path, index=None): def hasvalue(self, path, index=None):
"""if path has a value """if path has a value
@ -114,16 +113,8 @@ class Values(Cache):
path_idx = self._values[0].index(path) path_idx = self._values[0].index(path)
# get the "index" position # get the "index" position
subidx = self._values[1][path_idx].index(index) subidx = self._values[1][path_idx].index(index)
# transform tuple to list
values = list(self._values)
values_idx = list(values[1])
lvalues = list(values_idx[path_idx])
# reduce to one the index # reduce to one the index
lvalues[subidx] = lvalues[subidx] - 1 self._values[1][path_idx][subidx] -= 1
# store modification
values_idx[path_idx] = tuple(lvalues)
values[1] = tuple(values_idx)
self._values = tuple(values)
def resetvalue_index(self, def resetvalue_index(self,
path, path,
@ -131,23 +122,16 @@ class Values(Cache):
commit): commit):
log.debug('resetvalue_index %s %s %s', path, index, id(self)) log.debug('resetvalue_index %s %s %s', path, index, id(self))
def _resetvalue(nb): def _resetvalue(nb):
values_idx = list(values[nb]) del self._values[nb][path_idx]
del(values_idx[path_idx])
values[nb] = tuple(values_idx)
def _resetvalue_index(nb): def _resetvalue_index(nb):
values_idx = list(values[nb]) del self._values[nb][path_idx][subidx]
lvalues = list(values_idx[path_idx])
del(lvalues[subidx])
values_idx[path_idx] = tuple(lvalues)
values[nb] = tuple(values_idx)
path_idx = self._values[0].index(path) path_idx = self._values[0].index(path)
indexes = self._values[1][path_idx] indexes = self._values[1][path_idx]
if index in indexes: if index in indexes:
subidx = indexes.index(index) subidx = indexes.index(index)
values = list(self._values) if len(self._values[1][path_idx]) == 1:
if len(values[1][path_idx]) == 1:
_resetvalue(0) _resetvalue(0)
_resetvalue(1) _resetvalue(1)
_resetvalue(2) _resetvalue(2)
@ -156,7 +140,6 @@ class Values(Cache):
_resetvalue_index(1) _resetvalue_index(1)
_resetvalue_index(2) _resetvalue_index(2)
_resetvalue_index(3) _resetvalue_index(3)
self._values = tuple(values)
def resetvalue(self, def resetvalue(self,
path, path,
@ -165,17 +148,13 @@ class Values(Cache):
""" """
log.debug('resetvalue %s %s', path, id(self)) log.debug('resetvalue %s %s', path, id(self))
def _resetvalue(nb): def _resetvalue(nb):
lst = list(self._values[nb]) self._values[nb].pop(idx)
lst.pop(idx)
values.append(tuple(lst))
values = []
if path in self._values[0]: if path in self._values[0]:
idx = self._values[0].index(path) idx = self._values[0].index(path)
_resetvalue(0) _resetvalue(0)
_resetvalue(1) _resetvalue(1)
_resetvalue(2) _resetvalue(2)
_resetvalue(3) _resetvalue(3)
self._values = tuple(values)
# owner # owner
def setowner(self, def setowner(self,
@ -186,14 +165,10 @@ class Values(Cache):
""" """
idx = self._values[0].index(path) idx = self._values[0].index(path)
if index is None: if index is None:
vidx = None follower_idx = None
else: else:
vidx = self._values[1][idx].index(index) follower_idx = self._values[1][idx].index(index)
values = [] self._setvalue_info(3, idx, owner, index, follower_idx)
self._setvalue_info(3, idx, owner, values, index, vidx)
lst = list(self._values)
lst[3] = tuple(values[0])
self._values = tuple(lst)
def get_max_length(self, def get_max_length(self,
path): path):
@ -293,10 +268,10 @@ class Values(Cache):
self._informations = {} self._informations = {}
def exportation(self): def exportation(self):
return self._values return deepcopy(self._values)
def importation(self, export): def importation(self, export):
self._values = export self._values = deepcopy(export)
def delete_session(session_id): def delete_session(session_id):

View File

@ -31,22 +31,16 @@ class Cache(DictCache):
self._storage = storage self._storage = storage
super().__init__() super().__init__()
def setcache(self, path, index, val, self_props, props): def setcache(self, path, index, val, self_props, props, validated):
"""add val in cache for a specified path """add val in cache for a specified path
if follower, add index if follower, add index
""" """
if 'cache' in props or 'cache' in self_props: if 'cache' in props or 'cache' in self_props:
log.debug('setcache {} with index {} and value {} in {} ({})'.format(path, index, val, log.debug('setcache %s with index %s and value %s in %s (%s)',
_display_classname(self), path, index, val, _display_classname(self), id(self))
id(self))) self._setcache(path, index, val, time(), validated)
self._setcache(path, index, val, time()) log.debug('not setcache %s with index %s and value %s and props %s and %s in %s (%s)',
log.debug('not setcache {} with index {} and value {} and props {} and {} in {} ({})'.format(path, path, index, val, props, self_props, _display_classname(self), id(self))
index,
val,
props,
self_props,
_display_classname(self),
id(self)))
def getcache(self, def getcache(self,
path, path,
@ -55,12 +49,12 @@ class Cache(DictCache):
props, props,
self_props, self_props,
type_): type_):
no_cache = False, None no_cache = False, None, False
if 'cache' in props or type_ == 'context_props': if 'cache' in props or type_ == 'context_props':
indexed = self._getcache(path, index) indexed = self._getcache(path, index)
if indexed is None: if indexed is None:
return no_cache return no_cache
value, timestamp = indexed value, timestamp, validated = indexed
if type_ == 'context_props': if type_ == 'context_props':
# cached value is settings properties so value is props # cached value is settings properties so value is props
props = value props = value
@ -77,18 +71,18 @@ class Cache(DictCache):
if timestamp + expiration_time >= ntime: if timestamp + expiration_time >= ntime:
log.debug('getcache in cache (1) %s %s %s %s %s', path, value, _display_classname(self), log.debug('getcache in cache (1) %s %s %s %s %s', path, value, _display_classname(self),
id(self), index) id(self), index)
return True, value return True, value, validated
#else: else:
# log.debug('getcache expired value for path {} < {}'.format( log.debug('getcache expired value for path %s < %s',
# timestamp + expiration_time, ntime)) timestamp + expiration_time, ntime)
# # if expired, remove from cache # if expired, remove from cache
# #self.delcache(path) # self.delcache(path)
else: else:
log.debug('getcache in cache (2) %s %s %s %s %s', path, value, _display_classname(self), log.debug('getcache in cache (2) %s %s %s %s %s', path, value, _display_classname(self),
id(self), index) id(self), index)
return True, value return True, value, validated
log.debug('getcache {} with index {} not in {} cache'.format(path, index, log.debug('getcache %s with index %s not in %s cache',
_display_classname(self))) path, index, _display_classname(self))
return no_cache return no_cache
def delcache(self, path): def delcache(self, path):
@ -108,5 +102,5 @@ class Cache(DictCache):
please only use it in test purpose please only use it in test purpose
example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}} example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}}
""" """
log.debug('get_chached {} for {} ({})'.format(self._cache, _display_classname(self), id(self))) log.debug('get_chached %s for %s (%s)', self._cache, _display_classname(self), id(self))
return self._get_cached() return self._get_cached()

View File

@ -62,32 +62,32 @@ class Values(object):
""" """
# try to retrive value in cache # try to retrive value in cache
setting_properties = option_bag.config_bag.properties setting_properties = option_bag.config_bag.properties
is_cached, value = self._p_.getcache(option_bag.path, is_cached, value, validated = self._p_.getcache(option_bag.path,
option_bag.config_bag.expiration_time, option_bag.config_bag.expiration_time,
option_bag.index, option_bag.index,
setting_properties, setting_properties,
option_bag.properties, option_bag.properties,
'value') 'value')
if not validated:
if not is_cached:
# no cached value so get value # no cached value so get value
value = self.getvalue(option_bag) value = self.getvalue(option_bag)
# validate value # validate value
opt = option_bag.option option_bag.option.impl_validate(value,
opt.impl_validate(value,
option_bag, option_bag,
check_error=True) check_error=True)
if 'warnings' in setting_properties:
opt.impl_validate(value,
option_bag,
check_error=False)
# store value in cache # store value in cache
if not is_cached: validator = 'validator' in option_bag.config_bag.properties
if not is_cached or validator:
self._p_.setcache(option_bag.path, self._p_.setcache(option_bag.path,
option_bag.index, option_bag.index,
value, value,
option_bag.properties, option_bag.properties,
setting_properties) setting_properties,
validator)
if 'warnings' in setting_properties:
option_bag.option.impl_validate(value,
option_bag,
check_error=False)
if isinstance(value, list): if isinstance(value, list):
# return a copy, so value cannot be modified # return a copy, so value cannot be modified
return value.copy() return value.copy()
@ -174,7 +174,7 @@ class Values(object):
def _reset_cache(_value): def _reset_cache(_value):
if not 'expire' in option_bag.properties: if not 'expire' in option_bag.properties:
return return
is_cache, cache_value = self._p_.getcache(option_bag.path, is_cache, cache_value, validated = self._p_.getcache(option_bag.path,
None, None,
option_bag.index, option_bag.index,
option_bag.config_bag.properties, option_bag.config_bag.properties,
@ -508,7 +508,7 @@ class Values(object):
current_value = self.get_cached_value(option_bag) current_value = self.get_cached_value(option_bag)
length = len(current_value) length = len(current_value)
if index >= length: if index >= length:
raise IndexError(_('index "{}" is higher than the length "{}" ' raise IndexError(_('index {} is greater than the length {} '
'for option "{}"').format(index, 'for option "{}"').format(index,
length, length,
option_bag.option.impl_get_display_name())) option_bag.option.impl_get_display_name()))