better cache

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

View File

@ -1,5 +1,5 @@
# -*- 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
# 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 ..i18n import _
from ..setting import log, undefined, debug
from ..setting import log, undefined, debug, groups
from ..autolib import carry_out_calculation
from ..error import (ConfigError, ValueWarning, PropertiesOptionError,
display_list)
@ -58,7 +58,7 @@ def valid_name(name):
return False
def validate_callback(callback, callback_params, type_):
def validate_callback(callback, callback_params, type_, callbackoption):
if not isinstance(callback, FunctionType):
raise ValueError(_('{0} must be a function').format(type_))
if callback_params is not None:
@ -94,6 +94,17 @@ def validate_callback(callback, callback_params, type_):
' not a {} for second argument'
).format(type_, type(
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:
raise ValueError(_('unique must be set only with multi value'))
if requires is not None:
calc_properties, requires = validate_requires_arg(is_multi,
calc_properties, requires = validate_requires_arg(self, is_multi,
requires, name)
else:
calc_properties = frozenset()
@ -143,7 +154,7 @@ class Base(StorageBase):
if multi: # and validator_params is None:
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_has_dependency()
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()))
self._validate_callback(callback, callback_params)
if callback is not None:
validate_callback(callback, callback_params, 'callback')
validate_callback(callback, callback_params, 'callback', self)
self._set_callback(callback, callback_params)
def impl_is_optiondescription(self):
@ -239,6 +250,36 @@ class BaseOption(Base):
# ____________________________________________________________
# 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):
"""export of the requires during the serialization process
@ -417,6 +458,14 @@ class BaseOption(Base):
name = name.encode('utf8')
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):
__slots__ = tuple()
@ -927,7 +976,7 @@ class Option(OnlyOption):
"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
and tranform dict to internal tuple
@ -936,6 +985,14 @@ def validate_requires_arg(multi, requires, name):
know more about
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):
option = require['option']
if not isinstance(option, Option):
@ -945,6 +1002,7 @@ def validate_requires_arg(multi, requires, name):
raise ValueError(_('malformed requirements '
'multi option must not set '
'as requires of non multi option {0}').format(name))
set_dependency(option)
return option
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 '
'option and value for option {0}').format(name))
option = exp['option']
set_dependency(option)
if option is not None:
err = option._validate(exp['value'])
if err:

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"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
# 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}"
" which has {1} as master").format(
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 -*-
"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
# 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
"""
if isinstance(values, FunctionType):
validate_callback(values, values_params, 'values')
validate_callback(values, values_params, 'values', self)
else:
if values_params is not None:
raise ValueError(_('values is not a function, so values_params must be None'))

View File

@ -1,5 +1,5 @@
# -*- 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
# 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)
#cannot set multi option as OptionDescription requires
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)
is_multi = option.impl_is_multi()
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():
option._valid_consistencies(all_cons_opts[1:], init=False)
if func not in allowed_const_list and is_multi:
is_slave = option.impl_is_master_slaves()
if not is_slave:
is_masterslaves = option.impl_is_master_slaves()
if not is_masterslaves:
raise ValueError(_('malformed consistency option "{0}" '
'must be a master/slaves').format(
option.impl_getname()))
@ -178,7 +185,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
'must not be a multi for {1}').format(
require_opt.impl_getname(), option.impl_getname()))
if init:
session = config._impl_values._p_.getsession()
if len(cache_option) != len(set(cache_option)):
for idx in xrange(1, len(cache_option) + 1):
opt = cache_option.pop(0)
@ -194,7 +200,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
self._cache_consistencies[opt] = tuple(cons)
self._cache_force_store_values = force_store_values
self._set_readonly(False)
del(session)
def impl_build_force_store_values(self, config):
@ -408,8 +413,7 @@ class SynDynOptionDescription(object):
def _impl_getchildren(self, dyn=True, context=undefined):
children = []
for child in self._opt._impl_getchildren():
children.append(self._opt._impl_get_dynchild(child, self._suffix))
return children
yield(self._opt._impl_get_dynchild(child, self._suffix))
def impl_getchildren(self):
return self._impl_getchildren()