never same calculated properties has properties (only in cache)
This commit is contained in:
parent
3a6296f7e0
commit
04aa4e6bf1
|
@ -429,3 +429,13 @@ def test_requires_multi_disabled_inverse_2():
|
||||||
except PropertiesOptionError, err:
|
except PropertiesOptionError, err:
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
assert props == ['disabled']
|
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")')
|
||||||
|
|
|
@ -97,10 +97,9 @@ class Option(BaseInformation):
|
||||||
Reminder: an Option object is **not** a container for the value
|
Reminder: an Option object is **not** a container for the value
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_name', '_requires', '_multi', '_validator',
|
__slots__ = ('_name', '_requires', '_multi', '_validator',
|
||||||
'_default_multi',
|
'_default_multi', '_default', '_properties', '_callback',
|
||||||
'_default',
|
'_multitype', '_master_slaves', '_consistencies', '_empty',
|
||||||
'_properties', '_callback', '_multitype',
|
'_calc_properties')
|
||||||
'_master_slaves', '_consistencies', '_empty')
|
|
||||||
_empty = ''
|
_empty = ''
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
|
@ -130,8 +129,8 @@ class Option(BaseInformation):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._impl_informations = {}
|
self._impl_informations = {}
|
||||||
self.impl_set_information('doc', doc)
|
self.impl_set_information('doc', doc)
|
||||||
requires = validate_requires_arg(requires, self._name)
|
self._calc_properties, self._requires = validate_requires_arg(
|
||||||
self._requires = requires
|
requires, self._name)
|
||||||
self._multi = multi
|
self._multi = multi
|
||||||
self._consistencies = None
|
self._consistencies = None
|
||||||
if validator is not None:
|
if validator is not None:
|
||||||
|
@ -714,7 +713,8 @@ class OptionDescription(BaseInformation):
|
||||||
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
|
__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):
|
def __init__(self, name, doc, children, requires=None, properties=None):
|
||||||
"""
|
"""
|
||||||
|
@ -738,8 +738,7 @@ class OptionDescription(BaseInformation):
|
||||||
'{0}').format(child))
|
'{0}').format(child))
|
||||||
old = child
|
old = child
|
||||||
self._children = (tuple(child_names), tuple(children))
|
self._children = (tuple(child_names), tuple(children))
|
||||||
requires = validate_requires_arg(requires, self._name)
|
self._calc_properties, self._requires = validate_requires_arg(requires, self._name)
|
||||||
self._requires = requires
|
|
||||||
self._cache_paths = None
|
self._cache_paths = None
|
||||||
self._consistencies = None
|
self._consistencies = None
|
||||||
if properties is None:
|
if properties is None:
|
||||||
|
@ -933,7 +932,7 @@ def validate_requires_arg(requires, name):
|
||||||
the description of the requires dictionnary
|
the description of the requires dictionnary
|
||||||
"""
|
"""
|
||||||
if requires is None:
|
if requires is None:
|
||||||
return None
|
return None, None
|
||||||
ret_requires = {}
|
ret_requires = {}
|
||||||
config_action = {}
|
config_action = {}
|
||||||
|
|
||||||
|
@ -999,7 +998,6 @@ def validate_requires_arg(requires, name):
|
||||||
inverse, transitive, same_action)
|
inverse, transitive, same_action)
|
||||||
else:
|
else:
|
||||||
ret_requires[action][option][1].append(expected)
|
ret_requires[action][option][1].append(expected)
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
for opt_requires in ret_requires.values():
|
for opt_requires in ret_requires.values():
|
||||||
ret_action = []
|
ret_action = []
|
||||||
|
@ -1011,4 +1009,4 @@ def validate_requires_arg(requires, name):
|
||||||
require[5])
|
require[5])
|
||||||
ret_action.append(req)
|
ret_action.append(req)
|
||||||
ret.append(tuple(ret_action))
|
ret.append(tuple(ret_action))
|
||||||
return tuple(ret)
|
return tuple(config_action.keys()), tuple(ret)
|
||||||
|
|
|
@ -161,6 +161,11 @@ class Property(object):
|
||||||
self._properties = prop
|
self._properties = prop
|
||||||
|
|
||||||
def append(self, propname):
|
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._properties.add(propname)
|
||||||
self._setting._setproperties(self._properties, self._opt, self._path)
|
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)
|
is_cached, props = self._p_.getcache('property', path, ntime)
|
||||||
if is_cached:
|
if is_cached:
|
||||||
return props
|
return props
|
||||||
if is_apply_req:
|
|
||||||
self.apply_requires(opt, path)
|
|
||||||
props = self._p_.getproperties(path, opt._properties)
|
props = self._p_.getproperties(path, opt._properties)
|
||||||
|
if is_apply_req:
|
||||||
|
props |= self.apply_requires(opt, path)
|
||||||
if 'expire' in self:
|
if 'expire' in self:
|
||||||
if ntime is None:
|
if ntime is None:
|
||||||
ntime = time()
|
ntime = time()
|
||||||
|
@ -261,11 +266,16 @@ class Settings(object):
|
||||||
|
|
||||||
def append(self, propname):
|
def append(self, propname):
|
||||||
"puts property propname in the Config's properties attribute"
|
"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):
|
def remove(self, propname):
|
||||||
"deletes property propname in the Config's properties attribute"
|
"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):
|
def _setproperties(self, properties, opt, path):
|
||||||
"""save properties for specified opt
|
"""save properties for specified opt
|
||||||
|
@ -274,6 +284,8 @@ class Settings(object):
|
||||||
if opt is None:
|
if opt is None:
|
||||||
self._p_.setproperties(None, properties)
|
self._p_.setproperties(None, properties)
|
||||||
else:
|
else:
|
||||||
|
if opt._calc_properties is not None:
|
||||||
|
properties -= opt._calc_properties
|
||||||
if set(opt._properties) == properties:
|
if set(opt._properties) == properties:
|
||||||
self._p_.reset_properties(path)
|
self._p_.reset_properties(path)
|
||||||
else:
|
else:
|
||||||
|
@ -378,56 +390,53 @@ class Settings(object):
|
||||||
|
|
||||||
def apply_requires(self, opt, path):
|
def apply_requires(self, opt, path):
|
||||||
"""carries out the jit (just in time) requirements between options
|
"""carries out the jit (just in time) requirements between options
|
||||||
|
|
||||||
a requirement is a tuple of this form that comes from the option's
|
a requirement is a tuple of this form that comes from the option's
|
||||||
requirements validation::
|
requirements validation::
|
||||||
|
|
||||||
(option, expected, action, inverse, transitive, same_action)
|
(option, expected, action, inverse, transitive, same_action)
|
||||||
|
|
||||||
let's have a look at all the tuple's items:
|
let's have a look at all the tuple's items:
|
||||||
|
|
||||||
- **option** is the target option's name or path
|
- **option** is the target option's name or path
|
||||||
|
|
||||||
- **expected** is the target option's value that is going to trigger an action
|
- **expected** is the target option's value that is going to trigger an action
|
||||||
|
|
||||||
- **action** is the (property) action to be accomplished if the target option
|
- **action** is the (property) action to be accomplished if the target option
|
||||||
happens to have the expected value
|
happens to have the expected value
|
||||||
|
|
||||||
- if **inverse** is `True` and if the target option's value does not
|
- if **inverse** is `True` and if the target option's value does not
|
||||||
apply, then the property action must be removed from the option's
|
apply, then the property action must be removed from the option's
|
||||||
properties list (wich means that the property is inverted)
|
properties list (wich means that the property is inverted)
|
||||||
|
|
||||||
- **transitive**: but what happens if the target option cannot be
|
- **transitive**: but what happens if the target option cannot be
|
||||||
accessed ? We don't kown the target option's value. Actually if some
|
accessed ? We don't kown the target option's value. Actually if some
|
||||||
property in the target option is not present in the permissive, the
|
property in the target option is not present in the permissive, the
|
||||||
target option's value cannot be accessed. In this case, the
|
target option's value cannot be accessed. In this case, the
|
||||||
**action** have to be applied to the option. (the **action** property
|
**action** have to be applied to the option. (the **action** property
|
||||||
is then added to the option).
|
is then added to the option).
|
||||||
|
|
||||||
- **same_action**: actually, if **same_action** is `True`, the
|
- **same_action**: actually, if **same_action** is `True`, the
|
||||||
transitivity is not accomplished. The transitivity is accomplished
|
transitivity is not accomplished. The transitivity is accomplished
|
||||||
only if the target option **has the same property** that the demanded
|
only if the target option **has the same property** that the demanded
|
||||||
action. If the target option's value is not accessible because of
|
action. If the target option's value is not accessible because of
|
||||||
another reason, because of a property of another type, then an
|
another reason, because of a property of another type, then an
|
||||||
exception :exc:`~error.RequirementError` is raised.
|
exception :exc:`~error.RequirementError` is raised.
|
||||||
|
|
||||||
And at last, if no target option matches the expected values, the
|
And at last, if no target option matches the expected values, the
|
||||||
action must be removed from the option's properties list.
|
action must be removed from the option's properties list.
|
||||||
|
|
||||||
:param opt: the option on wich the requirement occurs
|
:param opt: the option on wich the requirement occurs
|
||||||
:type opt: `option.Option()`
|
:type opt: `option.Option()`
|
||||||
:param path: the option's path in the config
|
:param path: the option's path in the config
|
||||||
:type path: str
|
:type path: str
|
||||||
"""
|
"""
|
||||||
if opt._requires is None:
|
if opt._requires is None:
|
||||||
return
|
return frozenset()
|
||||||
|
|
||||||
# filters the callbacks
|
# filters the callbacks
|
||||||
setting = Property(self,
|
calc_properties = set()
|
||||||
self._getproperties(opt, path, False),
|
|
||||||
opt, path=path)
|
|
||||||
for requires in opt._requires:
|
for requires in opt._requires:
|
||||||
matches = False
|
|
||||||
for require in requires:
|
for require in requires:
|
||||||
option, expected, action, inverse, \
|
option, expected, action, inverse, \
|
||||||
transitive, same_action = require
|
transitive, same_action = require
|
||||||
|
@ -460,13 +469,10 @@ class Settings(object):
|
||||||
if (not inverse and
|
if (not inverse and
|
||||||
value in expected or
|
value in expected or
|
||||||
inverse and value not in expected):
|
inverse and value not in expected):
|
||||||
matches = True
|
calc_properties.add(action)
|
||||||
setting.append(action)
|
|
||||||
# the calculation cannot be carried out
|
# the calculation cannot be carried out
|
||||||
break
|
break
|
||||||
# no requirement has been triggered, then just reverse the action
|
return calc_properties
|
||||||
if not matches:
|
|
||||||
setting.remove(action)
|
|
||||||
|
|
||||||
def _get_opt_path(self, opt):
|
def _get_opt_path(self, opt):
|
||||||
return self.context.cfgimpl_get_description().impl_get_path_by_opt(opt)
|
return self.context.cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||||
|
|
Loading…
Reference in New Issue