never same calculated properties has properties (only in cache)

This commit is contained in:
Emmanuel Garette 2013-08-22 22:46:02 +02:00
parent 3a6296f7e0
commit 04aa4e6bf1
3 changed files with 63 additions and 49 deletions

View file

@ -429,3 +429,13 @@ def test_requires_multi_disabled_inverse_2():
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled']
def test_requires_requirement_append():
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.read_write()
raises(ValueError, 'c.cfgimpl_get_settings()[b].append("disabled")')

View file

@ -97,10 +97,9 @@ class Option(BaseInformation):
Reminder: an Option object is **not** a container for the value
"""
__slots__ = ('_name', '_requires', '_multi', '_validator',
'_default_multi',
'_default',
'_properties', '_callback', '_multitype',
'_master_slaves', '_consistencies', '_empty')
'_default_multi', '_default', '_properties', '_callback',
'_multitype', '_master_slaves', '_consistencies', '_empty',
'_calc_properties')
_empty = ''
def __init__(self, name, doc, default=None, default_multi=None,
@ -130,8 +129,8 @@ class Option(BaseInformation):
self._name = name
self._impl_informations = {}
self.impl_set_information('doc', doc)
requires = validate_requires_arg(requires, self._name)
self._requires = requires
self._calc_properties, self._requires = validate_requires_arg(
requires, self._name)
self._multi = multi
self._consistencies = None
if validator is not None:
@ -714,7 +713,8 @@ class OptionDescription(BaseInformation):
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
"""
__slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
'_properties', '_children', '_consistencies')
'_properties', '_children', '_consistencies',
'_calc_properties')
def __init__(self, name, doc, children, requires=None, properties=None):
"""
@ -738,8 +738,7 @@ class OptionDescription(BaseInformation):
'{0}').format(child))
old = child
self._children = (tuple(child_names), tuple(children))
requires = validate_requires_arg(requires, self._name)
self._requires = requires
self._calc_properties, self._requires = validate_requires_arg(requires, self._name)
self._cache_paths = None
self._consistencies = None
if properties is None:
@ -933,7 +932,7 @@ def validate_requires_arg(requires, name):
the description of the requires dictionnary
"""
if requires is None:
return None
return None, None
ret_requires = {}
config_action = {}
@ -999,7 +998,6 @@ def validate_requires_arg(requires, name):
inverse, transitive, same_action)
else:
ret_requires[action][option][1].append(expected)
ret = []
for opt_requires in ret_requires.values():
ret_action = []
@ -1011,4 +1009,4 @@ def validate_requires_arg(requires, name):
require[5])
ret_action.append(req)
ret.append(tuple(ret_action))
return tuple(ret)
return tuple(config_action.keys()), tuple(ret)

View file

@ -161,6 +161,11 @@ class Property(object):
self._properties = prop
def append(self, propname):
if self._opt is not None and self._opt._calc_properties is not None \
and propname in self._opt._calc_properties:
raise ValueError(_('cannot append {0} property for option {1}: '
'this property is calculated').format(
propname, self._opt._name))
self._properties.add(propname)
self._setting._setproperties(self._properties, self._opt, self._path)
@ -250,9 +255,9 @@ class Settings(object):
is_cached, props = self._p_.getcache('property', path, ntime)
if is_cached:
return props
if is_apply_req:
self.apply_requires(opt, path)
props = self._p_.getproperties(path, opt._properties)
if is_apply_req:
props |= self.apply_requires(opt, path)
if 'expire' in self:
if ntime is None:
ntime = time()
@ -261,11 +266,16 @@ class Settings(object):
def append(self, propname):
"puts property propname in the Config's properties attribute"
Property(self, self._getproperties()).append(propname)
props = self._p_.getproperties(None, default_properties)
props.add(propname)
self._setproperties(props, None, None)
def remove(self, propname):
"deletes property propname in the Config's properties attribute"
Property(self, self._getproperties()).remove(propname)
props = self._p_.getproperties(None, default_properties)
if propname in props:
props.remove(propname)
self._setproperties(props, None, None)
def _setproperties(self, properties, opt, path):
"""save properties for specified opt
@ -274,6 +284,8 @@ class Settings(object):
if opt is None:
self._p_.setproperties(None, properties)
else:
if opt._calc_properties is not None:
properties -= opt._calc_properties
if set(opt._properties) == properties:
self._p_.reset_properties(path)
else:
@ -420,14 +432,11 @@ class Settings(object):
:type path: str
"""
if opt._requires is None:
return
return frozenset()
# filters the callbacks
setting = Property(self,
self._getproperties(opt, path, False),
opt, path=path)
calc_properties = set()
for requires in opt._requires:
matches = False
for require in requires:
option, expected, action, inverse, \
transitive, same_action = require
@ -460,13 +469,10 @@ class Settings(object):
if (not inverse and
value in expected or
inverse and value not in expected):
matches = True
setting.append(action)
calc_properties.add(action)
# the calculation cannot be carried out
break
# no requirement has been triggered, then just reverse the action
if not matches:
setting.remove(action)
return calc_properties
def _get_opt_path(self, opt):
return self.context.cfgimpl_get_description().impl_get_path_by_opt(opt)