better cache

This commit is contained in:
Emmanuel Garette 2017-07-08 15:59:56 +02:00
parent 6bad3c6e64
commit dadf859905
21 changed files with 476 additions and 109 deletions

View file

@ -1,3 +1,7 @@
Sat Jul 8 15:57:13 2017 +0200 Emmanuel Garette <egarette@cadoles.com>
* better cache, only remove value/property from cache for value
modified and for all value affected by this modification
Sat May 20 16:27:09 2017 +0200 Emmanuel Garette <egarette@cadoles.com> Sat May 20 16:27:09 2017 +0200 Emmanuel Garette <egarette@cadoles.com>
* add 'operator' to requirement * add 'operator' to requirement

View file

@ -5,7 +5,7 @@ do_autopath()
from tiramisu import setting, value from tiramisu import setting, value
setting.expires_time = 1 setting.expires_time = 1
value.expires_time = 1 value.expires_time = 1
from tiramisu.option import IntOption, StrOption, OptionDescription from tiramisu.option import BoolOption, IPOption, IntOption, StrOption, OptionDescription
from tiramisu.config import Config from tiramisu.config import Config
from tiramisu.error import ConfigError from tiramisu.error import ConfigError
from tiramisu.setting import groups from tiramisu.setting import groups
@ -77,31 +77,42 @@ def test_cache_reset():
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
#when change a value #when change a value
c.u1 c.u1
c.u2
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u2' in values._p_.get_cached(c)
assert 'u2' in settings._p_.get_cached(c)
c.u2 = 1 c.u2 = 1
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u2' not in values._p_.get_cached(c)
assert 'u2' not in settings._p_.get_cached(c)
#when remove a value #when remove a value
c.u1 c.u1
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
del(c.u2) del(c.u2)
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u2' not in values._p_.get_cached(c)
assert 'u2' not in settings._p_.get_cached(c)
#when add/del property #when add/del property
c.u1 c.u1
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
c.cfgimpl_get_settings()[od1.u2].append('test') c.cfgimpl_get_settings()[od1.u2].append('test')
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u2' not in values._p_.get_cached(c)
assert 'u2' not in settings._p_.get_cached(c)
c.u1 c.u1
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
c.cfgimpl_get_settings()[od1.u2].remove('test') c.cfgimpl_get_settings()[od1.u2].remove('test')
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u2' not in values._p_.get_cached(c)
assert 'u2' not in settings._p_.get_cached(c)
#when enable/disabled property #when enable/disabled property
c.u1 c.u1
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
@ -122,34 +133,51 @@ def test_cache_reset_multi():
c = Config(od1) c = Config(od1)
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
#when change a value
c.u1 c.u1
c.u3
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' in values._p_.get_cached(c)
assert 'u3' in settings._p_.get_cached(c)
#when change a value
c.u3 = [1] c.u3 = [1]
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' not in values._p_.get_cached(c)
assert 'u3' not in settings._p_.get_cached(c)
#when append value #when append value
c.u1 c.u1
c.u3
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' in values._p_.get_cached(c)
assert 'u3' in settings._p_.get_cached(c)
c.u3.append(1) c.u3.append(1)
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' not in values._p_.get_cached(c)
assert 'u3' not in settings._p_.get_cached(c)
#when pop value #when pop value
c.u1 c.u1
c.u3
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' in values._p_.get_cached(c)
assert 'u3' in settings._p_.get_cached(c)
c.u3.pop(1) c.u3.pop(1)
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' not in values._p_.get_cached(c)
assert 'u3' not in settings._p_.get_cached(c)
#when remove a value #when remove a value
c.u1 c.u1
assert 'u1' in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
del(c.u3) del(c.u3)
assert 'u1' not in values._p_.get_cached(c) assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c)
assert 'u3' not in values._p_.get_cached(c)
assert 'u3' not in settings._p_.get_cached(c)
def test_reset_cache(): def test_reset_cache():
@ -348,3 +376,210 @@ def test_cache_master_slave():
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None]) assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1]) assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1])
#DEL, insert, ... #DEL, insert, ...
def return_value(value=None):
return value
def test_cache_callback():
val1 = StrOption('val1', "", 'val')
val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)}, properties=('mandatory',))
val3 = StrOption('val3', "", callback=return_value, callback_params={'': ('yes',)})
val4 = StrOption('val4', "", callback=return_value, callback_params={'value': ((val1, False),)})
val5 = StrOption('val5', "", callback=return_value, callback_params={'value': ('yes',)}, multi=True)
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5])
cfg = Config(maconfig)
cfg.cfgimpl_get_settings().remove('expire')
cfg.read_write()
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val4': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('val', None)},
'val2': {None: ('val', None)},
'val3': {None: ('yes', None)},
'val4': {None: ('val', None)},
'val5': {None: (['yes'], None)}}
cfg.val1 = 'new'
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val3': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val3': {None: ('yes', None)},
'val5': {None: (['yes'], None)}}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val4': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('yes', None)},
'val4': {None: ('new', None)},
'val5': {None: (['yes'], None)}}
cfg.val3 = 'new2'
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val4': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val4': {None: ('new', None)},
'val5': {None: (['yes'], None)}}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val4': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
'val4': {None: ('new', None)},
'val5': {None: (['yes'], None)}}
cfg.val4 = 'new3'
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
'val5': {None: (['yes'], None)}}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val4': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)},
'val5': {None: (['yes'], None)}}
cfg.val5.append('new4')
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val4': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)}}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val2': {None: (set(['mandatory']), None)},
'val3': {None: (set([]), None)},
'val4': {None: (set([]), None)},
'val5': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)},
'val5': {None: (['yes', 'new4'], None)}}
def test_cache_master_and_slaves_master():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.cfgimpl_get_settings().remove('expire')
cfg.read_write()
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val1.val1': {None: (set(['empty']), None)},
'val1.val2': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}}
cfg.val1.val1.append()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val1.val1': {None: (set(['empty']), None)},
'val1.val2': {None: (set([]), None), 0: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None], None)},
'val1.val2': {None: ([None], None), 0: (None, None)}}
cfg.val1.val1.append()
cfg.cfgimpl_get_values().force_cache()
cfg.val1.val2[1] = 'oui'
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val1.val1': {None: (set(['empty']), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None, None], None)}}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val1.val1': {None: (set(['empty']), None)},
'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)},
'val1.val2': {None: ([None, 'oui'], None), 0: (None, None), 1: ('oui', None)}}
def test_cache_master_callback():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'value': ((val1, False),)})
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.cfgimpl_get_settings().remove('expire')
cfg.read_write()
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val1.val1': {None: (set(['empty']), None)},
'val1.val2': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}}
cfg.val1.val1.append()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
cfg.cfgimpl_get_values().force_cache()
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)},
'val1.val1': {None: (set(['empty']), None)},
'val1.val2': {None: (set([]), None), 0: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None], None)},
'val1.val2': {None: ([None], None), 0: (None, None)}}
def test_cache_requires():
a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
od = OptionDescription('service', '', [a, b])
c = Config(od)
c.cfgimpl_get_settings().remove('expire')
c.read_write()
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {}
assert c.ip_address_service == None
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'ip_address_service': {None: (None, None)}}
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}}
c.ip_address_service = '1.1.1.1'
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)}}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'activate_service': {None: (True, None)}}
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'ip_address_service': {None: ('1.1.1.1', None)},
'activate_service': {None: (True, None)}}
c.activate_service = False
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {}
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set(['disabled']), None)}}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'activate_service': {None: (False, None)}}

