remove some try/except + consistency not works with submulti

This commit is contained in:
Emmanuel Garette 2016-01-03 13:23:15 +01:00
parent cc6b4ad7c4
commit e8764f6173
13 changed files with 273 additions and 259 deletions

View File

@ -720,38 +720,6 @@ def test_consistency_dyndescription_default():
raises(ValueError, "cfg.od.dodval2.st2val2 = 'yes'") raises(ValueError, "cfg.od.dodval2.st2val2 = 'yes'")
def test_consistency_dyndescription_multi():
st = StrOption('st', '', multi=True)
st2 = StrOption('st2', '', multi=True)
dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
od = OptionDescription('od', '', [dod])
st.impl_add_consistency('not_equal', st2)
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
cfg.od.dodval1.stval1.append('yes')
raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
cfg.od.dodval2.stval2.append('yes')
raises(ValueError, "cfg.od.dodval2.st2val2.append('yes')")
raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
del(cfg.od.dodval2.stval2)
raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
cfg.od.dodval2.st2val2.append('yes')
raises(ValueError, "cfg.od.dodval2.stval2.append('yes')")
def test_consistency_dyndescription_default_multi():
st = StrOption('st', '', ['yes'], multi=True)
st2 = StrOption('st2', '', multi=True)
dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
od = OptionDescription('od', '', [dod])
st.impl_add_consistency('not_equal', st2)
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
cfg.od.dodval1.stval1.append('yes')
def test_consistency_dyndescription_default_multi2(): def test_consistency_dyndescription_default_multi2():
st = StrOption('st', '', ['yes'], multi=True) st = StrOption('st', '', ['yes'], multi=True)
st2 = StrOption('st2', '', ['yes'], multi=True) st2 = StrOption('st2', '', ['yes'], multi=True)

View File

@ -291,6 +291,25 @@ def test_meta_master_slaves_value():
assert meta.conf1.netmask_admin_eth0 == [None] assert meta.conf1.netmask_admin_eth0 == [None]
def test_meta_master_slaves_value_default():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "mask", multi=True)
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.impl_set_group_type(groups.master)
conf1 = Config(interface1, name='conf1')
conf2 = Config(interface1, name='conf2')
meta = MetaConfig([conf1, conf2])
assert meta.conf1.netmask_admin_eth0 == [None]
meta.ip_admin_eth0 = ['192.168.1.1']
assert meta.conf1.netmask_admin_eth0 == [None]
meta.netmask_admin_eth0 = ['255.255.255.0']
assert meta.conf1.netmask_admin_eth0 == ['255.255.255.0']
meta.netmask_admin_eth0 = ['255.255.0.0']
assert meta.conf1.netmask_admin_eth0 == ['255.255.0.0']
meta.conf1.ip_admin_eth0 = ['192.168.1.1']
assert meta.conf1.netmask_admin_eth0 == [None]
def test_meta_master_slaves_owners(): def test_meta_master_slaves_owners():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "mask", multi=True, properties=('hidden',)) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "mask", multi=True, properties=('hidden',))

View File

@ -17,8 +17,6 @@ def test_consistency():
a.impl_add_consistency('not_equal', b) a.impl_add_consistency('not_equal', b)
#consistency to itself #consistency to itself
raises(ConfigError, "a.impl_add_consistency('not_equal', a)") raises(ConfigError, "a.impl_add_consistency('not_equal', a)")
#consistency with string
raises(ConfigError, "a.impl_add_consistency('not_equal', 'a')")
def test_consistency_not_exists(): def test_consistency_not_exists():
@ -157,21 +155,9 @@ def test_consistency_not_equal_symlink():
def test_consistency_not_equal_submulti(): def test_consistency_not_equal_submulti():
a = IntOption('a', '', multi=submulti) a = IntOption('a', '', multi=submulti)
b = IntOption('b', '', multi=submulti) b = IntOption('b', '', multi=submulti)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('a', '', [a, b])
a.impl_add_consistency('not_equal', b) od.impl_set_group_type(groups.master)
c = Config(od) raises(ConfigError, 'a.impl_add_consistency("not_equal", b)')
assert c.a == []
assert c.b == []
c.a = [[1]]
del(c.a)
c.a = [[1]]
raises(ValueError, "c.b = [[1]]")
c.a = [[1, 2]]
c.b = [[3]]
c.b = [[3, 1]]
c.b = [[3]]
c.b[0].append(1)
c.b = [[3], [1]]
def test_consistency_not_equal_default_submulti(): def test_consistency_not_equal_default_submulti():
@ -179,13 +165,14 @@ def test_consistency_not_equal_default_submulti():
b = IntOption('b', '', [[1]], multi=submulti) b = IntOption('b', '', [[1]], multi=submulti)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('od', '', [a, b])
od od
raises(ValueError, "a.impl_add_consistency('not_equal', b)") raises(ConfigError, "a.impl_add_consistency('not_equal', b)")
def test_consistency_not_equal_multi(): def test_consistency_not_equal_multi():
a = IntOption('a', '', multi=True) a = IntOption('a', '', multi=True)
b = IntOption('b', '', multi=True) b = IntOption('b', '', multi=True)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('a', '', [a, b])
od.impl_set_group_type(groups.master)
a.impl_add_consistency('not_equal', b) a.impl_add_consistency('not_equal', b)
c = Config(od) c = Config(od)
assert c.a == [] assert c.a == []
@ -200,16 +187,15 @@ def test_consistency_not_equal_multi():
def test_consistency_not_equal_multi_default(): def test_consistency_not_equal_multi_default():
a = IntOption('a', '', multi=True) a = IntOption('a', '', multi=True)
b = IntOption('b', '', multi=True, default_multi=1) b = IntOption('b', '', multi=True, default_multi=1)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('a', '', [a, b])
od.impl_set_group_type(groups.master)
a.impl_add_consistency('not_equal', b) a.impl_add_consistency('not_equal', b)
c = Config(od) c = Config(od)
assert c.a == [] assert c.a == []
assert c.b == [] assert c.b == []
c.a = [1] raises(ValueError, 'c.a = [1]')
c.a = [2]
del(c.a) del(c.a)
c.a = [1]
raises(ValueError, "c.b = [1]")
c.b = [2]
def test_consistency_default(): def test_consistency_default():
@ -325,8 +311,9 @@ def test_consistency_ip_netmask_error_multi():
def test_consistency_ip_netmask_multi(): def test_consistency_ip_netmask_multi():
a = IPOption('a', '', multi=True) a = IPOption('a', '', multi=True)
b = NetmaskOption('b', '', multi=True) b = NetmaskOption('b', '', multi=True)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('a', '', [a, b])
b.impl_add_consistency('ip_netmask', a) b.impl_add_consistency('ip_netmask', a)
od.impl_set_group_type(groups.master)
c = Config(od) c = Config(od)
c.a = ['192.168.1.1'] c.a = ['192.168.1.1']
c.b = ['255.255.255.0'] c.b = ['255.255.255.0']
@ -339,7 +326,8 @@ def test_consistency_ip_netmask_multi():
def test_consistency_network_netmask_multi(): def test_consistency_network_netmask_multi():
a = NetworkOption('a', '', multi=True) a = NetworkOption('a', '', multi=True)
b = NetmaskOption('b', '', multi=True) b = NetmaskOption('b', '', multi=True)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('a', '', [a, b])
od.impl_set_group_type(groups.master)
b.impl_add_consistency('network_netmask', a) b.impl_add_consistency('network_netmask', a)
c = Config(od) c = Config(od)
c.a = ['192.168.1.1'] c.a = ['192.168.1.1']

