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>
|
Sun Oct 26 08:50:38 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
|
||||||
* if option is frozen with force_default_on_freeze property, owner
|
* if option is frozen with force_default_on_freeze property, owner
|
||||||
must be 'default' check property when tried to change 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.config import Config
|
||||||
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
|
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
|
||||||
BroadcastOption, SymLinkOption, OptionDescription
|
BroadcastOption, SymLinkOption, OptionDescription
|
||||||
from tiramisu.error import ConfigError, ValueWarning
|
from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +27,13 @@ def test_consistency_not_exists():
|
||||||
raises(ConfigError, "a.impl_add_consistency('not_exists', b)")
|
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():
|
def test_consistency_warnings_only():
|
||||||
a = IntOption('a', '')
|
a = IntOption('a', '')
|
||||||
b = IntOption('b', '')
|
b = IntOption('b', '')
|
||||||
|
@ -392,6 +399,26 @@ def test_consistency_permissive():
|
||||||
c.a = 1
|
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):
|
def return_val(*args, **kwargs):
|
||||||
return '192.168.1.1'
|
return '192.168.1.1'
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import warnings
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from tiramisu.setting import log, undefined
|
from tiramisu.setting import log, undefined
|
||||||
from tiramisu.autolib import carry_out_calculation
|
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
|
from tiramisu.storage import get_storages_option
|
||||||
|
|
||||||
|
|
||||||
|
@ -403,7 +403,8 @@ class Option(OnlyOption):
|
||||||
_empty = ''
|
_empty = ''
|
||||||
|
|
||||||
def _launch_consistency(self, func, option, value, context, index,
|
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
|
"""Launch consistency now
|
||||||
|
|
||||||
:param func: function name, this name should start with _cons_
|
: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`
|
:type all_cons_opts: `list` of `tiramisu.option.Option`
|
||||||
:param warnings_only: specific raise error for warning
|
:param warnings_only: specific raise error for warning
|
||||||
:type warnings_only: `boolean`
|
:type warnings_only: `boolean`
|
||||||
|
:param transitive: propertyerror is transitive
|
||||||
|
:type transitive: `boolean`
|
||||||
"""
|
"""
|
||||||
if context is not undefined:
|
if context is not undefined:
|
||||||
descr = context.cfgimpl_get_description()
|
descr = context.cfgimpl_get_description()
|
||||||
|
|
||||||
all_cons_vals = []
|
all_cons_vals = []
|
||||||
for opt in all_cons_opts:
|
for opt in all_cons_opts:
|
||||||
#get value
|
try:
|
||||||
if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
|
#get value
|
||||||
option == opt:
|
if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
|
||||||
opt_value = value
|
option == opt:
|
||||||
else:
|
opt_value = value
|
||||||
#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:
|
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
|
#append value
|
||||||
if not self.impl_is_multi() or (isinstance(opt, DynSymLinkOption)
|
if not self.impl_is_multi() or (isinstance(opt, DynSymLinkOption)
|
||||||
and option._dyn == opt._dyn) or \
|
and option._dyn == opt._dyn) or \
|
||||||
option == opt:
|
option == opt:
|
||||||
all_cons_vals.append(opt_value)
|
all_cons_vals.append(opt_value)
|
||||||
elif self.impl_is_submulti():
|
elif self.impl_is_submulti():
|
||||||
try:
|
try:
|
||||||
all_cons_vals.append(opt_value[index][submulti_index])
|
all_cons_vals.append(opt_value[index][submulti_index])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
#value is not already set, could be higher index
|
#value is not already set, could be higher index
|
||||||
#so return if no value
|
#so return if no value
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
all_cons_vals.append(opt_value[index])
|
all_cons_vals.append(opt_value[index])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
#value is not already set, could be higher index
|
#value is not already set, could be higher index
|
||||||
#so return if no value
|
#so return if no value
|
||||||
return
|
return
|
||||||
|
except PropertiesOptionError as err:
|
||||||
|
if transitive:
|
||||||
|
raise err
|
||||||
|
else:
|
||||||
|
pass
|
||||||
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
|
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
|
||||||
|
|
||||||
def impl_validate(self, value, context=undefined, validate=True,
|
def impl_validate(self, value, context=undefined, validate=True,
|
||||||
|
@ -636,14 +645,22 @@ class Option(OnlyOption):
|
||||||
:type func: `str`
|
:type func: `str`
|
||||||
:param other_opts: options used to validate value
|
:param other_opts: options used to validate value
|
||||||
:type other_opts: `list` of `tiramisu.option.Option`
|
: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
|
if self.impl_is_readonly(): # pragma: optional cover
|
||||||
raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
|
raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
|
||||||
" read-only").format(
|
" read-only").format(
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
self.impl_getname()))
|
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():
|
if self._is_subdyn():
|
||||||
dynod = self._impl_getsubdyn()
|
dynod = self._impl_getsubdyn()
|
||||||
else:
|
else:
|
||||||
|
@ -678,16 +695,17 @@ class Option(OnlyOption):
|
||||||
if not self.impl_is_submulti():
|
if not self.impl_is_submulti():
|
||||||
self._launch_consistency(func, self, val, undefined, idx,
|
self._launch_consistency(func, self, val, undefined, idx,
|
||||||
None, all_cons_opts,
|
None, all_cons_opts,
|
||||||
warnings_only)
|
warnings_only, transitive)
|
||||||
else:
|
else:
|
||||||
for slave_idx, val in enumerate(value):
|
for slave_idx, val in enumerate(value):
|
||||||
self._launch_consistency(func, self, val, None,
|
self._launch_consistency(func, self, val, None,
|
||||||
idx, slave_idx,
|
idx, slave_idx,
|
||||||
all_cons_opts,
|
all_cons_opts,
|
||||||
warnings_only)
|
warnings_only, transitive)
|
||||||
else:
|
else:
|
||||||
self._launch_consistency(func, self, value, undefined, None,
|
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._add_consistency(func, all_cons_opts, params)
|
||||||
self.impl_validate(self.impl_getdefault())
|
self.impl_validate(self.impl_getdefault())
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
if consistencies is not None:
|
if consistencies is not None:
|
||||||
for func, all_cons_opts, params in consistencies:
|
for func, all_cons_opts, params in consistencies:
|
||||||
warnings_only = params.get('warnings_only', False)
|
warnings_only = params.get('warnings_only', False)
|
||||||
|
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
|
||||||
if isinstance(option, DynSymLinkOption):
|
if isinstance(option, DynSymLinkOption):
|
||||||
subpath = '.'.join(option._dyn.split('.')[:-1])
|
subpath = '.'.join(option._dyn.split('.')[:-1])
|
||||||
|
@ -190,7 +191,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
try:
|
try:
|
||||||
opts[0]._launch_consistency(func, option, value, context,
|
opts[0]._launch_consistency(func, option, value, context,
|
||||||
index, submulti_idx, opts,
|
index, submulti_idx, opts,
|
||||||
warnings_only)
|
warnings_only, transitive)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
raise ValueWarning(err.message, option)
|
raise ValueWarning(err.message, option)
|
||||||
|
|
Loading…
Reference in a new issue