View file

@ -3,7 +3,7 @@ do_autopath()
from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \ from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \
IntOption, IPOption, NetmaskOption, StrOption, OptionDescription, \ IntOption, IPOption, NetmaskOption, StrOption, OptionDescription, \
DynOptionDescription DynOptionDescription, MasterSlaves
from tiramisu.config import Config, GroupConfig, MetaConfig from tiramisu.config import Config, GroupConfig, MetaConfig
from tiramisu.setting import groups, owners from tiramisu.setting import groups, owners
from tiramisu.storage import delete_session from tiramisu.storage import delete_session
@ -118,8 +118,15 @@ def _diff_opt(opt1, opt2):
assert val1.impl_getname() == val2.impl_getname() assert val1.impl_getname() == val2.impl_getname()
except AttributeError: except AttributeError:
assert val1 == val2 assert val1 == val2
elif attr == '_dependencies':
assert len(val1) == len(val2)
for idx, val in enumerate(val1):
if isinstance(val, MasterSlaves):
assert val._p_.master.impl_getname() == val2[idx]._p_.master.impl_getname()
else:
assert val.impl_getname() == val2[idx].impl_getname()
else: else:
assert val1 == val2 assert val1 == val2, "error for {}".format(attr)
def _diff_opts(opt1, opt2): def _diff_opts(opt1, opt2):

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -21,6 +21,7 @@
"options handler global entry point" "options handler global entry point"
import weakref import weakref
import sys import sys
from time import time
from .error import PropertiesOptionError, ConfigError, ConflictError from .error import PropertiesOptionError, ConfigError, ConflictError
@ -70,10 +71,78 @@ class SubConfig(object):
self._impl_context = context self._impl_context = context
self._impl_path = subpath self._impl_path = subpath
def cfgimpl_reset_cache(self, only_expired=False, only=('values', def cfgimpl_reset_cache(self,
'settings')): only_expired=False,
"remove cache (in context)" only=('values', 'settings'),
self._cfgimpl_get_context().cfgimpl_reset_cache(only_expired, only) # pragma: optional cover opt=None,
path=None):
"""reset all settings in cache
:param only_expired: if True reset only expired cached values
:type only_expired: boolean
"""
context = self._cfgimpl_get_context()
if 'values' in only:
values = context.cfgimpl_get_values()
if 'settings' in only:
settings = context.cfgimpl_get_settings()
if only_expired:
if 'values' in only:
values._p_.reset_expired_cache(int(time()))
if 'settings' in only:
settings._p_.reset_expired_cache(int(time()))
elif not None in (opt, path):
if opt.__class__.__name__ == 'DynOptionDescription':
descr = context.cfgimpl_get_description()
spath = path.split('.')
subpath = '.'.join(spath[:-1])
dynopt = getattr(descr, subpath)._getattr(spath[-1], context=context,
dyn=False)
for suffix in dynopt._impl_get_suffixes(context):
path = subpath + '.' + spath[-1] + suffix
if 'values' in only:
values._p_.delcache(path)
if 'settings' in only:
settings._p_.delcache(path)
elif not isinstance(opt, DynSymLinkOption) and opt._is_subdyn():
descr = context.cfgimpl_get_description()
spath = path.split('.')
try:
subpath = '.'.join(spath[:-2])
dynsubopt = getattr(descr, subpath)
spath1 = spath[-2]
spath2 = spath[-1]
spath3 = None
except AttributeError:
subpath = '.'.join(spath[:-3])
dynsubopt = getattr(descr, subpath)
spath1 = spath[-3]
spath2 = spath[-2]
spath3 = spath[-1]
dynopt = dynsubopt._getattr(spath1, context=context, dyn=False)
for suffix in dynopt._impl_get_suffixes(context):
path = subpath + '.' + spath1 + suffix + '.' + spath2 + suffix
if spath3:
path += '.' + spath3 + suffix
if 'values' in only:
values._p_.delcache(path)
if 'settings' in only:
settings._p_.delcache(path)
else:
if 'values' in only:
values._p_.delcache(path)
if 'settings' in only:
settings._p_.delcache(path)
for option in getattr(opt, '_dependencies', []):
if 'values' in only:
option.reset_cache(opt, values, 'values')
if 'settings' in only:
option.reset_cache(opt, settings, 'settings')
else:
if 'values' in only:
values._p_.reset_all_cache()
if 'settings' in only:
settings._p_.reset_all_cache()
def cfgimpl_get_home_by_path(self, path, force_permissive=False, def cfgimpl_get_home_by_path(self, path, force_permissive=False,
returns_raise=False): returns_raise=False):
@ -678,7 +747,7 @@ class Config(_CommonConfig):
def __init__(self, descr, session_id=None, persistent=False, def __init__(self, descr, session_id=None, persistent=False,
name=undefined, force_values=None, force_settings=None, name=undefined, force_values=None, force_settings=None,
_duplicate=False): _duplicate=False, mandatory_name=False):
""" Configuration option management master class """ Configuration option management master class
:param descr: describes the configuration schema :param descr: describes the configuration schema
@ -700,6 +769,8 @@ class Config(_CommonConfig):
name = 'config' name = 'config'
if session_id is not None: if session_id is not None:
name += session_id name += session_id
if mandatory_name and name is None:
raise ValueError(_("name is mandatory for the config").format(name))
if name is not None and not valid_name(name): # pragma: optional cover if name is not None and not valid_name(name): # pragma: optional cover
raise ValueError(_("invalid name: {0} for config").format(name)) raise ValueError(_("invalid name: {0} for config").format(name))
self._impl_settings = Settings(self, settings) self._impl_settings = Settings(self, settings)
@ -712,14 +783,6 @@ class Config(_CommonConfig):
self._impl_build_all_caches() self._impl_build_all_caches()
self._impl_name = name self._impl_name = name
def cfgimpl_reset_cache(self,
only_expired=False,
only=('values', 'settings')):
if 'values' in only:
self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
if 'settings' in only:
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
def impl_getname(self): def impl_getname(self):
return self._impl_name return self._impl_name
@ -763,19 +826,15 @@ class GroupConfig(_CommonConfig):
def cfgimpl_get_children(self): def cfgimpl_get_children(self):
return self._impl_children return self._impl_children
#def cfgimpl_get_context(self):
# "a meta config is a config which has a setting, that is itself"
# return self
def cfgimpl_reset_cache(self, def cfgimpl_reset_cache(self,
only_expired=False, only_expired=False,
only=('values', 'settings')): only=('values', 'settings'),
if 'values' in only: opt=None,
self.cfgimpl_get_values().reset_cache(only_expired=only_expired) path=None):
if 'settings' in only: if isinstance(self, MetaConfig):
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired) super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired, only=only, opt=opt, path=path)
for child in self._impl_children: for child in self._impl_children:
child.cfgimpl_reset_cache(only_expired=only_expired, only=only) child.cfgimpl_reset_cache(only_expired=only_expired, only=only, opt=opt, path=path)
def set_value(self, path, value): def set_value(self, path, value):
"""Setattr not in current GroupConfig, but in each children """Setattr not in current GroupConfig, but in each children
@ -906,3 +965,7 @@ class MetaConfig(GroupConfig):
setattr(child, path, child_value) setattr(child, path, child_value)
setattr(self, path, value) setattr(self, path, value)
def new_config(self, session_id=None, name=undefined):
return Config(self._impl_descr, _duplicate=True, session_id=session_id, name=name,
mandatory_name=True)

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,5 +1,5 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2014 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2014-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -25,7 +25,7 @@ import sys
from inspect import getargspec from inspect import getargspec
from ..i18n import _ from ..i18n import _
from ..setting import log, undefined, debug from ..setting import log, undefined, debug, groups
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)
@ -58,7 +58,7 @@ def valid_name(name):
return False return False
def validate_callback(callback, callback_params, type_): def validate_callback(callback, callback_params, type_, callbackoption):
if not isinstance(callback, FunctionType): if not isinstance(callback, FunctionType):
raise ValueError(_('{0} must be a function').format(type_)) raise ValueError(_('{0} must be a function').format(type_))
if callback_params is not None: if callback_params is not None:
@ -94,6 +94,17 @@ def validate_callback(callback, callback_params, type_):
' not a {} for second argument' ' not a {} for second argument'
).format(type_, type( ).format(type_, type(
force_permissive))) force_permissive)))
if isinstance(option, SymLinkOption):
cur_opt = option._impl_getopt()
else:
cur_opt = option
if cur_opt != callbackoption:
if not getattr(cur_opt, '_dependencies', None):
options = []
else:
options = list(cur_opt._dependencies)
options.append(callbackoption)
cur_opt._dependencies = tuple(options)
#____________________________________________________________ #____________________________________________________________
# #
@ -127,7 +138,7 @@ class Base(StorageBase):
if not is_multi and unique is True: if not is_multi and unique is True:
raise ValueError(_('unique must be set only with multi value')) raise ValueError(_('unique must be set only with multi value'))
if requires is not None: if requires is not None:
calc_properties, requires = validate_requires_arg(is_multi, calc_properties, requires = validate_requires_arg(self, is_multi,
requires, name) requires, name)
else: else:
calc_properties = frozenset() calc_properties = frozenset()
@ -143,7 +154,7 @@ class Base(StorageBase):
if multi: # and validator_params is None: if multi: # and validator_params is None:
validator_params = self._build_validator_params(validator, validator_params) validator_params = self._build_validator_params(validator, validator_params)
validate_callback(validator, validator_params, 'validator') validate_callback(validator, validator_params, 'validator', self)
self._set_validator(validator, validator_params) self._set_validator(validator, validator_params)
self._set_has_dependency() self._set_has_dependency()
if calc_properties != frozenset([]) and properties is not tuple(): if calc_properties != frozenset([]) and properties is not tuple():
@ -217,7 +228,7 @@ class Base(StorageBase):
"cannot set another one's").format(self.impl_getname())) "cannot set another one's").format(self.impl_getname()))
self._validate_callback(callback, callback_params) self._validate_callback(callback, callback_params)
if callback is not None: if callback is not None:
validate_callback(callback, callback_params, 'callback') validate_callback(callback, callback_params, 'callback', self)
self._set_callback(callback, callback_params) self._set_callback(callback, callback_params)
def impl_is_optiondescription(self): def impl_is_optiondescription(self):
@ -239,6 +250,36 @@ class BaseOption(Base):
# ____________________________________________________________ # ____________________________________________________________
# serialize object # serialize object
def _impl_convert_dependencies(self, descr, load=False):
"""export of the requires during the serialization process
:type descr: :class:`tiramisu.option.OptionDescription`
:param load: `True` if we are at the init of the option description
:type load: bool
"""
if not load and getattr(self, '_dependencies', None) is None:
self._state_dependencies = None
elif load and self._state_dependencies is None:
del(self._state_dependencies)
else:
if load:
self._dependencies = []
for dependency in self._state_dependencies:
option = descr.impl_get_opt_by_path(dependency)
if option.impl_is_optiondescription() and \
option.impl_get_group_type() == groups.master:
master_path = dependency + '.' + dependency.split('.')[-1]
option = descr.impl_get_opt_by_path(master_path).impl_get_master_slaves()
self._dependencies.append(option)
del(self._state_dependencies)
else:
self._state_dependencies = []
for dependency in self._dependencies:
if isinstance(dependency, MasterSlaves):
self._state_dependencies.append('.'.join(descr.impl_get_path_by_opt(dependency._p_.master).split('.')[:-1]))
else:
self._state_dependencies.append(descr.impl_get_path_by_opt(dependency))
def _impl_convert_requires(self, descr, load=False): def _impl_convert_requires(self, descr, load=False):
"""export of the requires during the serialization process """export of the requires during the serialization process
@ -417,6 +458,14 @@ class BaseOption(Base):
name = name.encode('utf8') name = name.encode('utf8')
return name return name
def reset_cache(self, opt, obj, type_):
context = obj._getcontext()
path = self.impl_getpath(context)
obj._p_.delcache(path)
context.cfgimpl_reset_cache(only=(type_,),
opt=self,
path=path)
class OnlyOption(BaseOption): class OnlyOption(BaseOption):
__slots__ = tuple() __slots__ = tuple()
@ -927,7 +976,7 @@ class Option(OnlyOption):
"is calculated").format(self.impl_getname())) "is calculated").format(self.impl_getname()))
def validate_requires_arg(multi, requires, name): def validate_requires_arg(new_option, multi, requires, name):
"""check malformed requirements """check malformed requirements
and tranform dict to internal tuple and tranform dict to internal tuple
@ -936,6 +985,14 @@ def validate_requires_arg(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 = []
else:
options = list(option._dependencies)
options.append(new_option)
option._dependencies = tuple(options)
def get_option(require): def get_option(require):
option = require['option'] option = require['option']
if not isinstance(option, Option): if not isinstance(option, Option):
@ -945,6 +1002,7 @@ def validate_requires_arg(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)
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):
@ -970,6 +1028,7 @@ def validate_requires_arg(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)
if option is not None: if option is not None:
err = option._validate(exp['value']) err = option._validate(exp['value'])
if err: if err:

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"master slave support" "master slave support"
# Copyright (C) 2014 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2014-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -275,3 +275,8 @@ class MasterSlaves(object):
raise SlaveError(_("invalid len for the slave: {0}" raise SlaveError(_("invalid len for the slave: {0}"
" 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_):
for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext())
values._p_.delcache(slave_path)

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"option types and option description" "option types and option description"
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -49,7 +49,7 @@ class ChoiceOption(Option):
:param values: is a list of values the option can possibly take :param values: is a list of values the option can possibly take
""" """
if isinstance(values, FunctionType): if isinstance(values, FunctionType):
validate_callback(values, values_params, 'values') validate_callback(values, values_params, 'values', self)
else: else:
if values_params is not None: if values_params is not None:
raise ValueError(_('values is not a function, so values_params must be None')) raise ValueError(_('values is not a function, so values_params must be None'))

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2014 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2014-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -125,6 +125,13 @@ class OptionDescription(BaseOption, StorageOptionDescription):
cache_option, force_store_values) cache_option, force_store_values)
#cannot set multi option as OptionDescription requires #cannot set multi option as OptionDescription requires
else: else:
if option.impl_is_master_slaves('master'):
if not getattr(option, '_dependencies', None):
options = []
else:
options = list(option._dependencies)
options.append(option.impl_get_master_slaves())
option._dependencies = tuple(options)
option._set_readonly(True) option._set_readonly(True)
is_multi = option.impl_is_multi() is_multi = option.impl_is_multi()
if not isinstance(option, SymLinkOption) and 'force_store_value' in option.impl_getproperties(): if not isinstance(option, SymLinkOption) and 'force_store_value' in option.impl_getproperties():
@ -132,8 +139,8 @@ class OptionDescription(BaseOption, StorageOptionDescription):
for func, all_cons_opts, params in option._get_consistencies(): for func, all_cons_opts, params in option._get_consistencies():
option._valid_consistencies(all_cons_opts[1:], init=False) option._valid_consistencies(all_cons_opts[1:], init=False)
if func not in allowed_const_list and is_multi: if func not in allowed_const_list and is_multi:
is_slave = option.impl_is_master_slaves() is_masterslaves = option.impl_is_master_slaves()
if not is_slave: if not is_masterslaves:
raise ValueError(_('malformed consistency option "{0}" ' raise ValueError(_('malformed consistency option "{0}" '
'must be a master/slaves').format( 'must be a master/slaves').format(
option.impl_getname())) option.impl_getname()))
@ -178,7 +185,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
'must not be a multi for {1}').format( 'must not be a multi for {1}').format(
require_opt.impl_getname(), option.impl_getname())) require_opt.impl_getname(), option.impl_getname()))
if init: if init:
session = config._impl_values._p_.getsession()
if len(cache_option) != len(set(cache_option)): if len(cache_option) != len(set(cache_option)):
for idx in xrange(1, len(cache_option) + 1): for idx in xrange(1, len(cache_option) + 1):
opt = cache_option.pop(0) opt = cache_option.pop(0)
@ -194,7 +200,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
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) self._set_readonly(False)
del(session)
def impl_build_force_store_values(self, config): def impl_build_force_store_values(self, config):
@ -408,8 +413,7 @@ class SynDynOptionDescription(object):
def _impl_getchildren(self, dyn=True, context=undefined): def _impl_getchildren(self, dyn=True, context=undefined):
children = [] children = []
for child in self._opt._impl_getchildren(): for child in self._opt._impl_getchildren():
children.append(self._opt._impl_get_dynchild(child, self._suffix)) yield(self._opt._impl_get_dynchild(child, self._suffix))
return children
def impl_getchildren(self): def impl_getchildren(self):
return self._impl_getchildren() return self._impl_getchildren()

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"sets the options of the configuration objects Config object itself" "sets the options of the configuration objects Config object itself"
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2012-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -269,7 +269,7 @@ class Property(object):
raise ConfigError(_('cannot add those properties: {0}').format(propname)) raise ConfigError(_('cannot add those properties: {0}').format(propname))
self._properties.add(propname) self._properties.add(propname)
if save: if save:
self._setting._setproperties(self._properties, self._path, force=True) self._setting._setproperties(self._properties, self._opt, self._path, force=True)
def remove(self, propname): def remove(self, propname):
"""Removes a property named propname """Removes a property named propname
@ -279,7 +279,7 @@ class Property(object):
""" """
if propname in self._properties: if propname in self._properties:
self._properties.remove(propname) self._properties.remove(propname)
self._setting._setproperties(self._properties, self._path) self._setting._setproperties(self._properties, self._opt, self._path)
def extend(self, propnames): def extend(self, propnames):
"""Extends properties to the existing properties """Extends properties to the existing properties
@ -289,7 +289,7 @@ class Property(object):
""" """
for propname in propnames: for propname in propnames:
self._append(propname, save=False) self._append(propname, save=False)
self._setting._setproperties(self._properties, self._path) self._setting._setproperties(self._properties, self._opt, self._path)
def reset(self): def reset(self):
"""resets the properties (does not **clear** the properties, """resets the properties (does not **clear** the properties,
@ -370,7 +370,7 @@ class Settings(object):
if opt is not None and _path is None: if opt is not None and _path is None:
_path = opt.impl_getpath(self._getcontext()) _path = opt.impl_getpath(self._getcontext())
self._p_.delproperties(_path) self._p_.delproperties(_path)
self._getcontext().cfgimpl_reset_cache() self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path)
def _getproperties(self, opt=None, path=None, def _getproperties(self, opt=None, path=None,
setting_properties=undefined, read_write=True, setting_properties=undefined, read_write=True,
@ -415,20 +415,20 @@ class Settings(object):
props = self._p_.getproperties(None, default_properties) props = self._p_.getproperties(None, default_properties)
if propname not in props: if propname not in props:
props.add(propname) props.add(propname)
self._setproperties(props, None) self._setproperties(props, None, None)
def remove(self, propname): def remove(self, propname):
"deletes property propname in the Config's properties attribute" "deletes property propname in the Config's properties attribute"
props = self._p_.getproperties(None, default_properties) props = self._p_.getproperties(None, default_properties)
if propname in props: if propname in props:
props.remove(propname) props.remove(propname)
self._setproperties(props, None) self._setproperties(props, None, None)
def extend(self, propnames): def extend(self, propnames):
for propname in propnames: for propname in propnames:
self.append(propname) self.append(propname)
def _setproperties(self, properties, path, force=False): def _setproperties(self, properties, opt, path, force=False):
"""save properties for specified path """save properties for specified path
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
@ -438,7 +438,7 @@ class Settings(object):
raise ConfigError(_('cannot add those properties: {0}').format( raise ConfigError(_('cannot add those properties: {0}').format(
' '.join(forbidden_properties))) ' '.join(forbidden_properties)))
self._p_.setproperties(path, properties) self._p_.setproperties(path, properties)
self._getcontext().cfgimpl_reset_cache() self._getcontext().cfgimpl_reset_cache(opt=opt, path=path)
#____________________________________________________________ #____________________________________________________________
def validate_properties(self, opt_or_descr, is_descr, check_frozen, path, def validate_properties(self, opt_or_descr, is_descr, check_frozen, path,
@ -541,7 +541,7 @@ class Settings(object):
if not isinstance(permissive, tuple): # pragma: optional cover if not isinstance(permissive, tuple): # pragma: optional cover
raise TypeError(_('permissive must be a tuple')) raise TypeError(_('permissive must be a tuple'))
self._p_.setpermissive(path, permissive) self._p_.setpermissive(path, permissive)
self._getcontext().cfgimpl_reset_cache() self._getcontext().cfgimpl_reset_cache(opt=opt, path=path)
#____________________________________________________________ #____________________________________________________________
def setowner(self, owner): def setowner(self, owner):
@ -564,7 +564,7 @@ class Settings(object):
props = props | append props = props | append
modified = True modified = True
if modified: if modified:
self._setproperties(props, None) self._setproperties(props, None, None)
def read_only(self): def read_only(self):
"convenience method to freeze, hide and disable" "convenience method to freeze, hide and disable"
@ -574,17 +574,6 @@ class Settings(object):
"convenience method to freeze, hide and disable" "convenience method to freeze, hide and disable"
self._read(rw_remove, rw_append) self._read(rw_remove, rw_append)
def reset_cache(self, only_expired):
"""reset all settings in cache
:param only_expired: if True reset only expired cached values
:type only_expired: boolean
"""
if only_expired:
self._p_.reset_expired_cache(int(time()))
else:
self._p_.reset_all_cache()
def apply_requires(self, opt, path, setting_properties, index, debug): def apply_requires(self, opt, path, setting_properties, index, debug):
"""carries out the jit (just in time) requirements between options """carries out the jit (just in time) requirements between options

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -56,6 +56,7 @@ class StorageBase(object):
'_choice_values_params', '_choice_values_params',
#other #other
'_has_dependency', '_has_dependency',
'_dependencies',
'_state_master_slaves', '_state_master_slaves',
'_state_val_call', '_state_val_call',
'_state_requires', '_state_requires',
@ -64,8 +65,9 @@ class StorageBase(object):
'_state_informations', '_state_informations',
'_state_extra', '_state_extra',
'_state_readonly', '_state_readonly',
'_state_dependencies',
'__weakref__' '__weakref__'
) )
def __init__(self, name, multi, warnings_only, doc, extra, calc_properties, def __init__(self, name, multi, warnings_only, doc, extra, calc_properties,
requires, properties, allow_empty_list, unique, opt=undefined, requires, properties, allow_empty_list, unique, opt=undefined,
@ -588,10 +590,10 @@ class StorageMasterSlaves(object):
def __init__(self, master, slaves): def __init__(self, master, slaves):
self.master = master self.master = master
self.slaves = slaves self.slaves = tuple(slaves)
def _sm_getmaster(self): def _sm_getmaster(self):
return self.master return self.master
def _sm_getslaves(self): def _sm_getslaves(self):
return tuple(self.slaves) return self.slaves

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"default plugin for setting: set it in a simple dictionary" "default plugin for setting: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"default plugin for value: set it in a simple dictionary" "default plugin for value: set it in a simple dictionary"
# Copyright (C) 2013-2014 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"utils used by storage" "utils used by storage"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the # under the terms of the GNU Lesser General Public License as published by the
@ -98,6 +98,9 @@ class Cache(object):
setattr(self, key, value) setattr(self, key, value)
def setcache(self, path, val, time, index): def setcache(self, path, val, time, index):
"""add val in cache for a specified path
if slave, add index
"""
self._cache.setdefault(path, {})[index] = (val, time) self._cache.setdefault(path, {})[index] = (val, time)
def getcache(self, path, exp, index): def getcache(self, path, exp, index):
@ -106,6 +109,12 @@ class Cache(object):
return True, value return True, value
return False, None # pragma: no cover return False, None # pragma: no cover
def delcache(self, path):
"""remove cache for a specified path
"""
if path in self._cache:
del self._cache[path]
def hascache(self, path, index): def hascache(self, path, index):
""" path is in the cache """ path is in the cache

View file

@ -201,7 +201,7 @@ class Values(object):
self._setvalue(opt, path, value, force_owner=owners.forced) self._setvalue(opt, path, value, force_owner=owners.forced)
else: else:
self._p_.resetvalue(path, session) self._p_.resetvalue(path, session)
context.cfgimpl_reset_cache() context.cfgimpl_reset_cache(opt=opt, path=path)
def _isempty(self, opt, value, force_allow_empty_list=False, index=None): def _isempty(self, opt, value, force_allow_empty_list=False, index=None):
"convenience method to know if an option is empty" "convenience method to know if an option is empty"
@ -427,7 +427,7 @@ class Values(object):
def _setvalue(self, opt, path, value, force_owner=undefined, index=None): def _setvalue(self, opt, path, value, force_owner=undefined, index=None):
context = self._getcontext() context = self._getcontext()
context.cfgimpl_reset_cache() context.cfgimpl_reset_cache(opt=opt, path=path)
if force_owner is undefined: if force_owner is undefined:
owner = context.cfgimpl_get_settings().getowner() owner = context.cfgimpl_get_settings().getowner()
else: else:
@ -599,15 +599,6 @@ class Values(object):
index=index, force_permissive=force_permissive) index=index, force_permissive=force_permissive)
return d == owners.default return d == owners.default
def reset_cache(self, only_expired):
"""
clears the cache if necessary
"""
if only_expired:
self._p_.reset_expired_cache(int(time()))
else:
self._p_.reset_all_cache()
# information # information
def set_information(self, key, value): def set_information(self, key, value):
"""updates the information's attribute """updates the information's attribute
@ -699,8 +690,7 @@ class Values(object):
if not 'cache' in context.cfgimpl_get_settings(): if not 'cache' in context.cfgimpl_get_settings():
raise ConfigError(_('can force cache only if cache ' raise ConfigError(_('can force cache only if cache '
'is actived in config')) 'is actived in config'))
#remove all cached properties and value to update "expired" time #FIXME properties and value should update "expired" time
context.cfgimpl_reset_cache()
for path in context.cfgimpl_get_description().impl_getpaths( for path in context.cfgimpl_get_description().impl_getpaths(
include_groups=True): include_groups=True):
err = context.getattr(path, returns_raise=True) err = context.getattr(path, returns_raise=True)