View File

@ -14,12 +14,12 @@ from tiramisu.i18n import _
def return_true(value, param=None): def return_true(value, param=None):
if value == 'val' and param in [None, 'yes']: if value == 'val' and param in [None, 'yes']:
return True return True
raise ValueError('error') return ValueError('error')
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']:
raise ValueError('error') return ValueError('error')
def return_val(value, param=None): def return_val(value, param=None):
@ -28,7 +28,7 @@ def return_val(value, param=None):
def return_if_val(value): def return_if_val(value):
if value != 'val': if value != 'val':
raise ValueError('error') return ValueError('error')
def test_validator(): def test_validator():

View File

@ -18,8 +18,7 @@
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
"enables us to carry out a calculation and return an option's value" "enables us to carry out a calculation and return an option's value"
from .error import PropertiesOptionError, ConfigError, ContextError, \ from .error import PropertiesOptionError, ConfigError, SlaveError
SlaveError
from .i18n import _ from .i18n import _
from .setting import undefined from .setting import undefined
# ____________________________________________________________ # ____________________________________________________________
@ -145,7 +144,7 @@ def carry_out_calculation(option, context, callback, callback_params,
for callbk in callbacks: for callbk in callbacks:
if isinstance(callbk, tuple): if isinstance(callbk, tuple):
if context is undefined: if context is undefined:
raise ContextError() # pragma: optional cover return undefined
if callbk[0] is None: # pragma: optional cover if callbk[0] is None: # pragma: optional cover
#Not an option, set full context #Not an option, set full context
tcparams.setdefault(key, []).append((context, False)) tcparams.setdefault(key, []).append((context, False))

View File

@ -34,12 +34,6 @@ class ConfigError(Exception):
pass pass
class ContextError(Exception):
"""context needed but not given
"""
pass
class ConflictError(Exception): class ConflictError(Exception):
"duplicate options are present in a single config" "duplicate options are present in a single config"
pass pass

View File

@ -25,8 +25,7 @@ import warnings
from ..i18n import _ from ..i18n import _
from ..setting import log, undefined from ..setting import log, undefined
from ..autolib import carry_out_calculation from ..autolib import carry_out_calculation
from ..error import ConfigError, ValueWarning, PropertiesOptionError,\ from ..error import ConfigError, ValueWarning, PropertiesOptionError
ContextError
from ..storage import get_storages_option from ..storage import get_storages_option
@ -142,10 +141,9 @@ class Base(StorageBase):
allow_empty_list) allow_empty_list)
if multi is not False and default is None: if multi is not False and default is None:
default = [] default = []
try: err = self.impl_validate(default, is_multi=is_multi)
self.impl_validate(default, is_multi=is_multi) if err:
except ContextError: raise err
pass
self._set_default_values(default, default_multi, is_multi) self._set_default_values(default, default_multi, is_multi)
##callback is False in optiondescription ##callback is False in optiondescription
if callback is not False: if callback is not False:
@ -347,7 +345,7 @@ class BaseOption(Base):
def _impl_valid_unicode(self, value): def _impl_valid_unicode(self, value):
if not isinstance(value, unicode) and not isinstance(value, str): if not isinstance(value, unicode) and not isinstance(value, str):
raise ValueError(_('invalid unicode or string')) return ValueError(_('invalid unicode or string'))
class OnlyOption(BaseOption): class OnlyOption(BaseOption):
@ -413,21 +411,17 @@ class Option(OnlyOption):
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():
print option._name, opt_value
all_cons_vals.append(opt_value[index][submulti_index]) all_cons_vals.append(opt_value[index][submulti_index])
else: else:
all_cons_vals.append(opt_value[index]) all_cons_vals.append(opt_value[index])
except IndexError, err:
#value is not already set, could be higher index
#so return if no value and not default_value
log.debug('indexerror in _launch_consistency: {0}'.format(err))
return
except PropertiesOptionError as err: except PropertiesOptionError as err:
log.debug('propertyerror in _launch_consistency: {0}'.format(err)) log.debug('propertyerror in _launch_consistency: {0}'.format(err))
if transitive: if transitive:
raise err raise err
else: else:
return return
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only) return 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,
force_index=None, force_submulti_index=None, force_index=None, force_submulti_index=None,
@ -467,52 +461,44 @@ class Option(OnlyOption):
else: else:
validator_params_ = {'': (val,)} validator_params_ = {'': (val,)}
# Raise ValueError if not valid # Raise ValueError if not valid
try: value = carry_out_calculation(current_opt, context=context,
carry_out_calculation(current_opt, context=context,
callback=validator, callback=validator,
callback_params=validator_params_) callback_params=validator_params_)
except ContextError: if isinstance(value, Exception):
pass return value
def do_validation(_value, _index, submulti_index): def do_validation(_value, _index, submulti_index):
if _value is None: if _value is None:
return return
# option validation # option validation
try: err = self._validate(_value, context, current_opt)
self._validate(_value, context, current_opt) if err:
except ValueError as err: # pragma: optional cover
log.debug('do_validation: value: {0}, index: {1}, ' log.debug('do_validation: value: {0}, index: {1}, '
'submulti_index: {2}'.format(_value, _index, 'submulti_index: {2}'.format(_value, _index,
submulti_index), submulti_index),
exc_info=True) exc_info=True)
raise ValueError(_('invalid value for option {0}: {1}' return ValueError(_('invalid value for option {0}: {1}'
'').format(self.impl_getname(), err)) '').format(self.impl_getname(), err))
error = None
warning = None warning = None
try: error = calculation_validator(_value)
# valid with self._validator if not error:
calculation_validator(_value) error = self._second_level_validation(_value, self._is_warnings_only())
self._second_level_validation(_value, self._is_warnings_only()) if error:
except ValueError as error:
log.debug(_('do_validation for {0}: error in value').format( log.debug(_('do_validation for {0}: error in value').format(
self.impl_getname()), exc_info=True) self.impl_getname()), exc_info=True)
if self._is_warnings_only(): if self._is_warnings_only():
warning = error warning = error
error = None error = None
if error is None and warning is None: if error is None and warning is None:
try:
# if context launch consistency validation # if context launch consistency validation
#if context is not undefined: #if context is not undefined:
self._valid_consistency(current_opt, _value, context, ret = self._valid_consistency(current_opt, _value, context,
_index, submulti_index) _index, submulti_index)
except ValueError as error: if ret:
log.debug(_('do_validation for {0}: error in consistency').format( if isinstance(ret, ValueWarning):
self.impl_getname()), exc_info=True) warning = ret
pass elif isinstance(ret, ValueError):
except ValueWarning as warning: error = ret
log.debug(_('do_validation for {0}: warning in consistency').format(
self.impl_getname()), exc_info=True)
pass
if warning: if warning:
msg = _("warning on the value of the option {0}: {1}").format( msg = _("warning on the value of the option {0}: {1}").format(
self.impl_getname(), warning) self.impl_getname(), warning)
@ -522,7 +508,7 @@ class Option(OnlyOption):
ValueWarning, ValueWarning,
self.__class__.__name__, 0) self.__class__.__name__, 0)
elif error: elif error:
raise ValueError(_("invalid value for option {0}: {1}").format( return ValueError(_("invalid value for option {0}: {1}").format(
self.impl_getname(), error)) self.impl_getname(), error))
# generic calculation # generic calculation
@ -532,7 +518,7 @@ class Option(OnlyOption):
if is_multi is None: if is_multi is None:
is_multi = self.impl_is_multi() is_multi = self.impl_is_multi()
if not is_multi: if not is_multi:
do_validation(value, None, None) return do_validation(value, None, None)
elif force_index is not None: elif force_index is not None:
if self.impl_is_submulti() and force_submulti_index is None: if self.impl_is_submulti() and force_submulti_index is None:
if not isinstance(value, list): # pragma: optional cover if not isinstance(value, list): # pragma: optional cover
@ -540,25 +526,31 @@ class Option(OnlyOption):
" must be a list").format( " must be a list").format(
value, self.impl_getname())) value, self.impl_getname()))
for idx, val in enumerate(value): for idx, val in enumerate(value):
do_validation(val, force_index, idx) err = do_validation(val, force_index, idx)
if err:
return err
else: else:
do_validation(value, force_index, force_submulti_index) return do_validation(value, force_index, force_submulti_index)
else: elif not isinstance(value, list): # pragma: optional cover
if not isinstance(value, list): # pragma: optional cover return ValueError(_("invalid value {0} for option {1} which "
raise ValueError(_("invalid value {0} for option {1} which "
"must be a list").format(value, "must be a list").format(value,
self.impl_getname())) self.impl_getname()))
elif self.impl_is_submulti() and force_submulti_index is None:
for idx, val in enumerate(value): for idx, val in enumerate(value):
if self.impl_is_submulti() and force_submulti_index is None:
if not isinstance(val, list): # pragma: optional cover if not isinstance(val, list): # pragma: optional cover
raise ValueError(_("invalid value {0} for option {1} " return ValueError(_("invalid value {0} for option {1} "
"which must be a list of list" "which must be a list of list"
"").format(value, "").format(value,
self.impl_getname())) self.impl_getname()))
for slave_idx, slave_val in enumerate(val): for slave_idx, slave_val in enumerate(val):
do_validation(slave_val, idx, slave_idx) err = do_validation(slave_val, idx, slave_idx)
if err:
return err
else: else:
do_validation(val, idx, force_submulti_index) for idx, val in enumerate(value):
err = do_validation(val, idx, force_submulti_index)
if err:
return err
def impl_is_master_slaves(self, type_='both'): def impl_is_master_slaves(self, type_='both'):
"""FIXME """FIXME
@ -585,7 +577,12 @@ class Option(OnlyOption):
dynod = self._impl_getsubdyn() dynod = self._impl_getsubdyn()
else: else:
dynod = None dynod = None
if self.impl_is_submulti():
raise ConfigError(_('cannot add consistency with submulti option'))
is_multi = self.impl_is_multi()
for opt in other_opts: for opt in other_opts:
if opt.impl_is_submulti():
raise ConfigError(_('cannot add consistency with submulti option'))
if not isinstance(opt, Option): # pragma: optional cover if not isinstance(opt, Option): # pragma: optional cover
raise ConfigError(_('consistency must be set with an option')) raise ConfigError(_('consistency must be set with an option'))
if opt._is_subdyn(): if opt._is_subdyn():
@ -601,7 +598,7 @@ class Option(OnlyOption):
'dynoptiondescription but not all')) 'dynoptiondescription but not all'))
if self is opt: # pragma: optional cover if self is opt: # pragma: optional cover
raise ConfigError(_('cannot add consistency with itself')) raise ConfigError(_('cannot add consistency with itself'))
if self.impl_is_multi() != opt.impl_is_multi(): # pragma: optional cover if is_multi != opt.impl_is_multi(): # pragma: optional cover
raise ConfigError(_('every options in consistency must be ' raise ConfigError(_('every options in consistency must be '
'multi or none')) 'multi or none'))
@ -630,9 +627,8 @@ class Option(OnlyOption):
raise ValueError(_('unknow parameter {0} in consistency').format(unknown_params)) raise ValueError(_('unknow parameter {0} in consistency').format(unknown_params))
self._add_consistency(func, all_cons_opts, params) self._add_consistency(func, all_cons_opts, params)
#validate default value when add consistency #validate default value when add consistency
try: err = self.impl_validate(self.impl_getdefault())
self.impl_validate(self.impl_getdefault()) if err:
except ValueError, err:
self._del_consistency() self._del_consistency()
raise err raise err
@ -640,7 +636,7 @@ class Option(OnlyOption):
if context is not undefined: if context is not undefined:
descr = context.cfgimpl_get_description() descr = context.cfgimpl_get_description()
if descr._cache_consistencies is None: if descr._cache_consistencies is None:
return True return
#consistencies is something like [('_cons_not_equal', (opt1, opt2))] #consistencies is something like [('_cons_not_equal', (opt1, opt2))]
if isinstance(option, DynSymLinkOption): if isinstance(option, DynSymLinkOption):
consistencies = descr._cache_consistencies.get(option._impl_getopt()) consistencies = descr._cache_consistencies.get(option._impl_getopt())
@ -664,15 +660,14 @@ class Option(OnlyOption):
opts.append(opt._impl_to_dyn(name, path)) opts.append(opt._impl_to_dyn(name, path))
else: else:
opts = all_cons_opts opts = all_cons_opts
try: err = 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, transitive) warnings_only, transitive)
except ValueError as err: if err:
if warnings_only: if warnings_only:
raise ValueWarning(err.message, option) return ValueWarning(err.message, option)
else: else:
raise err return err
def _cons_not_equal(self, opts, vals, warnings_only): def _cons_not_equal(self, opts, vals, warnings_only):
for idx_inf, val_inf in enumerate(vals): for idx_inf, val_inf in enumerate(vals):
@ -683,7 +678,7 @@ class Option(OnlyOption):
else: else:
msg = _("same value for {0} and {1}, must be different") msg = _("same value for {0} and {1}, must be different")
log.debug('_cons_not_equal: {0} and {1} are not different'.format(val_inf, val_sup)) log.debug('_cons_not_equal: {0} and {1} are not different'.format(val_inf, val_sup))
raise ValueError(msg.format(opts[idx_inf].impl_getname(), return ValueError(msg.format(opts[idx_inf].impl_getname(),
opts[idx_inf + idx_sup + 1].impl_getname())) opts[idx_inf + idx_sup + 1].impl_getname()))
# serialize/unserialize # serialize/unserialize
@ -804,9 +799,8 @@ def validate_requires_arg(multi, requires, name):
'multi option must not set ' 'multi option must not set '
'as requires of non multi option {0}').format(name)) 'as requires of non multi option {0}').format(name))
if expected is not None: if expected is not None:
try: err = option._validate(expected)
option._validate(expected) if err:
except ValueError as err: # pragma: optional cover
raise ValueError(_('malformed requirements second argument ' raise ValueError(_('malformed requirements second argument '
'must be valid for option {0}' 'must be valid for option {0}'
': {1}').format(name, err)) ': {1}').format(name, err))
@ -887,6 +881,9 @@ class SymLinkOption(OnlyOption):
def _is_subdyn(self): def _is_subdyn(self):
return getattr(self._impl_getopt(), '_subdyn', None) is not None return getattr(self._impl_getopt(), '_subdyn', None) is not None
def _get_consistencies(self):
return ()
class DynSymLinkOption(object): class DynSymLinkOption(object):
__slots__ = ('_dyn', '_opt', '_name') __slots__ = ('_dyn', '_opt', '_name')

