propertyerror are transitive in consistency, now it's possible to set non-transitive consistency
This commit is contained in:
parent
2ccf92f879
commit
7646071efd
4 changed files with 92 additions and 42 deletions
|
@ -1,3 +1,7 @@
|
|||
Mon Dec 1 22:58:13 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
|
||||
* propertyerror are transitive in consistency, now it's possible to set
|
||||
non-transitive consistency
|
||||
|
||||
Sun Oct 26 08:50:38 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
|
||||
* if option is frozen with force_default_on_freeze property, owner
|
||||
must be 'default' check property when tried to change owner
|
||||
|
|
|
@ -5,7 +5,7 @@ from tiramisu.setting import owners, groups
|
|||
from tiramisu.config import Config
|
||||
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
|
||||
BroadcastOption, SymLinkOption, OptionDescription
|
||||
from tiramisu.error import ConfigError, ValueWarning
|
||||
from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError
|
||||
import warnings
|
||||
|
||||
|
||||
|
@ -27,6 +27,13 @@ def test_consistency_not_exists():
|
|||
raises(ConfigError, "a.impl_add_consistency('not_exists', b)")
|
||||
|
||||
|
||||
def test_consistency_unknown_params():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '')
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
raises(ValueError, "a.impl_add_consistency('not_equal', b, unknown=False)")
|
||||
|
||||
|
||||
def test_consistency_warnings_only():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '')
|
||||
|
@ -392,6 +399,26 @@ def test_consistency_permissive():
|
|||
c.a = 1
|
||||
|
||||
|
||||
def test_consistency_disabled():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '', properties=('disabled',))
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
a.impl_add_consistency('not_equal', b)
|
||||
c = Config(od)
|
||||
c.read_write()
|
||||
raises(PropertiesOptionError, "c.a = 1")
|
||||
|
||||
|
||||
def test_consistency_disabled_transitive():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '', properties=('disabled',))
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
a.impl_add_consistency('not_equal', b, transitive=False)
|
||||
c = Config(od)
|
||||
c.read_write()
|
||||
c.a = 1
|
||||
|
||||
|
||||
def return_val(*args, **kwargs):
|
||||
return '192.168.1.1'
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import warnings
|
|||
from tiramisu.i18n import _
|
||||
from tiramisu.setting import log, undefined
|
||||
from tiramisu.autolib import carry_out_calculation
|
||||
from tiramisu.error import ConfigError, ValueWarning
|
||||
from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError
|
||||
from tiramisu.storage import get_storages_option
|
||||
|
||||
|
||||
|
@ -403,7 +403,8 @@ class Option(OnlyOption):
|
|||
_empty = ''
|
||||
|
||||
def _launch_consistency(self, func, option, value, context, index,
|
||||
submulti_index, all_cons_opts, warnings_only):
|
||||
submulti_index, all_cons_opts, warnings_only,
|
||||
transitive):
|
||||
"""Launch consistency now
|
||||
|
||||
:param func: function name, this name should start with _cons_
|
||||
|
@ -420,47 +421,55 @@ class Option(OnlyOption):
|
|||
:type all_cons_opts: `list` of `tiramisu.option.Option`
|
||||
:param warnings_only: specific raise error for warning
|
||||
:type warnings_only: `boolean`
|
||||
:param transitive: propertyerror is transitive
|
||||
:type transitive: `boolean`
|
||||
"""
|
||||
if context is not undefined:
|
||||
descr = context.cfgimpl_get_description()
|
||||
|
||||
all_cons_vals = []
|
||||
for opt in all_cons_opts:
|
||||
#get value
|
||||
if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
|
||||
option == opt:
|
||||
opt_value = value
|
||||
else:
|
||||
#if context, calculate value, otherwise get default value
|
||||
if context is not undefined:
|
||||
if isinstance(opt, DynSymLinkOption):
|
||||
path = opt.impl_getpath(context)
|
||||
else:
|
||||
path = descr.impl_get_path_by_opt(opt)
|
||||
opt_value = context.getattr(path, validate=False,
|
||||
force_permissive=True)
|
||||
try:
|
||||
#get value
|
||||
if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
|
||||
option == opt:
|
||||
opt_value = value
|
||||
else:
|
||||
opt_value = opt.impl_getdefault()
|
||||
#if context, calculate value, otherwise get default value
|
||||
if context is not undefined:
|
||||
if isinstance(opt, DynSymLinkOption):
|
||||
path = opt.impl_getpath(context)
|
||||
else:
|
||||
path = descr.impl_get_path_by_opt(opt)
|
||||
opt_value = context.getattr(path, validate=False,
|
||||
force_permissive=True)
|
||||
else:
|
||||
opt_value = opt.impl_getdefault()
|
||||
|
||||
#append value
|
||||
if not self.impl_is_multi() or (isinstance(opt, DynSymLinkOption)
|
||||
and option._dyn == opt._dyn) or \
|
||||
option == opt:
|
||||
all_cons_vals.append(opt_value)
|
||||
elif self.impl_is_submulti():
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index][submulti_index])
|
||||
except IndexError:
|
||||
#value is not already set, could be higher index
|
||||
#so return if no value
|
||||
return
|
||||
else:
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index])
|
||||
except IndexError:
|
||||
#value is not already set, could be higher index
|
||||
#so return if no value
|
||||
return
|
||||
#append value
|
||||
if not self.impl_is_multi() or (isinstance(opt, DynSymLinkOption)
|
||||
and option._dyn == opt._dyn) or \
|
||||
option == opt:
|
||||
all_cons_vals.append(opt_value)
|
||||
elif self.impl_is_submulti():
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index][submulti_index])
|
||||
except IndexError:
|
||||
#value is not already set, could be higher index
|
||||
#so return if no value
|
||||
return
|
||||
else:
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index])
|
||||
except IndexError:
|
||||
#value is not already set, could be higher index
|
||||
#so return if no value
|
||||
return
|
||||
except PropertiesOptionError as err:
|
||||
if transitive:
|
||||
raise err
|
||||
else:
|
||||
pass
|
||||
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
|
||||
|
||||
def impl_validate(self, value, context=undefined, validate=True,
|
||||
|
@ -636,14 +645,22 @@ class Option(OnlyOption):
|
|||
:type func: `str`
|
||||
:param other_opts: options used to validate value
|
||||
:type other_opts: `list` of `tiramisu.option.Option`
|
||||
:param params: extra params (only warnings_only are allowed)
|
||||
:param params: extra params (warnings_only and transitive are allowed)
|
||||
"""
|
||||
if self.impl_is_readonly(): # pragma: optional cover
|
||||
raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
|
||||
" read-only").format(
|
||||
self.__class__.__name__,
|
||||
self.impl_getname()))
|
||||
warnings_only = params.get('warnings_only', False)
|
||||
warnings_only = False
|
||||
transitive = True
|
||||
for key, value in params.items():
|
||||
if key == 'warnings_only':
|
||||
warnings_only = value
|
||||
elif key == 'transitive':
|
||||
transitive = value
|
||||
else:
|
||||
raise ValueError(_('unknow parameter {0} in consistency').format(key))
|
||||
if self._is_subdyn():
|
||||
dynod = self._impl_getsubdyn()
|
||||
else:
|
||||
|
@ -678,16 +695,17 @@ class Option(OnlyOption):
|
|||
if not self.impl_is_submulti():
|
||||
self._launch_consistency(func, self, val, undefined, idx,
|
||||
None, all_cons_opts,
|
||||
warnings_only)
|
||||
warnings_only, transitive)
|
||||
else:
|
||||
for slave_idx, val in enumerate(value):
|
||||
self._launch_consistency(func, self, val, None,
|
||||
idx, slave_idx,
|
||||
all_cons_opts,
|
||||
warnings_only)
|
||||
warnings_only, transitive)
|
||||
else:
|
||||
self._launch_consistency(func, self, value, undefined, None,
|
||||
None, all_cons_opts, warnings_only)
|
||||
None, all_cons_opts, warnings_only,
|
||||
transitive)
|
||||
self._add_consistency(func, all_cons_opts, params)
|
||||
self.impl_validate(self.impl_getdefault())
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
|||
if consistencies is not None:
|
||||
for func, all_cons_opts, params in consistencies:
|
||||
warnings_only = params.get('warnings_only', False)
|
||||
transitive = params.get('transitive', True)
|
||||
#all_cons_opts[0] is the option where func is set
|
||||
if isinstance(option, DynSymLinkOption):
|
||||
subpath = '.'.join(option._dyn.split('.')[:-1])
|
||||
|
@ -190,7 +191,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
|||
try:
|
||||
opts[0]._launch_consistency(func, option, value, context,
|
||||
index, submulti_idx, opts,
|
||||
warnings_only)
|
||||
warnings_only, transitive)
|
||||
except ValueError as err:
|
||||
if warnings_only:
|
||||
raise ValueWarning(err.message, option)
|
||||
|
|
Loading…
Reference in a new issue