diff --git a/test/test_option_validator.py b/test/test_option_validator.py index 8058f83..df44b9c 100644 --- a/test/test_option_validator.py +++ b/test/test_option_validator.py @@ -81,6 +81,10 @@ def value_values_index2(value, values, index, auto=False): value == 'val2' and values == ['val1', 'val2'] and index == 'val'): raise ValueError('error') +def value_empty(value, empty, values): + if not value == 'val' or empty is not False and not values == ['val']: + raise ValueError('error') + def test_validator(): opt1 = StrOption('opt1', '', validator=return_true, default='val') @@ -176,6 +180,24 @@ def test_validator_params_value_values_notmulti(): raises(TypeError, "opt1 = StrOption('opt1', '', validator=value_values, default='val')") +def test_validator_params_value_values_kwargs_empty(): + v = BoolOption('v', '', default=False) + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"]) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', + "masque du sous-reseau", + multi=True, + validator=value_empty, + validator_params={'': ((v, False),)}) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [v, interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == ['ip'] + cfg.ip_admin_eth0.netmask_admin_eth0[0] = 'val' + #cfg.ip_admin_eth0.ip_admin_eth0.append('val') + #cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' + + def test_validator_params_value_values_kwargs(): v = BoolOption('v', '', default=False) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"]) diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index 81593a5..0c5ed6a 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -32,7 +32,7 @@ from ..error import (ConfigError, ValueWarning, PropertiesOptionError, from ..storage import get_storages_option from . import MasterSlaves -if sys.version_info[0] >= 3: # pragma: optional cover +if sys.version_info[0] >= 3: # pragma: no cover xrange = range @@ -47,49 +47,49 @@ allowed_const_list = ['_cons_not_equal'] def valid_name(name): "an option's name is a str and does not start with 'impl' or 'cfgimpl'" - if not isinstance(name, str): # pragma: optional cover + if not isinstance(name, str): return False if re.match(name_regexp, name) is not None and \ name not in forbidden_names and \ not name.startswith('impl_') and \ not name.startswith('cfgimpl_'): return True - else: # pragma: optional cover + else: return False def validate_callback(callback, callback_params, type_): - if not isinstance(callback, FunctionType): # pragma: optional cover + if not isinstance(callback, FunctionType): raise ValueError(_('{0} must be a function').format(type_)) if callback_params is not None: - if not isinstance(callback_params, dict): # pragma: optional cover + if not isinstance(callback_params, dict): raise ValueError(_('{0}_params must be a dict').format(type_)) for key, callbacks in callback_params.items(): - if key != '' and len(callbacks) != 1: # pragma: optional cover + if key != '' and len(callbacks) != 1: raise ValueError(_("{0}_params with key {1} mustn't have " "length different to 1").format(type_, key)) - if not isinstance(callbacks, tuple): # pragma: optional cover + if not isinstance(callbacks, tuple): raise ValueError(_('{0}_params must be tuple for key "{1}"' ).format(type_, key)) for callbk in callbacks: if isinstance(callbk, tuple): if len(callbk) == 1: - if callbk not in ((None,), ('index',)): # pragma: optional cover + if callbk not in ((None,), ('index',)): raise ValueError(_('{0}_params with length of ' 'tuple as 1 must only have ' 'None as first value')) - elif len(callbk) != 2: # pragma: optional cover + elif len(callbk) != 2: raise ValueError(_('{0}_params must only have 1 or 2 ' 'as length')) else: option, force_permissive = callbk if not isinstance(option, Option) and not \ - isinstance(option, SymLinkOption): # pragma: optional cover + isinstance(option, SymLinkOption): raise ValueError(_('{}_params must have an option' ' not a {} for first argument' ).format(type_, type(option))) - if force_permissive not in [True, False]: # pragma: optional cover + if force_permissive not in [True, False]: raise ValueError(_('{}_params must have a boolean' ' not a {} for second argument' ).format(type_, type( @@ -106,9 +106,9 @@ class Base(StorageBase): callback_params=None, validator=None, validator_params=None, properties=None, warnings_only=False, extra=None, allow_empty_list=undefined, session=None): - if not valid_name(name): # pragma: optional cover + if not valid_name(name): raise ValueError(_("invalid name: {0} for option").format(name)) - if not multi and default_multi is not None: # pragma: optional cover + if not multi and default_multi is not None: raise ValueError(_("default_multi is set whereas multi is False" " in option: {0}").format(name)) if multi is True: @@ -134,7 +134,7 @@ class Base(StorageBase): requires = undefined if properties is None: properties = tuple() - if not isinstance(properties, tuple): # pragma: optional cover + if not isinstance(properties, tuple): raise TypeError(_('invalid properties type {0} for {1},' ' must be a tuple').format( type(properties), @@ -146,7 +146,7 @@ class Base(StorageBase): validate_callback(validator, validator_params, 'validator') self._set_validator(validator, validator_params) self._set_has_dependency() - if calc_properties != frozenset([]) and properties is not tuple(): # pragma: optional cover + if calc_properties != frozenset([]) and properties is not tuple(): set_forbidden_properties = calc_properties & set(properties) if set_forbidden_properties != frozenset(): raise ValueError('conflict: properties already set in ' @@ -207,7 +207,7 @@ class Base(StorageBase): return getattr(self, '_has_dependency', False) def impl_set_callback(self, callback, callback_params=None, _init=False): - if callback is None and callback_params is not None: # pragma: optional cover + if callback is None and callback_params is not None: raise ValueError(_("params defined for a callback function but " "no callback defined" " yet for option {0}").format( @@ -296,7 +296,7 @@ class BaseOption(Base): """ try: self._stated - except AttributeError: # pragma: optional cover + except AttributeError: raise SystemError(_('cannot serialize Option, ' 'only in OptionDescription')) if isinstance(self, SymLinkOption): @@ -335,7 +335,7 @@ class BaseOption(Base): getattr(self, func)(descr, load=True) try: del(self._stated) - except AttributeError: # pragma: optional cover + except AttributeError: pass def __setstate__(self, state): @@ -377,7 +377,7 @@ class BaseOption(Base): pass elif name != '_readonly': is_readonly = self.impl_is_readonly() - if is_readonly: # pragma: optional cover + if is_readonly: raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is" " read-only").format( self.__class__.__name__, @@ -646,7 +646,7 @@ class Option(OnlyOption): err = _is_not_unique(value) if err: return err - if not isinstance(value, list): # pragma: optional cover + if not isinstance(value, list): return ValueError(_('invalid value "{0}" for "{1}" which' ' must be a list').format( value, self.impl_get_display_name())) @@ -664,7 +664,7 @@ class Option(OnlyOption): ' in "{}"').format(value, self.impl_get_display_name())) return do_validation(value, force_index, force_submulti_index) - elif not isinstance(value, list): # pragma: optional cover + elif not isinstance(value, list): return ValueError(_('invalid value "{0}" for "{1}" which ' 'must be a list').format(value, self.impl_getname())) @@ -673,7 +673,7 @@ class Option(OnlyOption): err = _is_not_unique(val) if err: return err - if not isinstance(val, list): # pragma: optional cover + if not isinstance(val, list): return ValueError(_('invalid value "{0}" for "{1}" ' 'which must be a list of list' '').format(val, @@ -732,7 +732,7 @@ class Option(OnlyOption): 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): raise ConfigError(_('consistency must be set with an option')) if opt._is_subdyn(): if dynod is None: @@ -745,9 +745,9 @@ class Option(OnlyOption): elif dynod is not None: raise ConfigError(_('almost one option in consistency is in a ' 'dynoptiondescription but not all')) - if self is opt: # pragma: optional cover + if self is opt: raise ConfigError(_('cannot add consistency with itself')) - if is_multi != opt.impl_is_multi(): # pragma: optional cover + if is_multi != opt.impl_is_multi(): raise ConfigError(_('every options in consistency must be ' 'multi or none')) if init: @@ -764,7 +764,7 @@ class Option(OnlyOption): :type other_opts: `list` of `tiramisu.option.Option` :param params: extra params (warnings_only and transitive are allowed) """ - if self.impl_is_readonly(): # pragma: optional cover + if self.impl_is_readonly(): raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is" " read-only").format( self.__class__.__name__, @@ -908,7 +908,7 @@ class Option(OnlyOption): is_multi = self.impl_is_multi() default = self.impl_getdefault() if (not is_multi and (default is not None or default_multi is not None)) or \ - (is_multi and (default != [] or default_multi is not None)): # pragma: optional cover + (is_multi and (default != [] or default_multi is not None)): raise ValueError(_("default value not allowed if option: {0} " "is calculated").format(self.impl_getname())) @@ -928,13 +928,13 @@ def validate_requires_arg(multi, requires, name): # start parsing all requires given by user (has dict) # transforme it to a tuple for require in requires: - if not isinstance(require, dict): # pragma: optional cover + if not isinstance(require, dict): raise ValueError(_("malformed requirements type for option:" " {0}, must be a dict").format(name)) valid_keys = ('option', 'expected', 'action', 'inverse', 'transitive', 'same_action') unknown_keys = frozenset(require.keys()) - frozenset(valid_keys) - if unknown_keys != frozenset(): # pragma: optional cover + if unknown_keys != frozenset(): raise ValueError(_('malformed requirements for option: {0}' ' unknown keys {1}, must only ' '{2}').format(name, @@ -949,24 +949,24 @@ def validate_requires_arg(multi, requires, name): option = require['option'] expected = require['expected'] action = require['action'] - if action == 'force_store_value': # pragma: optional cover + if action == 'force_store_value': raise ValueError(_("malformed requirements for option: {0}" " action cannot be force_store_value" ).format(name)) inverse = require.get('inverse', False) - if inverse not in [True, False]: # pragma: optional cover + if inverse not in [True, False]: raise ValueError(_('malformed requirements for option: {0}' ' inverse must be boolean')) transitive = require.get('transitive', True) - if transitive not in [True, False]: # pragma: optional cover + if transitive not in [True, False]: raise ValueError(_('malformed requirements for option: {0}' ' transitive must be boolean')) same_action = require.get('same_action', True) - if same_action not in [True, False]: # pragma: optional cover + if same_action not in [True, False]: raise ValueError(_('malformed requirements for option: {0}' ' same_action must be boolean')) - if not isinstance(option, Option): # pragma: optional cover + if not isinstance(option, Option): raise ValueError(_('malformed requirements ' 'must be an option in option {0}').format(name)) if not multi and option.impl_is_multi(): @@ -1005,7 +1005,7 @@ class SymLinkOption(OnlyOption): # __slots__ = ('_opt', '_state_opt') def __init__(self, name, opt): - if not isinstance(opt, Option): # pragma: optional cover + if not isinstance(opt, Option): raise ValueError(_('malformed symlinkoption ' 'must be an option ' 'for symlink {0}').format(name))