View File

@ -21,7 +21,7 @@
# ____________________________________________________________ # ____________________________________________________________
from ..i18n import _ from ..i18n import _
from ..setting import log, undefined from ..setting import log, undefined
from ..error import SlaveError, ConfigError, PropertiesOptionError from ..error import SlaveError, PropertiesOptionError
from .baseoption import DynSymLinkOption, SymLinkOption, Option from .baseoption import DynSymLinkOption, SymLinkOption, Option
@ -180,6 +180,7 @@ class MasterSlaves(object):
master=master) master=master)
master_is_meta = values._is_meta(master, masterp) master_is_meta = values._is_meta(master, masterp)
multi = values._get_multi(opt, path) multi = values._get_multi(opt, path)
#if masterlen is [], test properties (has no value, don't get any value)
if masterlen == 0: if masterlen == 0:
if validate_properties: if validate_properties:
props = context.cfgimpl_get_settings().validate_properties(opt, False, props = context.cfgimpl_get_settings().validate_properties(opt, False,

View File

@ -23,9 +23,9 @@ import re
import sys import sys
from IPy import IP from IPy import IP
from types import FunctionType from types import FunctionType
from ..setting import log, undefined from ..setting import undefined
from ..error import ConfigError, ContextError from ..error import ConfigError
from ..i18n import _ from ..i18n import _
from .baseoption import Option, validate_callback from .baseoption import Option, validate_callback
from ..autolib import carry_out_calculation from ..autolib import carry_out_calculation
@ -83,15 +83,15 @@ class ChoiceOption(Option):
values = carry_out_calculation(current_opt, context=context, values = carry_out_calculation(current_opt, context=context,
callback=values, callback=values,
callback_params=values_params) callback_params=values_params)
if not isinstance(values, list): # pragma: optional cover if values is not undefined and not isinstance(values, list): # pragma: optional cover
raise ConfigError(_('calculated values for {0} is not a list' raise ConfigError(_('calculated values for {0} is not a list'
'').format(self.impl_getname())) '').format(self.impl_getname()))
return values return values
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
values = self.impl_get_values(context, current_opt=current_opt) values = self.impl_get_values(context, current_opt=current_opt)
if not value in values: # pragma: optional cover if values is not undefined and not value in values: # pragma: optional cover
raise ValueError(_('value {0} is not permitted, ' return ValueError(_('value {0} is not permitted, '
'only {1} is allowed' 'only {1} is allowed'
'').format(value, '').format(value,
values)) values))
@ -103,7 +103,7 @@ class BoolOption(Option):
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
if not isinstance(value, bool): if not isinstance(value, bool):
raise ValueError(_('invalid boolean')) # pragma: optional cover return ValueError(_('invalid boolean')) # pragma: optional cover
class IntOption(Option): class IntOption(Option):
@ -112,7 +112,7 @@ class IntOption(Option):
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
if not isinstance(value, int): if not isinstance(value, int):
raise ValueError(_('invalid integer')) # pragma: optional cover return ValueError(_('invalid integer')) # pragma: optional cover
class FloatOption(Option): class FloatOption(Option):
@ -121,7 +121,7 @@ class FloatOption(Option):
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
if not isinstance(value, float): if not isinstance(value, float):
raise ValueError(_('invalid float')) # pragma: optional cover return ValueError(_('invalid float')) # pragma: optional cover
class StrOption(Option): class StrOption(Option):
@ -130,7 +130,7 @@ class StrOption(Option):
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
if not isinstance(value, str): if not isinstance(value, str):
raise ValueError(_('invalid string')) # pragma: optional cover return ValueError(_('invalid string')) # pragma: optional cover
if sys.version_info[0] >= 3: # pragma: optional cover if sys.version_info[0] >= 3: # pragma: optional cover
@ -146,7 +146,7 @@ else:
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
if not isinstance(value, unicode): if not isinstance(value, unicode):
raise ValueError(_('invalid unicode')) # pragma: optional cover return ValueError(_('invalid unicode')) # pragma: optional cover
class IPOption(Option): class IPOption(Option):
@ -175,15 +175,17 @@ class IPOption(Option):
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
# sometimes an ip term starts with a zero # sometimes an ip term starts with a zero
# but this does not fit in some case, for example bind does not like it # but this does not fit in some case, for example bind does not like it
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
for val in value.split('.'): for val in value.split('.'):
if val.startswith("0") and len(val) > 1: if val.startswith("0") and len(val) > 1:
raise ValueError(_('invalid IP')) # pragma: optional cover return ValueError(_('invalid IP')) # pragma: optional cover
# 'standard' validation # 'standard' validation
try: try:
IP('{0}/32'.format(value)) IP('{0}/32'.format(value))
except ValueError: # pragma: optional cover except ValueError: # pragma: optional cover
raise ValueError(_('invalid IP')) return ValueError(_('invalid IP'))
def _second_level_validation(self, value, warnings_only): def _second_level_validation(self, value, warnings_only):
ip = IP('{0}/32'.format(value)) ip = IP('{0}/32'.format(value))
@ -192,13 +194,13 @@ class IPOption(Option):
msg = _("IP is in reserved class") msg = _("IP is in reserved class")
else: else:
msg = _("invalid IP, mustn't be in reserved class") msg = _("invalid IP, mustn't be in reserved class")
raise ValueError(msg) return ValueError(msg)
if self._get_extra('_private_only') and not ip.iptype() == 'PRIVATE': # pragma: optional cover if self._get_extra('_private_only') and not ip.iptype() == 'PRIVATE': # pragma: optional cover
if warnings_only: if warnings_only:
msg = _("IP is not in private class") msg = _("IP is not in private class")
else: else:
msg = _("invalid IP, must be in private class") msg = _("invalid IP, must be in private class")
raise ValueError(msg) return ValueError(msg)
def _cons_in_network(self, opts, vals, warnings_only): def _cons_in_network(self, opts, vals, warnings_only):
if len(vals) != 3: if len(vals) != 3:
@ -213,10 +215,10 @@ class IPOption(Option):
else: else:
msg = _('invalid IP {0} ({1}) not in network {2} ({3}) with ' msg = _('invalid IP {0} ({1}) not in network {2} ({3}) with '
'netmask {4} ({5})') 'netmask {4} ({5})')
raise ValueError(msg.format(ip, opts[0].impl_getname(), network, return ValueError(msg.format(ip, opts[0].impl_getname(), network,
opts[1].impl_getname(), netmask, opts[2].impl_getname())) opts[1].impl_getname(), netmask, opts[2].impl_getname()))
# test if ip is not network/broadcast IP # test if ip is not network/broadcast IP
opts[2]._cons_ip_netmask((opts[2], opts[0]), (netmask, ip), warnings_only) return opts[2]._cons_ip_netmask((opts[2], opts[0]), (netmask, ip), warnings_only)
class PortOption(Option): class PortOption(Option):
@ -275,14 +277,16 @@ class PortOption(Option):
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
if isinstance(value, int): if isinstance(value, int):
value = unicode(value) value = unicode(value)
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
if self._get_extra('_allow_range') and ":" in str(value): # pragma: optional cover if self._get_extra('_allow_range') and ":" in str(value): # pragma: optional cover
value = str(value).split(':') value = str(value).split(':')
if len(value) != 2: if len(value) != 2:
raise ValueError(_('invalid port, range must have two values ' return ValueError(_('invalid port, range must have two values '
'only')) 'only'))
if not value[0] < value[1]: if not value[0] < value[1]:
raise ValueError(_('invalid port, first port in range must be' return ValueError(_('invalid port, first port in range must be'
' smaller than the second one')) ' smaller than the second one'))
else: else:
value = [value] value = [value]
@ -291,9 +295,9 @@ class PortOption(Option):
try: try:
val = int(val) val = int(val)
except ValueError: # pragma: optional cover except ValueError: # pragma: optional cover
raise ValueError(_('invalid port')) return ValueError(_('invalid port'))
if not self._get_extra('_min_value') <= val <= self._get_extra('_max_value'): # pragma: optional cover if not self._get_extra('_min_value') <= val <= self._get_extra('_max_value'): # pragma: optional cover
raise ValueError(_('invalid port, must be an integer between {0} ' return ValueError(_('invalid port, must be an integer between {0} '
'and {1}').format(self._get_extra('_min_value'), 'and {1}').format(self._get_extra('_min_value'),
self._get_extra('_max_value'))) self._get_extra('_max_value')))
@ -303,11 +307,13 @@ class NetworkOption(Option):
__slots__ = tuple() __slots__ = tuple()
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
try: try:
IP(value) IP(value)
except ValueError: # pragma: optional cover except ValueError: # pragma: optional cover
raise ValueError(_('invalid network address')) return ValueError(_('invalid network address'))
def _second_level_validation(self, value, warnings_only): def _second_level_validation(self, value, warnings_only):
ip = IP(value) ip = IP(value)
@ -316,7 +322,7 @@ class NetworkOption(Option):
msg = _("network address is in reserved class") msg = _("network address is in reserved class")
else: else:
msg = _("invalid network address, mustn't be in reserved class") msg = _("invalid network address, mustn't be in reserved class")
raise ValueError(msg) return ValueError(msg)
class NetmaskOption(Option): class NetmaskOption(Option):
@ -324,23 +330,25 @@ class NetmaskOption(Option):
__slots__ = tuple() __slots__ = tuple()
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
try: try:
IP('0.0.0.0/{0}'.format(value)) IP('0.0.0.0/{0}'.format(value))
except ValueError: # pragma: optional cover except ValueError: # pragma: optional cover
raise ValueError(_('invalid netmask address')) return ValueError(_('invalid netmask address'))
def _cons_network_netmask(self, opts, vals, warnings_only): def _cons_network_netmask(self, opts, vals, warnings_only):
#opts must be (netmask, network) options #opts must be (netmask, network) options
if None in vals: if None in vals:
return return
self.__cons_netmask(opts, vals[0], vals[1], False, warnings_only) return self.__cons_netmask(opts, vals[0], vals[1], False, warnings_only)
def _cons_ip_netmask(self, opts, vals, warnings_only): def _cons_ip_netmask(self, opts, vals, warnings_only):
#opts must be (netmask, ip) options #opts must be (netmask, ip) options
if None in vals: if None in vals:
return return
self.__cons_netmask(opts, vals[0], vals[1], True, warnings_only) return self.__cons_netmask(opts, vals[0], vals[1], True, warnings_only)
def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net, def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net,
warnings_only): warnings_only):
@ -364,7 +372,7 @@ class NetmaskOption(Option):
if not make_net: if not make_net:
msg = _('invalid network {0} ({1}) with netmask {2}') msg = _('invalid network {0} ({1}) with netmask {2}')
if msg is not None: # pragma: optional cover if msg is not None: # pragma: optional cover
raise ValueError(msg.format(val_ipnetwork, opts[1].impl_getname(), return ValueError(msg.format(val_ipnetwork, opts[1].impl_getname(),
val_netmask)) val_netmask))
@ -372,11 +380,13 @@ class BroadcastOption(Option):
__slots__ = tuple() __slots__ = tuple()
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
try: try:
IP('{0}/32'.format(value)) IP('{0}/32'.format(value))
except ValueError: # pragma: optional cover except ValueError: # pragma: optional cover
raise ValueError(_('invalid broadcast address')) return ValueError(_('invalid broadcast address'))
def _cons_broadcast(self, opts, vals, warnings_only): def _cons_broadcast(self, opts, vals, warnings_only):
if len(vals) != 3: if len(vals) != 3:
@ -385,7 +395,7 @@ class BroadcastOption(Option):
return return
broadcast, network, netmask = vals broadcast, network, netmask = vals
if IP('{0}/{1}'.format(network, netmask)).broadcast() != IP(broadcast): if IP('{0}/{1}'.format(network, netmask)).broadcast() != IP(broadcast):
raise ValueError(_('invalid broadcast {0} ({1}) with network {2} ' return ValueError(_('invalid broadcast {0} ({1}) with network {2} '
'({3}) and netmask {4} ({5})').format( '({3}) and netmask {4} ({5})').format(
broadcast, opts[0].impl_getname(), network, broadcast, opts[0].impl_getname(), network,
opts[1].impl_getname(), netmask, opts[2].impl_getname())) # pragma: optional cover opts[1].impl_getname(), netmask, opts[2].impl_getname())) # pragma: optional cover
@ -430,13 +440,15 @@ class DomainnameOption(Option):
extra=extra) extra=extra)
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
def _valid_length(val): def _valid_length(val):
if len(val) < 1: if len(val) < 1:
raise ValueError(_("invalid domainname's length (min 1)")) return ValueError(_("invalid domainname's length (min 1)"))
if len(val) > part_name_length: if len(val) > part_name_length:
raise ValueError(_("invalid domainname's length (max {0})" return ValueError(_("invalid domainname's length (max {0})"
"").format(part_name_length)) "").format(part_name_length))
if self._get_extra('_allow_ip') is True: # pragma: optional cover if self._get_extra('_allow_ip') is True: # pragma: optional cover
@ -451,23 +463,25 @@ class DomainnameOption(Option):
part_name_length = 63 part_name_length = 63
if self._get_extra('_dom_type') == 'domainname': if self._get_extra('_dom_type') == 'domainname':
if not self._get_extra('_allow_without_dot') and not "." in value: if not self._get_extra('_allow_without_dot') and not "." in value:
raise ValueError(_("invalid domainname, must have dot")) return ValueError(_("invalid domainname, must have dot"))
if len(value) > 255: if len(value) > 255:
raise ValueError(_("invalid domainname's length (max 255)")) return ValueError(_("invalid domainname's length (max 255)"))
for dom in value.split('.'): for dom in value.split('.'):
_valid_length(dom) err = _valid_length(dom)
if err:
return err
else: else:
_valid_length(value) return _valid_length(value)
def _second_level_validation(self, value, warnings_only): def _second_level_validation(self, value, warnings_only):
def _valid_char(val): def _valid_char(val):
if self._get_extra('_has_upper').search(val): if self._get_extra('_has_upper').search(val):
raise ValueError(_('some characters are uppercase')) return ValueError(_('some characters are uppercase'))
if not self._get_extra('_domain_re').search(val): if not self._get_extra('_domain_re').search(val):
if warnings_only: if warnings_only:
raise ValueError(_('some characters may cause problems')) return ValueError(_('some characters may cause problems'))
else: else:
raise ValueError(_('invalid domainname')) return ValueError(_('invalid domainname'))
#not for IP #not for IP
if self._get_extra('_allow_ip') is True: if self._get_extra('_allow_ip') is True:
try: try:
@ -477,9 +491,9 @@ class DomainnameOption(Option):
pass pass
if self._get_extra('_dom_type') == 'domainname': if self._get_extra('_dom_type') == 'domainname':
for dom in value.split('.'): for dom in value.split('.'):
_valid_char(dom) return _valid_char(dom)
else: else:
_valid_char(value) return _valid_char(value)
class EmailOption(DomainnameOption): class EmailOption(DomainnameOption):
@ -487,17 +501,19 @@ class EmailOption(DomainnameOption):
username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$") username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
splitted = value.split('@', 1) splitted = value.split('@', 1)
try: if len(splitted) == 1:
username, domain = splitted return ValueError(_('invalid email address, must contains one @'))
except ValueError: # pragma: optional cover username, domain = value.split('@', 1)
raise ValueError(_('invalid email address, must contains one @'
))
if not self.username_re.search(username): if not self.username_re.search(username):
raise ValueError(_('invalid username in email address')) # pragma: optional cover return ValueError(_('invalid username in email address')) # pragma: optional cover
super(EmailOption, self)._validate(domain) err = super(EmailOption, self)._validate(domain)
super(EmailOption, self)._second_level_validation(domain, False) if err:
return err
return super(EmailOption, self)._second_level_validation(domain, False)
def _second_level_validation(self, value, warnings_only): def _second_level_validation(self, value, warnings_only):
pass pass
@ -509,36 +525,41 @@ class URLOption(DomainnameOption):
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$") path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
match = self.proto_re.search(value) match = self.proto_re.search(value)
if not match: # pragma: optional cover if not match: # pragma: optional cover
raise ValueError(_('invalid url, must start with http:// or ' return ValueError(_('invalid url, must start with http:// or '
'https://')) 'https://'))
value = value[len(match.group(0)):] value = value[len(match.group(0)):]
# get domain/files # get domain/files
splitted = value.split('/', 1) splitted = value.split('/', 1)
try: if len(splitted) == 1:
domain, files = splitted
except ValueError:
domain = value domain = value
files = None files = None
else:
domain, files = splitted
# if port in domain # if port in domain
splitted = domain.split(':', 1) splitted = domain.split(':', 1)
try: if len(splitted) == 1:
domain, port = splitted
except ValueError: # pragma: optional cover
domain = splitted[0] domain = splitted[0]
port = 0 port = 0
else:
domain, port = splitted
if not 0 <= int(port) <= 65535: if not 0 <= int(port) <= 65535:
raise ValueError(_('invalid url, port must be an between 0 and ' return ValueError(_('invalid url, port must be an between 0 and '
'65536')) # pragma: optional cover '65536')) # pragma: optional cover
# validate domainname # validate domainname
super(URLOption, self)._validate(domain) err = super(URLOption, self)._validate(domain)
super(URLOption, self)._second_level_validation(domain, False) if err:
return err
err = super(URLOption, self)._second_level_validation(domain, False)
if err:
return err
# validate file # validate file
if files is not None and files != '' and not self.path_re.search(files): if files is not None and files != '' and not self.path_re.search(files):
raise ValueError(_('invalid url, must ends with a valid resource name')) # pragma: optional cover return ValueError(_('invalid url, must ends with a valid resource name')) # pragma: optional cover
def _second_level_validation(self, value, warnings_only): def _second_level_validation(self, value, warnings_only):
pass pass
@ -550,10 +571,12 @@ class UsernameOption(Option):
username_re = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$") username_re = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
match = self.username_re.search(value) match = self.username_re.search(value)
if not match: if not match:
raise ValueError(_('invalid username')) # pragma: optional cover return ValueError(_('invalid username')) # pragma: optional cover
class FilenameOption(Option): class FilenameOption(Option):
@ -561,7 +584,9 @@ class FilenameOption(Option):
path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$") path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
def _validate(self, value, context=undefined, current_opt=undefined): def _validate(self, value, context=undefined, current_opt=undefined):
self._impl_valid_unicode(value) err = self._impl_valid_unicode(value)
if err:
return err
match = self.path_re.search(value) match = self.path_re.search(value)
if not match: if not match:
raise ValueError(_('invalid filename')) # pragma: optional cover return ValueError(_('invalid filename')) # pragma: optional cover

View File

@ -111,15 +111,32 @@ class OptionDescription(BaseOption, StorageOptionDescription):
#cannot set multi option as OptionDescription requires #cannot set multi option as OptionDescription requires
else: else:
option._set_readonly(True) option._set_readonly(True)
is_multi = option.impl_is_multi()
for func, all_cons_opts, params in option._get_consistencies(): for func, all_cons_opts, params in option._get_consistencies():
all_cons_opts[0]._valid_consistencies(all_cons_opts[1:]) option._valid_consistencies(all_cons_opts[1:])
if is_multi:
is_slave = option.impl_is_master_slaves()
if not is_slave:
raise ValueError(_('malformed consistency option {0} '
'must be a master/slaves').format(
option.impl_getname()))
masterslaves = option.impl_get_master_slaves()
for opt in all_cons_opts: for opt in all_cons_opts:
if is_multi:
if not opt.impl_is_master_slaves():
raise ValueError(_('malformed consistency option {0} '
'must not be a multi for {1}').format(
option.impl_getname(), opt.impl_getname()))
elif masterslaves != opt.impl_get_master_slaves():
raise ValueError(_('malformed consistency option {0} '
'must be in same master/slaves for {1}').format(
option.impl_getname(), opt.impl_getname()))
_consistencies.setdefault(opt, _consistencies.setdefault(opt,
[]).append((func, []).append((func,
all_cons_opts, all_cons_opts,
params)) params))
is_slave = None is_slave = None
if option.impl_is_multi(): if is_multi:
all_requires = option.impl_getrequires() all_requires = option.impl_getrequires()
if all_requires != tuple(): if all_requires != tuple():
for requires in all_requires: for requires in all_requires:

View File

@ -19,7 +19,7 @@
# ____________________________________________________________ # ____________________________________________________________
from ...i18n import _ from ...i18n import _
from ...setting import undefined from ...setting import undefined
from ...error import ConfigError, ContextError from ...error import ConfigError
static_tuple = tuple() static_tuple = tuple()
static_set = frozenset() static_set = frozenset()
@ -94,15 +94,12 @@ class StorageBase(object):
_setattr(self, '_default', default) _setattr(self, '_default', default)
if is_multi and default_multi is not None: if is_multi and default_multi is not None:
try: err = self._validate(default_multi)
self._validate(default_multi) if err:
except ValueError as err: # pragma: optional cover
raise ValueError(_("invalid default_multi value {0} " raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format( "for option {1}: {2}").format(
str(default_multi), str(default_multi),
self.impl_getname(), str(err))) self.impl_getname(), str(err)))
except ContextError, err:
pass
_setattr(self, '_default_multi', default_multi) _setattr(self, '_default_multi', default_multi)
# information # information

View File

@ -326,7 +326,9 @@ class _Base(SqlAlchemyBase):
def _set_default_values(self, default, default_multi): def _set_default_values(self, default, default_multi):
self._default = default self._default = default
if self.impl_is_multi() and default_multi is not None: if self.impl_is_multi() and default_multi is not None:
self._validate(default_multi) err = self._validate(default_multi)
if err:
raise err
self._default_multi = default_multi self._default_multi = default_multi
def _get_consistencies(self): def _get_consistencies(self):

View File

@ -78,7 +78,8 @@ class Values(object):
if meta is not None: if meta is not None:
try: try:
value = meta.cfgimpl_get_values( value = meta.cfgimpl_get_values(
)._get_cached_value(opt, path, index=index, from_masterslave=True) )._get_cached_value(opt, path, index=index, submulti_index=submulti_index,
from_masterslave=True)
if isinstance(value, Multi): if isinstance(value, Multi):
if index is not None: if index is not None:
value = value[index] value = value[index]
@ -207,8 +208,8 @@ class Values(object):
force_permissive=False, trusted_cached_properties=True, force_permissive=False, trusted_cached_properties=True,
validate_properties=True, validate_properties=True,
setting_properties=undefined, self_properties=undefined, setting_properties=undefined, self_properties=undefined,
index=None, from_masterslave=False, with_meta=True, index=None, submulti_index=undefined, from_masterslave=False,
masterlen=undefined, check_frozen=False): with_meta=True, masterlen=undefined, check_frozen=False):
context = self._getcontext() context = self._getcontext()
settings = context.cfgimpl_get_settings() settings = context.cfgimpl_get_settings()
if path is None: if path is None:
@ -257,6 +258,7 @@ class Values(object):
with_meta=with_meta, with_meta=with_meta,
masterlen=masterlen, masterlen=masterlen,
index=index, index=index,
submulti_index=submulti_index,
check_frozen=check_frozen) check_frozen=check_frozen)
# cache doesn't work with SubMulti yet # cache doesn't work with SubMulti yet
if not isinstance(val, SubMulti) and 'cache' in setting_properties and \ if not isinstance(val, SubMulti) and 'cache' in setting_properties and \
@ -325,12 +327,11 @@ class Values(object):
force_submulti_index = None force_submulti_index = None
else: else:
force_submulti_index = submulti_index force_submulti_index = submulti_index
try: err = opt.impl_validate(value, context,
opt.impl_validate(value, context,
'validator' in setting_properties, 'validator' in setting_properties,
force_index=force_index, force_index=force_index,
force_submulti_index=force_submulti_index) force_submulti_index=force_submulti_index)
except ValueError, err: if err:
config_error = err config_error = err
value = None value = None
@ -373,13 +374,15 @@ class Values(object):
if 'validator' in setting_properties: if 'validator' in setting_properties:
fake_context = context._gen_fake_values() fake_context = context._gen_fake_values()
fake_values = fake_context.cfgimpl_get_values() fake_values = fake_context.cfgimpl_get_values()
fake_values._setvalue(opt, path, value)
props = fake_values.validate(opt, value, path, check_frozen, props = fake_values.validate(opt, value, path, check_frozen,
force_permissive, setting_properties, force_permissive, setting_properties,
not_raises=not_raises) not_raises=not_raises)
if props and not_raises: if props and not_raises:
return return
fake_values._setvalue(opt, path, value) err = opt.impl_validate(value, fake_context)
opt.impl_validate(value, fake_context) if err:
raise err
self._setvalue(opt, path, value) self._setvalue(opt, path, value)
def _setvalue(self, opt, path, value): def _setvalue(self, opt, path, value):
@ -811,8 +814,10 @@ class Multi(list):
self._store() self._store()
def _validate(self, value, fake_context, force_index, submulti=False): def _validate(self, value, fake_context, force_index, submulti=False):
self.opt.impl_validate(value, context=fake_context, err = self.opt.impl_validate(value, context=fake_context,
force_index=force_index) force_index=force_index)
if err:
raise err
def pop(self, index, force=False): def pop(self, index, force=False):
"""the list value can be updated (poped) """the list value can be updated (poped)
@ -877,9 +882,11 @@ class SubMulti(Multi):
super(SubMulti, self)._validate(value, fake_context, super(SubMulti, self)._validate(value, fake_context,
force_index, submulti) force_index, submulti)
else: else:
self.opt.impl_validate(value, context=fake_context, err = self.opt.impl_validate(value, context=fake_context,
force_index=self._index, force_index=self._index,
force_submulti_index=force_index) force_submulti_index=force_index)
if err:
raise err
def _get_validated_value(self, index): def _get_validated_value(self, index):
values = self._getcontext().cfgimpl_get_values() values = self._getcontext().cfgimpl_get_values()