warnings only if needed
This commit is contained in:
parent
42d830687d
commit
0f4b1caca4
|
@ -703,3 +703,43 @@ def test_consistency_with_callback():
|
||||||
c.impl_add_consistency('in_network', a, b)
|
c.impl_add_consistency('in_network', a, b)
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
cfg.c
|
cfg.c
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_double_warnings():
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', 1)
|
||||||
|
c = IntOption('c', '', 1)
|
||||||
|
od = OptionDescription('od', '', [a, b, c])
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
a.impl_add_consistency('not_equal', b, warnings_only=True)
|
||||||
|
a.impl_add_consistency('not_equal', c, warnings_only=True)
|
||||||
|
cfg = Config(od)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.a = 1
|
||||||
|
assert w != []
|
||||||
|
assert len(w) == 2
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.c = 2
|
||||||
|
assert w == []
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.a = 2
|
||||||
|
assert w != []
|
||||||
|
assert len(w) == 1
|
||||||
|
cfg.cfgimpl_get_settings().remove('warnings')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.a = 1
|
||||||
|
assert w == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_warnings_error():
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', 1)
|
||||||
|
c = IntOption('c', '', 1)
|
||||||
|
od = OptionDescription('od', '', [a, b, c])
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
a.impl_add_consistency('not_equal', b, warnings_only=True)
|
||||||
|
a.impl_add_consistency('not_equal', c)
|
||||||
|
cfg = Config(od)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
raises(ValueError, "cfg.a = 1")
|
||||||
|
assert w == []
|
||||||
|
|
|
@ -31,7 +31,6 @@ from ..error import (ConfigError, ValueWarning, PropertiesOptionError,
|
||||||
from ..storage import get_storages_option
|
from ..storage import get_storages_option
|
||||||
from . import MasterSlaves
|
from . import MasterSlaves
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[0] >= 3: # pragma: optional cover
|
if sys.version_info[0] >= 3: # pragma: optional cover
|
||||||
xrange = range
|
xrange = range
|
||||||
|
|
||||||
|
@ -469,12 +468,24 @@ class Option(OnlyOption):
|
||||||
all_cons_opts.append(opt)
|
all_cons_opts.append(opt)
|
||||||
|
|
||||||
if val_consistencies:
|
if val_consistencies:
|
||||||
return getattr(self, func)(current_opt, all_cons_opts, all_cons_vals, warnings_only)
|
err = getattr(self, func)(current_opt, all_cons_opts, all_cons_vals, warnings_only)
|
||||||
|
if err:
|
||||||
|
if warnings_only:
|
||||||
|
if isinstance(err, ValueError):
|
||||||
|
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}').format(
|
||||||
|
value, self._display_name, self.impl_get_display_name(), err)
|
||||||
|
else:
|
||||||
|
msg = '{}'.format(err)
|
||||||
|
warnings.warn_explicit(ValueWarning(msg, self),
|
||||||
|
ValueWarning,
|
||||||
|
self.__class__.__name__, 0)
|
||||||
|
else:
|
||||||
|
return err
|
||||||
|
|
||||||
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,
|
||||||
current_opt=undefined, is_multi=None,
|
current_opt=undefined, is_multi=None,
|
||||||
display_warnings=True, multi=None):
|
display_error=True, display_warnings=True, multi=None):
|
||||||
"""
|
"""
|
||||||
:param value: the option's value
|
:param value: the option's value
|
||||||
:param context: Config's context
|
:param context: Config's context
|
||||||
|
@ -493,8 +504,10 @@ class Option(OnlyOption):
|
||||||
if current_opt is undefined:
|
if current_opt is undefined:
|
||||||
current_opt = self
|
current_opt = self
|
||||||
|
|
||||||
|
display_warnings = display_warnings and (context is undefined or
|
||||||
|
'warnings' in context.cfgimpl_get_settings())
|
||||||
def _is_not_unique(value):
|
def _is_not_unique(value):
|
||||||
if self.impl_is_unique() and len(set(value)) != len(value):
|
if display_error and self.impl_is_unique() and len(set(value)) != len(value):
|
||||||
for idx, val in enumerate(value):
|
for idx, val in enumerate(value):
|
||||||
if val in value[idx+1:]:
|
if val in value[idx+1:]:
|
||||||
return ValueError(_('invalid value "{}", this value is already in "{}"').format(
|
return ValueError(_('invalid value "{}", this value is already in "{}"').format(
|
||||||
|
@ -527,6 +540,7 @@ class Option(OnlyOption):
|
||||||
if _value is None:
|
if _value is None:
|
||||||
error = warning = None
|
error = warning = None
|
||||||
else:
|
else:
|
||||||
|
if display_error:
|
||||||
# option validation
|
# option validation
|
||||||
err = self._validate(_value, context, current_opt)
|
err = self._validate(_value, context, current_opt)
|
||||||
if err:
|
if err:
|
||||||
|
@ -536,9 +550,6 @@ class Option(OnlyOption):
|
||||||
submulti_index),
|
submulti_index),
|
||||||
exc_info=True)
|
exc_info=True)
|
||||||
err_msg = '{0}'.format(err)
|
err_msg = '{0}'.format(err)
|
||||||
name = self.impl_getdoc()
|
|
||||||
if name is None or name == '':
|
|
||||||
name = self.impl_getname()
|
|
||||||
if err_msg:
|
if err_msg:
|
||||||
msg = _('"{0}" is an invalid {1} for "{2}", {3}'
|
msg = _('"{0}" is an invalid {1} for "{2}", {3}'
|
||||||
'').format(_value, self._display_name,
|
'').format(_value, self._display_name,
|
||||||
|
@ -548,9 +559,8 @@ class Option(OnlyOption):
|
||||||
'').format(_value, self._display_name,
|
'').format(_value, self._display_name,
|
||||||
self.impl_get_display_name())
|
self.impl_get_display_name())
|
||||||
return ValueError(msg)
|
return ValueError(msg)
|
||||||
warning = None
|
|
||||||
error = None
|
error = None
|
||||||
if display_warnings:
|
if (display_error and not self._is_warnings_only()) or (display_warnings and self._is_warnings_only()):
|
||||||
error = calculation_validator(_value)
|
error = calculation_validator(_value)
|
||||||
if not error:
|
if not error:
|
||||||
error = self._second_level_validation(_value, self._is_warnings_only())
|
error = self._second_level_validation(_value, self._is_warnings_only())
|
||||||
|
@ -559,30 +569,23 @@ class Option(OnlyOption):
|
||||||
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
|
|
||||||
error = None
|
|
||||||
if error is None and warning is None:
|
|
||||||
# if context launch consistency validation
|
|
||||||
#if context is not undefined:
|
|
||||||
ret = self._valid_consistency(current_opt, _value, context,
|
|
||||||
_index, submulti_index)
|
|
||||||
if ret:
|
|
||||||
if isinstance(ret, ValueWarning):
|
|
||||||
if display_warnings:
|
|
||||||
warning = ret
|
|
||||||
elif isinstance(ret, ValueError):
|
|
||||||
error = ret
|
|
||||||
else:
|
|
||||||
return ret
|
|
||||||
if warning:
|
|
||||||
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}').format(
|
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}').format(
|
||||||
_value, self._display_name, self.impl_get_display_name(), warning)
|
_value, self._display_name, self.impl_get_display_name(), error)
|
||||||
if context is undefined or 'warnings' in \
|
|
||||||
context.cfgimpl_get_settings():
|
|
||||||
warnings.warn_explicit(ValueWarning(msg, self),
|
warnings.warn_explicit(ValueWarning(msg, self),
|
||||||
ValueWarning,
|
ValueWarning,
|
||||||
self.__class__.__name__, 0)
|
self.__class__.__name__, 0)
|
||||||
elif error:
|
error = None
|
||||||
|
if error is None:
|
||||||
|
# if context launch consistency validation
|
||||||
|
#if context is not undefined:
|
||||||
|
ret = self._valid_consistency(current_opt, _value, context,
|
||||||
|
_index, submulti_index, display_warnings,
|
||||||
|
display_error)
|
||||||
|
if isinstance(ret, ValueError):
|
||||||
|
error = ret
|
||||||
|
elif ret:
|
||||||
|
return ret
|
||||||
|
if error:
|
||||||
err_msg = '{0}'.format(error)
|
err_msg = '{0}'.format(error)
|
||||||
if err_msg:
|
if err_msg:
|
||||||
msg = _('"{0}" is an invalid {1} for "{2}", {3}'
|
msg = _('"{0}" is an invalid {1} for "{2}", {3}'
|
||||||
|
@ -594,10 +597,6 @@ class Option(OnlyOption):
|
||||||
self.impl_get_display_name())
|
self.impl_get_display_name())
|
||||||
return ValueError(msg)
|
return ValueError(msg)
|
||||||
|
|
||||||
# generic calculation
|
|
||||||
#if context is not undefined:
|
|
||||||
# descr = context.cfgimpl_get_description()
|
|
||||||
|
|
||||||
if is_multi is None:
|
if is_multi is None:
|
||||||
is_multi = self.impl_is_multi()
|
is_multi = self.impl_is_multi()
|
||||||
|
|
||||||
|
@ -653,7 +652,7 @@ class Option(OnlyOption):
|
||||||
if err:
|
if err:
|
||||||
return err
|
return err
|
||||||
return self._valid_consistency(current_opt, None, context,
|
return self._valid_consistency(current_opt, None, context,
|
||||||
None, None)
|
None, None, display_warnings, display_error)
|
||||||
|
|
||||||
def impl_is_dynsymlinkoption(self):
|
def impl_is_dynsymlinkoption(self):
|
||||||
return False
|
return False
|
||||||
|
@ -752,7 +751,8 @@ class Option(OnlyOption):
|
||||||
#consistency could generate warnings or errors
|
#consistency could generate warnings or errors
|
||||||
self._set_has_dependency()
|
self._set_has_dependency()
|
||||||
|
|
||||||
def _valid_consistency(self, option, value, context, index, submulti_idx):
|
def _valid_consistency(self, option, value, context, index, submulti_idx,
|
||||||
|
display_warnings, display_error):
|
||||||
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:
|
||||||
|
@ -767,6 +767,7 @@ class Option(OnlyOption):
|
||||||
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)
|
||||||
|
if (warnings_only and display_warnings) or (not warnings_only and display_error):
|
||||||
transitive = params.get('transitive', True)
|
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):
|
||||||
|
@ -785,9 +786,6 @@ class Option(OnlyOption):
|
||||||
opts, warnings_only,
|
opts, warnings_only,
|
||||||
transitive)
|
transitive)
|
||||||
if err:
|
if err:
|
||||||
if warnings_only:
|
|
||||||
return ValueWarning(str(err), option)
|
|
||||||
else:
|
|
||||||
return err
|
return err
|
||||||
|
|
||||||
def _cons_not_equal(self, current_opt, opts, vals, warnings_only):
|
def _cons_not_equal(self, current_opt, opts, vals, warnings_only):
|
||||||
|
@ -1062,12 +1060,13 @@ class DynSymLinkOption(object):
|
||||||
|
|
||||||
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, is_multi=None,
|
force_index=None, force_submulti_index=None, is_multi=None,
|
||||||
display_warnings=True, multi=None):
|
display_error=True, display_warnings=True, multi=None):
|
||||||
return self._impl_getopt().impl_validate(value, context, validate,
|
return self._impl_getopt().impl_validate(value, context, validate,
|
||||||
force_index,
|
force_index,
|
||||||
force_submulti_index,
|
force_submulti_index,
|
||||||
current_opt=self,
|
current_opt=self,
|
||||||
is_multi=is_multi,
|
is_multi=is_multi,
|
||||||
|
display_error=display_error,
|
||||||
display_warnings=display_warnings,
|
display_warnings=display_warnings,
|
||||||
multi=multi)
|
multi=multi)
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ class Values(object):
|
||||||
|
|
||||||
def __getitem__(self, opt):
|
def __getitem__(self, opt):
|
||||||
"enables us to use the pythonic dictionary-like access to values"
|
"enables us to use the pythonic dictionary-like access to values"
|
||||||
return self.getitem(opt)
|
return self._get_cached_value(opt)
|
||||||
|
|
||||||
def getitem(self, opt, validate=True, force_permissive=False):
|
def getitem(self, opt, validate=True, force_permissive=False):
|
||||||
"""
|
"""
|
||||||
|
@ -315,6 +315,7 @@ class Values(object):
|
||||||
value = self._getvalue(opt, path, self_properties, index, submulti_index,
|
value = self._getvalue(opt, path, self_properties, index, submulti_index,
|
||||||
with_meta, masterlen, session)
|
with_meta, masterlen, session)
|
||||||
if isinstance(value, Exception):
|
if isinstance(value, Exception):
|
||||||
|
value_error = True
|
||||||
if isinstance(value, ConfigError):
|
if isinstance(value, ConfigError):
|
||||||
# For calculating properties, we need value (ie for mandatory
|
# For calculating properties, we need value (ie for mandatory
|
||||||
# value).
|
# value).
|
||||||
|
@ -330,6 +331,7 @@ class Values(object):
|
||||||
else:
|
else:
|
||||||
raise value
|
raise value
|
||||||
else:
|
else:
|
||||||
|
value_error = False
|
||||||
if index is undefined:
|
if index is undefined:
|
||||||
force_index = None
|
force_index = None
|
||||||
else:
|
else:
|
||||||
|
@ -350,7 +352,8 @@ class Values(object):
|
||||||
'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,
|
||||||
display_warnings=display_warnings)
|
display_error=True,
|
||||||
|
display_warnings=False)
|
||||||
if err:
|
if err:
|
||||||
config_error = err
|
config_error = err
|
||||||
value = None
|
value = None
|
||||||
|
@ -370,6 +373,13 @@ class Values(object):
|
||||||
index=index)
|
index=index)
|
||||||
if props:
|
if props:
|
||||||
return props
|
return props
|
||||||
|
if not value_error and validate and display_warnings:
|
||||||
|
opt.impl_validate(value, context,
|
||||||
|
'validator' in setting_properties,
|
||||||
|
force_index=force_index,
|
||||||
|
force_submulti_index=force_submulti_index,
|
||||||
|
display_error=False,
|
||||||
|
display_warnings=display_warnings)
|
||||||
if config_error is not None:
|
if config_error is not None:
|
||||||
return config_error
|
return config_error
|
||||||
return value
|
return value
|
||||||
|
@ -396,9 +406,10 @@ class Values(object):
|
||||||
session=session, not_raises=not_raises)
|
session=session, not_raises=not_raises)
|
||||||
if props and not_raises:
|
if props and not_raises:
|
||||||
return
|
return
|
||||||
err = opt.impl_validate(value, fake_context)
|
err = opt.impl_validate(value, fake_context, display_warnings=False)
|
||||||
if err:
|
if err:
|
||||||
raise err
|
raise err
|
||||||
|
opt.impl_validate(value, fake_context, display_error=False)
|
||||||
self._setvalue(opt, path, value)
|
self._setvalue(opt, path, value)
|
||||||
|
|
||||||
def _setvalue(self, opt, path, value, force_owner=undefined, index=None):
|
def _setvalue(self, opt, path, value, force_owner=undefined, index=None):
|
||||||
|
|
Loading…
Reference in New Issue