add warning ability
This commit is contained in:
parent
5ba97c5928
commit
06baff2f3b
|
@ -3,7 +3,6 @@ from py.test import raises
|
||||||
|
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from tiramisu.option import StrOption, OptionDescription
|
from tiramisu.option import StrOption, OptionDescription
|
||||||
from tiramisu.error import ConfigError
|
|
||||||
|
|
||||||
|
|
||||||
def return_true(value, param=None):
|
def return_true(value, param=None):
|
||||||
|
@ -13,37 +12,36 @@ def return_true(value, param=None):
|
||||||
|
|
||||||
def return_false(value, param=None):
|
def return_false(value, param=None):
|
||||||
if value == 'val' and param in [None, 'yes']:
|
if value == 'val' and param in [None, 'yes']:
|
||||||
return False
|
raise ValueError('error')
|
||||||
|
|
||||||
|
|
||||||
def return_val(value, param=None):
|
def return_val(value, param=None):
|
||||||
return 'val'
|
return 'val'
|
||||||
|
|
||||||
|
|
||||||
|
def return_if_val(value):
|
||||||
|
if value != 'val':
|
||||||
|
raise ValueError('error')
|
||||||
|
|
||||||
|
|
||||||
def test_validator():
|
def test_validator():
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, default='val')
|
opt1 = StrOption('opt1', '', validator=return_true, default='val')
|
||||||
raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')")
|
raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')")
|
||||||
raises(ConfigError, "StrOption('opt3', '', validator=return_val, default='val')")
|
|
||||||
opt2 = StrOption('opt2', '', validator=return_false)
|
opt2 = StrOption('opt2', '', validator=return_false)
|
||||||
opt3 = StrOption('opt3', '', validator=return_val)
|
root = OptionDescription('root', '', [opt1, opt2])
|
||||||
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
assert cfg.opt1 == 'val'
|
assert cfg.opt1 == 'val'
|
||||||
raises(ValueError, "cfg.opt2 = 'val'")
|
raises(ValueError, "cfg.opt2 = 'val'")
|
||||||
raises(ConfigError, "cfg.opt3 = 'val'")
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params():
|
def test_validator_params():
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, validator_params={'': ('yes',)}, default='val')
|
opt1 = StrOption('opt1', '', validator=return_true, validator_params={'': ('yes',)}, default='val')
|
||||||
raises(ValueError, "StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)}, default='val')")
|
raises(ValueError, "StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)}, default='val')")
|
||||||
raises(ConfigError, "StrOption('opt3', '', validator=return_val, validator_params={'': ('yes',)}, default='val')")
|
|
||||||
opt2 = StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)})
|
opt2 = StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)})
|
||||||
opt3 = StrOption('opt3', '', validator=return_val, validator_params={'': ('yes',)})
|
root = OptionDescription('root', '', [opt1, opt2])
|
||||||
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
assert cfg.opt1 == 'val'
|
assert cfg.opt1 == 'val'
|
||||||
raises(ValueError, "cfg.opt2 = 'val'")
|
raises(ValueError, "cfg.opt2 = 'val'")
|
||||||
raises(ConfigError, "cfg.opt3 = 'val'")
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_key():
|
def test_validator_params_key():
|
||||||
|
@ -57,3 +55,36 @@ def test_validator_params_key():
|
||||||
def test_validator_params_option():
|
def test_validator_params_option():
|
||||||
opt0 = StrOption('opt0', '', default='val')
|
opt0 = StrOption('opt0', '', default='val')
|
||||||
raises(ValueError, "opt1 = StrOption('opt1', '', validator=return_true, validator_params={'': ((opt0, False),)}, default='val')")
|
raises(ValueError, "opt1 = StrOption('opt1', '', validator=return_true, validator_params={'': ((opt0, False),)}, default='val')")
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_multi():
|
||||||
|
opt1 = StrOption('opt1', '', validator=return_if_val, multi=True)
|
||||||
|
root = OptionDescription('root', '', [opt1])
|
||||||
|
cfg = Config(root)
|
||||||
|
assert cfg.opt1 == []
|
||||||
|
cfg.opt1.append('val')
|
||||||
|
assert cfg.opt1 == ['val']
|
||||||
|
raises(ValueError, "cfg.opt1.append('val1')")
|
||||||
|
raises(ValueError, "cfg.opt1 = ['val', 'val1']")
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_warning():
|
||||||
|
opt1 = StrOption('opt1', '', validator=return_true, default='val', only_warning=True)
|
||||||
|
opt2 = StrOption('opt2', '', validator=return_false, only_warning=True)
|
||||||
|
opt3 = StrOption('opt3', '', validator=return_if_val, multi=True, only_warning=True)
|
||||||
|
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
||||||
|
cfg = Config(root)
|
||||||
|
assert cfg.opt1 == 'val'
|
||||||
|
cfg.opt1 = 'val'
|
||||||
|
assert cfg.cfgimpl_get_values().has_warning() is False
|
||||||
|
cfg.opt2 = 'val'
|
||||||
|
assert cfg.cfgimpl_get_values().has_warning() is True
|
||||||
|
assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val for option opt2: error'
|
||||||
|
assert cfg.cfgimpl_get_values().has_warning() is False
|
||||||
|
cfg.opt3.append('val')
|
||||||
|
assert cfg.cfgimpl_get_values().has_warning() is False
|
||||||
|
cfg.opt3.append('val1')
|
||||||
|
assert cfg.cfgimpl_get_values().has_warning() is True
|
||||||
|
assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val1 for option opt3: error'
|
||||||
|
assert cfg.cfgimpl_get_values().has_warning() is False
|
||||||
|
raises(ValueError, "cfg.opt2 = 1")
|
||||||
|
|
|
@ -26,7 +26,7 @@ from copy import copy, deepcopy
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from IPy import IP
|
from IPy import IP
|
||||||
|
|
||||||
from tiramisu.error import ConflictError, ConfigError
|
from tiramisu.error import ConflictError
|
||||||
from tiramisu.setting import groups, multitypes
|
from tiramisu.setting import groups, multitypes
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from tiramisu.autolib import carry_out_calculation
|
from tiramisu.autolib import carry_out_calculation
|
||||||
|
@ -327,13 +327,13 @@ class Option(BaseOption):
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_multi', '_validator', '_default_multi', '_default',
|
__slots__ = ('_multi', '_validator', '_default_multi', '_default',
|
||||||
'_state_callback', '_callback', '_multitype',
|
'_state_callback', '_callback', '_multitype',
|
||||||
'_master_slaves', '__weakref__')
|
'_only_warning', '_master_slaves', '__weakref__')
|
||||||
_empty = ''
|
_empty = ''
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None):
|
properties=None, only_warning=False):
|
||||||
"""
|
"""
|
||||||
:param name: the option's name
|
:param name: the option's name
|
||||||
:param doc: the option's description
|
:param doc: the option's description
|
||||||
|
@ -351,6 +351,8 @@ class Option(BaseOption):
|
||||||
validation of the value
|
validation of the value
|
||||||
:param validator_params: the validator's parameters
|
:param validator_params: the validator's parameters
|
||||||
:param properties: tuple of default properties
|
:param properties: tuple of default properties
|
||||||
|
:param only_warning: _validator and _consistencies don't raise if True
|
||||||
|
Values()._warning contain message
|
||||||
|
|
||||||
"""
|
"""
|
||||||
super(Option, self).__init__(name, doc, requires, properties)
|
super(Option, self).__init__(name, doc, requires, properties)
|
||||||
|
@ -388,6 +390,7 @@ class Option(BaseOption):
|
||||||
default = []
|
default = []
|
||||||
self._multitype = multitypes.default
|
self._multitype = multitypes.default
|
||||||
self._default_multi = default_multi
|
self._default_multi = default_multi
|
||||||
|
self._only_warning = only_warning
|
||||||
self.impl_validate(default)
|
self.impl_validate(default)
|
||||||
self._default = default
|
self._default = default
|
||||||
|
|
||||||
|
@ -436,10 +439,17 @@ class Option(BaseOption):
|
||||||
if None not in (values, values_):
|
if None not in (values, values_):
|
||||||
getattr(self, func)(opt_._name, values, values_)
|
getattr(self, func)(opt_._name, values, values_)
|
||||||
|
|
||||||
def impl_validate(self, value, context=None, validate=True):
|
def impl_validate(self, value, context=None, validate=True,
|
||||||
|
force_no_multi=False):
|
||||||
"""
|
"""
|
||||||
:param value: the option's value
|
:param value: the option's value
|
||||||
|
:param context: Config's context
|
||||||
|
:type context: :class:`tiramisu.config.Config`
|
||||||
:param validate: if true enables ``self._validator`` validation
|
:param validate: if true enables ``self._validator`` validation
|
||||||
|
:type validate: boolean
|
||||||
|
:param force_no_multi: if multi, value has to be a list
|
||||||
|
not if force_no_multi is True
|
||||||
|
:type force_no_multi: boolean
|
||||||
"""
|
"""
|
||||||
if not validate:
|
if not validate:
|
||||||
return
|
return
|
||||||
|
@ -456,46 +466,49 @@ class Option(BaseOption):
|
||||||
validator_params[''] = (val,)
|
validator_params[''] = (val,)
|
||||||
else:
|
else:
|
||||||
validator_params = {'': (val,)}
|
validator_params = {'': (val,)}
|
||||||
ret = carry_out_calculation(self._name, config=context,
|
# Raise ValueError if not valid
|
||||||
callback=self._validator[0],
|
carry_out_calculation(self._name, config=context,
|
||||||
callback_params=validator_params)
|
callback=self._validator[0],
|
||||||
if ret not in [False, True]:
|
callback_params=validator_params)
|
||||||
raise ConfigError(_('validator should return a boolean, '
|
|
||||||
'not {0}').format(ret))
|
|
||||||
return ret
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def do_validation(_value, _index=None):
|
def do_validation(_value, _index=None):
|
||||||
if _value is None:
|
if _value is None:
|
||||||
return True
|
return True
|
||||||
if not val_validator(_value):
|
ret_validation = None
|
||||||
raise ValueError(_("invalid value {0} "
|
|
||||||
"for option {1} for object {2}"
|
|
||||||
).format(_value,
|
|
||||||
self._name,
|
|
||||||
self.__class__.__name__))
|
|
||||||
try:
|
try:
|
||||||
self._validate(_value)
|
# valid with self._validator
|
||||||
|
val_validator(_value)
|
||||||
|
# if not context launch consistency validation
|
||||||
|
if context is not None:
|
||||||
|
descr._valid_consistency(self, _value, context, _index)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError(_("invalid value {0} for option {1}: {2}"
|
msg = _("invalid value {0} for option {1}: {2}").format(
|
||||||
"").format(_value, self._name, err))
|
_value, self._name, err)
|
||||||
if context is not None:
|
if self._only_warning:
|
||||||
descr._valid_consistency(self, _value, context, _index)
|
ret_validation = msg
|
||||||
|
else:
|
||||||
|
raise ValueError(msg)
|
||||||
|
# option validation
|
||||||
|
self._validate(_value)
|
||||||
|
return ret_validation
|
||||||
|
|
||||||
# generic calculation
|
# generic calculation
|
||||||
if context is not None:
|
if context is not None:
|
||||||
descr = context.cfgimpl_get_description()
|
descr = context.cfgimpl_get_description()
|
||||||
if not self._multi:
|
|
||||||
do_validation(value)
|
ret = None
|
||||||
|
if not self._multi or force_no_multi:
|
||||||
|
ret = do_validation(value)
|
||||||
else:
|
else:
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
raise ValueError(_("invalid value {0} for option {1} "
|
raise ValueError(_("invalid value {0} for option {1} "
|
||||||
"which must be a list").format(value,
|
"which must be a list").format(value,
|
||||||
self._name))
|
self._name))
|
||||||
for index in range(0, len(value)):
|
for index, val in enumerate(value):
|
||||||
val = value[index]
|
ret_ = do_validation(val, index)
|
||||||
do_validation(val, index)
|
if ret_ is not None:
|
||||||
|
ret = ret_
|
||||||
|
return ret
|
||||||
|
|
||||||
def impl_getdefault(self, default_multi=False):
|
def impl_getdefault(self, default_multi=False):
|
||||||
"accessing the default value"
|
"accessing the default value"
|
||||||
|
@ -610,7 +623,7 @@ class ChoiceOption(Option):
|
||||||
def __init__(self, name, doc, values, default=None, default_multi=None,
|
def __init__(self, name, doc, values, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, open_values=False, validator=None,
|
callback_params=None, open_values=False, validator=None,
|
||||||
validator_params=None, properties=()):
|
validator_params=None, properties=None, only_warning=False):
|
||||||
"""
|
"""
|
||||||
:param values: is a list of values the option can possibly take
|
:param values: is a list of values the option can possibly take
|
||||||
"""
|
"""
|
||||||
|
@ -629,7 +642,8 @@ class ChoiceOption(Option):
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_params=validator_params,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties,
|
||||||
|
only_warning=only_warning)
|
||||||
|
|
||||||
def impl_get_values(self):
|
def impl_get_values(self):
|
||||||
return self._values
|
return self._values
|
||||||
|
@ -747,7 +761,8 @@ class IPOption(Option):
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None, only_private=False, allow_reserved=False):
|
properties=None, only_private=False, allow_reserved=False,
|
||||||
|
only_warning=False):
|
||||||
self._only_private = only_private
|
self._only_private = only_private
|
||||||
self._allow_reserved = allow_reserved
|
self._allow_reserved = allow_reserved
|
||||||
super(IPOption, self).__init__(name, doc, default=default,
|
super(IPOption, self).__init__(name, doc, default=default,
|
||||||
|
@ -758,7 +773,8 @@ class IPOption(Option):
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_params=validator_params,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties,
|
||||||
|
only_warning=only_warning)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
ip = IP('{0}/32'.format(value))
|
ip = IP('{0}/32'.format(value))
|
||||||
|
@ -786,7 +802,7 @@ class PortOption(Option):
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None, allow_range=False, allow_zero=False,
|
properties=None, allow_range=False, allow_zero=False,
|
||||||
allow_wellknown=True, allow_registred=True,
|
allow_wellknown=True, allow_registred=True,
|
||||||
allow_private=False):
|
allow_private=False, only_warning=False):
|
||||||
self._allow_range = allow_range
|
self._allow_range = allow_range
|
||||||
self._min_value = None
|
self._min_value = None
|
||||||
self._max_value = None
|
self._max_value = None
|
||||||
|
@ -818,7 +834,8 @@ class PortOption(Option):
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_params=validator_params,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties,
|
||||||
|
only_warning=only_warning)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if self._allow_range and ":" in str(value):
|
if self._allow_range and ":" in str(value):
|
||||||
|
@ -864,7 +881,6 @@ class NetmaskOption(Option):
|
||||||
#opts must be (netmask, ip) options
|
#opts must be (netmask, ip) options
|
||||||
self.__cons_netmask(optname, value, value_, True)
|
self.__cons_netmask(optname, value, value_, True)
|
||||||
|
|
||||||
#def __cons_netmask(self, opt, value, context, index, opts, make_net):
|
|
||||||
def __cons_netmask(self, optname, val_netmask, val_ipnetwork, make_net):
|
def __cons_netmask(self, optname, val_netmask, val_ipnetwork, make_net):
|
||||||
msg = None
|
msg = None
|
||||||
try:
|
try:
|
||||||
|
@ -903,7 +919,8 @@ class DomainnameOption(Option):
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None, allow_ip=False, type_='domainname'):
|
properties=None, allow_ip=False, type_='domainname',
|
||||||
|
only_warning=False):
|
||||||
#netbios: for MS domain
|
#netbios: for MS domain
|
||||||
#hostname: to identify the device
|
#hostname: to identify the device
|
||||||
#domainname:
|
#domainname:
|
||||||
|
@ -922,7 +939,8 @@ class DomainnameOption(Option):
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_params=validator_params,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties,
|
||||||
|
only_warning=only_warning)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if self._allow_ip is True:
|
if self._allow_ip is True:
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Values(object):
|
||||||
but the values are physicaly located here, in `Values`, wich is also
|
but the values are physicaly located here, in `Values`, wich is also
|
||||||
responsible of a caching utility.
|
responsible of a caching utility.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('context', '_p_', '__weakref__')
|
__slots__ = ('context', '_warning', '_p_', '__weakref__')
|
||||||
|
|
||||||
def __init__(self, context, storage):
|
def __init__(self, context, storage):
|
||||||
"""
|
"""
|
||||||
|
@ -106,8 +106,9 @@ class Values(object):
|
||||||
path = self._get_opt_path(opt)
|
path = self._get_opt_path(opt)
|
||||||
if self._p_.hasvalue(path):
|
if self._p_.hasvalue(path):
|
||||||
setting = self.context().cfgimpl_get_settings()
|
setting = self.context().cfgimpl_get_settings()
|
||||||
opt.impl_validate(opt.impl_getdefault(), self.context(),
|
self._warning = opt.impl_validate(opt.impl_getdefault(),
|
||||||
'validator' in setting)
|
self.context(),
|
||||||
|
'validator' in setting)
|
||||||
self.context().cfgimpl_reset_cache()
|
self.context().cfgimpl_reset_cache()
|
||||||
if (opt.impl_is_multi() and
|
if (opt.impl_is_multi() and
|
||||||
opt.impl_get_multitype() == multitypes.master):
|
opt.impl_get_multitype() == multitypes.master):
|
||||||
|
@ -229,7 +230,8 @@ class Values(object):
|
||||||
else:
|
else:
|
||||||
value = self._getvalue(opt, path, validate)
|
value = self._getvalue(opt, path, validate)
|
||||||
if config_error is None and validate:
|
if config_error is None and validate:
|
||||||
opt.impl_validate(value, self.context(), 'validator' in setting)
|
self._warning = opt.impl_validate(value, self.context(),
|
||||||
|
'validator' in setting)
|
||||||
if config_error is None and self._is_default_owner(path) and \
|
if config_error is None and self._is_default_owner(path) and \
|
||||||
'force_store_value' in setting[opt]:
|
'force_store_value' in setting[opt]:
|
||||||
self.setitem(opt, value, path, is_write=False)
|
self.setitem(opt, value, path, is_write=False)
|
||||||
|
@ -250,8 +252,9 @@ class Values(object):
|
||||||
# is_write is, for example, used with "force_store_value"
|
# is_write is, for example, used with "force_store_value"
|
||||||
# user didn't change value, so not write
|
# user didn't change value, so not write
|
||||||
# valid opt
|
# valid opt
|
||||||
opt.impl_validate(value, self.context(),
|
self._warning = opt.impl_validate(value, self.context(),
|
||||||
'validator' in self.context().cfgimpl_get_settings())
|
'validator' in self.context(
|
||||||
|
).cfgimpl_get_settings())
|
||||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||||
value = Multi(value, self.context, opt, path, setitem=True)
|
value = Multi(value, self.context, opt, path, setitem=True)
|
||||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||||
|
@ -370,6 +373,22 @@ class Values(object):
|
||||||
def __setstate__(self, states):
|
def __setstate__(self, states):
|
||||||
self._p_ = states['_p_']
|
self._p_ = states['_p_']
|
||||||
|
|
||||||
|
def has_warning(self):
|
||||||
|
"""If option is "only_warning", validation error is store in
|
||||||
|
self._warning.
|
||||||
|
has_warning just indicate that a warning message is store
|
||||||
|
"""
|
||||||
|
return self._warning is not None
|
||||||
|
|
||||||
|
def get_last_warning(self):
|
||||||
|
"""Get last warning message in self._warning.
|
||||||
|
We can get only one time this message.
|
||||||
|
"""
|
||||||
|
ret = self._warning
|
||||||
|
self._warning = None
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# multi types
|
# multi types
|
||||||
|
|
||||||
|
@ -476,7 +495,9 @@ class Multi(list):
|
||||||
value = None
|
value = None
|
||||||
self._validate(value)
|
self._validate(value)
|
||||||
super(Multi, self).append(value)
|
super(Multi, self).append(value)
|
||||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
|
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||||
|
self,
|
||||||
|
validate_properties=not force)
|
||||||
if not force and self.opt.impl_get_multitype() == multitypes.master:
|
if not force and self.opt.impl_get_multitype() == multitypes.master:
|
||||||
for slave in self.opt.impl_get_master_slaves():
|
for slave in self.opt.impl_get_master_slaves():
|
||||||
path = values._get_opt_path(slave)
|
path = values._get_opt_path(slave)
|
||||||
|
@ -537,7 +558,9 @@ class Multi(list):
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
try:
|
try:
|
||||||
self.opt._validate(value)
|
self.context().cfgimpl_get_values()._warning = \
|
||||||
|
self.opt.impl_validate(value, context=self.context(),
|
||||||
|
force_no_multi=True)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError(_("invalid value {0} "
|
raise ValueError(_("invalid value {0} "
|
||||||
"for option {1}: {2}"
|
"for option {1}: {2}"
|
||||||
|
|
Loading…
Reference in New Issue