optimisations
This commit is contained in:
parent
122796bd19
commit
ec169a8dc6
|
@ -83,6 +83,22 @@ def test_consistency_warnings_only_more_option():
|
||||||
assert len(w) == 1
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_warnings_only_option():
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', warnings_only=True)
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
a.impl_add_consistency('not_equal', b)
|
||||||
|
api = Config(od)
|
||||||
|
api.option('a').value.set(1)
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
api.option('b').value.set(1)
|
||||||
|
assert w != []
|
||||||
|
api.option('a').value.reset()
|
||||||
|
api.option('b').value.set(1)
|
||||||
|
raises(ValueError, "api.option('a').value.set(1)")
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_not_equal():
|
def test_consistency_not_equal():
|
||||||
a = IntOption('a', '')
|
a = IntOption('a', '')
|
||||||
b = IntOption('b', '')
|
b = IntOption('b', '')
|
||||||
|
@ -786,6 +802,48 @@ def test_consistency_with_callback():
|
||||||
api.option('c').value.get()
|
api.option('c').value.get()
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_warnings_only_options():
|
||||||
|
a = IPOption('a', '', warnings_only=True)
|
||||||
|
b = IPOption('b', '')
|
||||||
|
c = NetworkOption('c', '', default='192.168.1.0')
|
||||||
|
d = NetmaskOption('d', '', default='255.255.255.0', properties=('disabled',))
|
||||||
|
od = OptionDescription('od', '', [a, b, c, d])
|
||||||
|
a.impl_add_consistency('not_equal', b)
|
||||||
|
a.impl_add_consistency('in_network', c, d, transitive=False)
|
||||||
|
api = Config(od)
|
||||||
|
api.property.read_write()
|
||||||
|
api.option('a').value.set('192.168.1.1')
|
||||||
|
raises(ValueError, "api.option('b').value.set('192.168.1.1')")
|
||||||
|
api.option('a').value.set('192.168.2.1')
|
||||||
|
#
|
||||||
|
api.option('a').value.set('192.168.1.1')
|
||||||
|
api.property.pop('disabled')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
api.option('a').value.set('192.168.2.1')
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
#def test_consistency_warnings_only_options_callback():
|
||||||
|
# a = IPOption('a', '', warnings_only=True)
|
||||||
|
# b = IPOption('b', '')
|
||||||
|
# c = NetworkOption('c', '', default='192.168.1.0')
|
||||||
|
# d = NetmaskOption('d', '', callback=return_netmask2, callback_params=Params(ParamOption(a)))
|
||||||
|
# od = OptionDescription('od', '', [a, b, c, d])
|
||||||
|
# a.impl_add_consistency('not_equal', b)
|
||||||
|
# a.impl_add_consistency('in_network', c, d, transitive=False)
|
||||||
|
# api = Config(od)
|
||||||
|
# api.property.read_write()
|
||||||
|
# api.option('a').value.set('192.168.1.1')
|
||||||
|
# raises(ValueError, "api.option('b').value.set('192.168.1.1')")
|
||||||
|
# api.option('a').value.set('192.168.2.1')
|
||||||
|
# #
|
||||||
|
# api.option('a').value.set('192.168.1.1')
|
||||||
|
# api.property.pop('disabled')
|
||||||
|
# with warnings.catch_warnings(record=True) as w:
|
||||||
|
# api.option('a').value.set('192.168.2.1')
|
||||||
|
# assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_double_warnings():
|
def test_consistency_double_warnings():
|
||||||
a = IntOption('a', '')
|
a = IntOption('a', '')
|
||||||
b = IntOption('b', '', 1)
|
b = IntOption('b', '', 1)
|
||||||
|
@ -802,10 +860,7 @@ def test_consistency_double_warnings():
|
||||||
assert len(w) == 2
|
assert len(w) == 2
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
api.option('od.c').value.set(2)
|
api.option('od.c').value.set(2)
|
||||||
if TIRAMISU_VERSION == 2:
|
assert len(w) == 0
|
||||||
assert len(w) == 0
|
|
||||||
else:
|
|
||||||
assert len(w) == 1
|
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
api.option('od.a').value.set(2)
|
api.option('od.a').value.set(2)
|
||||||
assert w != []
|
assert w != []
|
||||||
|
|
|
@ -71,6 +71,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||||
# don't validate if option is option that we tried to validate
|
# don't validate if option is option that we tried to validate
|
||||||
config_bag = option_bag.config_bag.copy()
|
config_bag = option_bag.config_bag.copy()
|
||||||
config_bag.set_permissive()
|
config_bag.set_permissive()
|
||||||
|
config_bag.properties -= {'warnings'}
|
||||||
soption_bag = OptionBag()
|
soption_bag = OptionBag()
|
||||||
soption_bag.set_option(opt,
|
soption_bag.set_option(opt,
|
||||||
path,
|
path,
|
||||||
|
|
|
@ -626,7 +626,7 @@ class SubConfig(object):
|
||||||
descr = self.cfgimpl_get_description()
|
descr = self.cfgimpl_get_description()
|
||||||
if not dyn and descr.impl_is_dynoptiondescription():
|
if not dyn and descr.impl_is_dynoptiondescription():
|
||||||
context_descr = self.cfgimpl_get_context().cfgimpl_get_description()
|
context_descr = self.cfgimpl_get_context().cfgimpl_get_description()
|
||||||
return context_descr.impl_get_path_by_opt(descr.impl_getopt())
|
return descr.impl_getopt().impl_getpath(context_descr)
|
||||||
return self._impl_path
|
return self._impl_path
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ class Base(object):
|
||||||
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)
|
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_name',
|
__slots__ = ('_name',
|
||||||
|
'_path',
|
||||||
'_informations',
|
'_informations',
|
||||||
#calcul
|
#calcul
|
||||||
'_subdyn',
|
'_subdyn',
|
||||||
|
@ -407,7 +408,7 @@ class BaseOption(Base):
|
||||||
is_readonly = True
|
is_readonly = True
|
||||||
elif name != '_readonly':
|
elif name != '_readonly':
|
||||||
is_readonly = self.impl_is_readonly()
|
is_readonly = self.impl_is_readonly()
|
||||||
if is_readonly:
|
if is_readonly and (name != '_path' or value != getattr(self, '_path', value)):
|
||||||
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
|
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
|
||||||
' read-only').format(self.__class__.__name__,
|
' read-only').format(self.__class__.__name__,
|
||||||
self.impl_get_display_name(),
|
self.impl_get_display_name(),
|
||||||
|
@ -416,7 +417,8 @@ class BaseOption(Base):
|
||||||
|
|
||||||
def impl_getpath(self,
|
def impl_getpath(self,
|
||||||
context):
|
context):
|
||||||
return context.cfgimpl_get_description().impl_get_path_by_opt(self)
|
return self._path
|
||||||
|
#return context.cfgimpl_get_description().impl_get_path_by_opt(self)
|
||||||
|
|
||||||
def impl_has_callback(self):
|
def impl_has_callback(self):
|
||||||
"to know if a callback has been defined or not"
|
"to know if a callback has been defined or not"
|
||||||
|
|
|
@ -194,6 +194,7 @@ class Option(OnlyOption):
|
||||||
else:
|
else:
|
||||||
config_bag = undefined
|
config_bag = undefined
|
||||||
force_index = None
|
force_index = None
|
||||||
|
is_warnings_only = getattr(self, '_warnings_only', False)
|
||||||
|
|
||||||
if check_error and config_bag is not undefined and \
|
if check_error and config_bag is not undefined and \
|
||||||
not 'validator' in config_bag.properties:
|
not 'validator' in config_bag.properties:
|
||||||
|
@ -201,7 +202,8 @@ class Option(OnlyOption):
|
||||||
self.valid_consistency(option_bag,
|
self.valid_consistency(option_bag,
|
||||||
value,
|
value,
|
||||||
context,
|
context,
|
||||||
check_error)
|
check_error,
|
||||||
|
is_warnings_only)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _is_not_unique(value):
|
def _is_not_unique(value):
|
||||||
|
@ -250,15 +252,27 @@ class Option(OnlyOption):
|
||||||
option_bag.ori_option)
|
option_bag.ori_option)
|
||||||
if ((check_error and not is_warnings_only) or
|
if ((check_error and not is_warnings_only) or
|
||||||
(not check_error and is_warnings_only)):
|
(not check_error and is_warnings_only)):
|
||||||
calculation_validator(_value,
|
try:
|
||||||
_index)
|
calculation_validator(_value,
|
||||||
self._second_level_validation(_value,
|
_index)
|
||||||
is_warnings_only)
|
self._second_level_validation(_value,
|
||||||
|
is_warnings_only)
|
||||||
|
except ValueError as err:
|
||||||
|
if is_warnings_only:
|
||||||
|
msg = _('attention, "{0}" could be an invalid {1} for "{2}"'
|
||||||
|
'').format(val,
|
||||||
|
self._display_name,
|
||||||
|
self.impl_get_display_name())
|
||||||
|
err_msg = '{0}'.format(err)
|
||||||
|
if err_msg:
|
||||||
|
msg += ', {}'.format(err_msg)
|
||||||
|
warnings.warn_explicit(ValueWarning(msg, weakref.ref(self)),
|
||||||
|
ValueWarning,
|
||||||
|
self.__class__.__name__, 0)
|
||||||
|
else:
|
||||||
|
raise err
|
||||||
#if is_multi is None:
|
#if is_multi is None:
|
||||||
# is_multi = self.impl_is_multi()
|
# is_multi = self.impl_is_multi()
|
||||||
|
|
||||||
is_warnings_only = getattr(self, '_warnings_only', False)
|
|
||||||
try:
|
try:
|
||||||
val = value
|
val = value
|
||||||
if not self.impl_is_multi():
|
if not self.impl_is_multi():
|
||||||
|
@ -294,33 +308,24 @@ class Option(OnlyOption):
|
||||||
self.valid_consistency(option_bag,
|
self.valid_consistency(option_bag,
|
||||||
value,
|
value,
|
||||||
context,
|
context,
|
||||||
check_error)
|
check_error,
|
||||||
|
is_warnings_only)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
|
#raise err
|
||||||
if debug: # pragma: no cover
|
if debug: # pragma: no cover
|
||||||
log.debug('do_validation: value: {0}, index: {1}:'
|
log.debug('do_validation: value: {0}, index: {1}:'
|
||||||
' {2}'.format(val,
|
' {2}'.format(val,
|
||||||
force_index,
|
force_index,
|
||||||
err),
|
err),
|
||||||
exc_info=True)
|
exc_info=True)
|
||||||
if is_warnings_only:
|
msg = _('"{0}" is an invalid {1} for "{2}"'
|
||||||
msg = _('attention, "{0}" could be an invalid {1} for "{2}"'
|
'').format(val,
|
||||||
'').format(val,
|
self._display_name,
|
||||||
self._display_name,
|
self.impl_get_display_name())
|
||||||
self.impl_get_display_name())
|
|
||||||
else:
|
|
||||||
msg = _('"{0}" is an invalid {1} for "{2}"'
|
|
||||||
'').format(val,
|
|
||||||
self._display_name,
|
|
||||||
self.impl_get_display_name())
|
|
||||||
err_msg = '{0}'.format(err)
|
err_msg = '{0}'.format(err)
|
||||||
if err_msg:
|
if err_msg:
|
||||||
msg += ', {}'.format(err_msg)
|
msg += ', {}'.format(err_msg)
|
||||||
if check_error:
|
raise ValueError(msg)
|
||||||
raise ValueError(msg)
|
|
||||||
else:
|
|
||||||
warnings.warn_explicit(ValueWarning(msg, weakref.ref(self)),
|
|
||||||
ValueWarning,
|
|
||||||
self.__class__.__name__, 0)
|
|
||||||
|
|
||||||
|
|
||||||
def impl_is_dynsymlinkoption(self):
|
def impl_is_dynsymlinkoption(self):
|
||||||
|
@ -449,7 +454,8 @@ class Option(OnlyOption):
|
||||||
option_bag,
|
option_bag,
|
||||||
value,
|
value,
|
||||||
context,
|
context,
|
||||||
check_error):
|
check_error,
|
||||||
|
option_warnings_only):
|
||||||
if context is not undefined:
|
if context is not undefined:
|
||||||
descr = context.cfgimpl_get_description()
|
descr = context.cfgimpl_get_description()
|
||||||
# no consistency found at all
|
# no consistency found at all
|
||||||
|
@ -468,9 +474,10 @@ class Option(OnlyOption):
|
||||||
cconfig_bag = undefined
|
cconfig_bag = undefined
|
||||||
else:
|
else:
|
||||||
cconfig_bag = option_bag.config_bag.copy()
|
cconfig_bag = option_bag.config_bag.copy()
|
||||||
|
cconfig_bag.properties = cconfig_bag.properties - {'warnings'}
|
||||||
cconfig_bag.set_permissive()
|
cconfig_bag.set_permissive()
|
||||||
for cons_id, func, all_cons_opts, params in consistencies:
|
for cons_id, func, all_cons_opts, params in consistencies:
|
||||||
warnings_only = params.get('warnings_only', False)
|
warnings_only = option_warnings_only or params.get('warnings_only', False)
|
||||||
if (warnings_only and not check_error) or (not warnings_only and check_error):
|
if (warnings_only and not check_error) or (not warnings_only and check_error):
|
||||||
transitive = params.get('transitive', True)
|
transitive = params.get('transitive', True)
|
||||||
#all_cons_opts[0] is the option where func is set
|
#all_cons_opts[0] is the option where func is set
|
||||||
|
|
|
@ -213,6 +213,7 @@ class CacheOptionDescription(BaseOption):
|
||||||
path = str('.'.join(_currpath + [attr]))
|
path = str('.'.join(_currpath + [attr]))
|
||||||
cache_option.append(option)
|
cache_option.append(option)
|
||||||
cache_path.append(path)
|
cache_path.append(path)
|
||||||
|
option._path = path
|
||||||
if option.impl_is_optiondescription():
|
if option.impl_is_optiondescription():
|
||||||
_currpath.append(attr)
|
_currpath.append(attr)
|
||||||
option._build_cache_option(_currpath,
|
option._build_cache_option(_currpath,
|
||||||
|
@ -230,7 +231,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
option_bag):
|
option_bag):
|
||||||
option = option_bag.option
|
option = option_bag.option
|
||||||
dynopt = option.getsubdyn()
|
dynopt = option.getsubdyn()
|
||||||
rootpath = self.impl_get_path_by_opt(dynopt)
|
rootpath = dynopt.impl_getpath(option_bag.config_bag.context)
|
||||||
ori_index = len(rootpath) + 1
|
ori_index = len(rootpath) + 1
|
||||||
subpaths = [rootpath] + option.impl_getpath(
|
subpaths = [rootpath] + option.impl_getpath(
|
||||||
option_bag.config_bag.context)[ori_index:].split('.')[:-1]
|
option_bag.config_bag.context)[ori_index:].split('.')[:-1]
|
||||||
|
|
|
@ -23,6 +23,7 @@ from ..i18n import _
|
||||||
|
|
||||||
|
|
||||||
class SymLinkOption(OnlyOption):
|
class SymLinkOption(OnlyOption):
|
||||||
|
__slots__ = ('_opt',)
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
name,
|
||||||
|
@ -39,6 +40,8 @@ class SymLinkOption(OnlyOption):
|
||||||
|
|
||||||
def __getattr__(self,
|
def __getattr__(self,
|
||||||
name):
|
name):
|
||||||
|
if name == '_path':
|
||||||
|
return
|
||||||
return getattr(self._opt, name)
|
return getattr(self._opt, name)
|
||||||
|
|
||||||
def impl_has_dependency(self,
|
def impl_has_dependency(self,
|
||||||
|
@ -55,7 +58,7 @@ class SymLinkOption(OnlyOption):
|
||||||
return self._opt
|
return self._opt
|
||||||
|
|
||||||
def impl_is_readonly(self):
|
def impl_is_readonly(self):
|
||||||
return True
|
return self._path is not None
|
||||||
|
|
||||||
def get_consistencies(self):
|
def get_consistencies(self):
|
||||||
return ()
|
return ()
|
||||||
|
|
|
@ -138,7 +138,7 @@ class OptionBag:
|
||||||
index,
|
index,
|
||||||
config_bag):
|
config_bag):
|
||||||
if path is None:
|
if path is None:
|
||||||
path = config_bag.context.cfgimpl_get_description().impl_get_path_by_opt(option)
|
path = option.impl_getpath(config_bag.context)
|
||||||
self.path = path
|
self.path = path
|
||||||
self.index = index
|
self.index = index
|
||||||
self.option = option
|
self.option = option
|
||||||
|
@ -156,6 +156,11 @@ class OptionBag:
|
||||||
return True
|
return True
|
||||||
raise KeyError('unknown key {} for OptionBag'.format(key))
|
raise KeyError('unknown key {} for OptionBag'.format(key))
|
||||||
|
|
||||||
|
def __delattr__(self, key):
|
||||||
|
if key == 'properties':
|
||||||
|
return
|
||||||
|
raise KeyError('unknown key {} for ConfigBag'.format(key))
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
option_bag = OptionBag()
|
option_bag = OptionBag()
|
||||||
|
|
|
@ -88,7 +88,7 @@ class Cache(DictCache):
|
||||||
print('getcache expired value for path {} < {}'.format(
|
print('getcache expired value for path {} < {}'.format(
|
||||||
timestamp + expires_time, ntime))
|
timestamp + expires_time, ntime))
|
||||||
# if expired, remove from cache
|
# if expired, remove from cache
|
||||||
self.delcache(path)
|
#self.delcache(path)
|
||||||
else:
|
else:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print('getcache in cache (2)', path, value, _display_classname(self),
|
print('getcache in cache (2)', path, value, _display_classname(self),
|
||||||
|
|
|
@ -84,6 +84,8 @@ class Values(object):
|
||||||
# validate value
|
# validate value
|
||||||
context = self._getcontext()
|
context = self._getcontext()
|
||||||
opt = option_bag.option
|
opt = option_bag.option
|
||||||
|
#print('===', option_bag.path)
|
||||||
|
#if not is_cached:
|
||||||
opt.impl_validate(value,
|
opt.impl_validate(value,
|
||||||
option_bag,
|
option_bag,
|
||||||
context=context,
|
context=context,
|
||||||
|
@ -160,13 +162,15 @@ class Values(object):
|
||||||
opt = option_bag.option
|
opt = option_bag.option
|
||||||
index = option_bag.index
|
index = option_bag.index
|
||||||
def _reset_cache(_value):
|
def _reset_cache(_value):
|
||||||
|
if not 'expire' in option_bag.properties:
|
||||||
|
return
|
||||||
is_cache, cache_value = self._p_.getcache(option_bag.path,
|
is_cache, cache_value = self._p_.getcache(option_bag.path,
|
||||||
expires_time,
|
None,
|
||||||
index,
|
index,
|
||||||
config_bag.properties,
|
config_bag.properties,
|
||||||
option_bag.properties,
|
option_bag.properties,
|
||||||
'value')
|
'value')
|
||||||
if is_cache and cache_value == _value:
|
if not is_cache or cache_value == _value:
|
||||||
# calculation return same value as previous value,
|
# calculation return same value as previous value,
|
||||||
# so do not invalidate cache
|
# so do not invalidate cache
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue