diff --git a/test/test_option_validator.py b/test/test_option_validator.py index f2ccd8b..057aa4d 100644 --- a/test/test_option_validator.py +++ b/test/test_option_validator.py @@ -80,15 +80,20 @@ def test_validator_warning(): 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().get_warnings() == {opt2: '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().get_warnings() == {opt3: 'invalid value val1 for option opt3: error'} assert cfg.cfgimpl_get_values().has_warning() is False raises(ValueError, "cfg.opt2 = 1") + cfg.opt2 = 'val' + cfg.opt3.append('val') + assert cfg.cfgimpl_get_values().has_warning() is True + assert cfg.cfgimpl_get_values().get_warnings() == {opt2: 'invalid value val for option opt2: error', opt3: 'invalid value val1 for option opt3: error'} + assert cfg.cfgimpl_get_values().has_warning() is False def test_validator_warning_master_slave(): @@ -104,13 +109,13 @@ def test_validator_warning_master_slave(): cfg.ip_admin_eth0.netmask_admin_eth0 = ['val1'] assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['val1'] assert cfg.cfgimpl_get_values().has_warning() is True - assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val1 for option netmask_admin_eth0: error' + assert cfg.cfgimpl_get_values().get_warnings() == {netmask_admin_eth0: 'invalid value val1 for option netmask_admin_eth0: error'} cfg.ip_admin_eth0.ip_admin_eth0 = ['val'] assert cfg.ip_admin_eth0.ip_admin_eth0 == ['val'] - assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val for option ip_admin_eth0: error' + assert cfg.cfgimpl_get_values().get_warnings() == {ip_admin_eth0: 'invalid value val for option ip_admin_eth0: error'} cfg.ip_admin_eth0.ip_admin_eth0 = ['val', 'val1', 'val1'] - assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val for option ip_admin_eth0: error' + assert cfg.cfgimpl_get_values().get_warnings() == {ip_admin_eth0: 'invalid value val for option ip_admin_eth0: error'} cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val', 'val1'] - assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val for option ip_admin_eth0: error' + assert cfg.cfgimpl_get_values().get_warnings() == {ip_admin_eth0: 'invalid value val for option ip_admin_eth0: error'} cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val1', 'val'] - assert cfg.cfgimpl_get_values().get_last_warning() == 'invalid value val for option ip_admin_eth0: error' + assert cfg.cfgimpl_get_values().get_warnings() == {ip_admin_eth0: 'invalid value val for option ip_admin_eth0: error'} diff --git a/tiramisu/value.py b/tiramisu/value.py index d2aa6a1..a180806 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -45,6 +45,7 @@ class Values(object): self.context = weakref.ref(context) # the storage type is dictionary or sqlite3 self._p_ = storage + self._warning = {} def _getdefault(self, opt): """ @@ -106,9 +107,9 @@ class Values(object): path = self._get_opt_path(opt) if self._p_.hasvalue(path): setting = self.context().cfgimpl_get_settings() - self._warning = opt.impl_validate(opt.impl_getdefault(), - self.context(), - 'validator' in setting) + self._setwarning(opt.impl_validate(opt.impl_getdefault(), + self.context(), + 'validator' in setting), opt) self.context().cfgimpl_reset_cache() if (opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.master): @@ -230,8 +231,8 @@ class Values(object): else: value = self._getvalue(opt, path, validate) if config_error is None and validate: - self._warning = opt.impl_validate(value, self.context(), - 'validator' in setting) + self._setwarning(opt.impl_validate(value, self.context(), + 'validator' in setting), opt) if config_error is None and self._is_default_owner(path) and \ 'force_store_value' in setting[opt]: self.setitem(opt, value, path, is_write=False) @@ -252,9 +253,9 @@ class Values(object): # is_write is, for example, used with "force_store_value" # user didn't change value, so not write # valid opt - self._warning = opt.impl_validate(value, self.context(), - 'validator' in self.context( - ).cfgimpl_get_settings()) + self._setwarning(opt.impl_validate(value, self.context(), + 'validator' in self.context( + ).cfgimpl_get_settings()), opt) if opt.impl_is_multi() and not isinstance(value, Multi): value = Multi(value, self.context, opt, path, setitem=True) self._setvalue(opt, path, value, force_permissive=force_permissive, @@ -373,19 +374,24 @@ class Values(object): def __setstate__(self, states): self._p_ = states['_p_'] + def _setwarning(self, msg, opt): + if msg is not None: + self._warning[opt] = msg + 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 + return self._warning != {} - def get_last_warning(self): - """Get last warning message in self._warning. - We can get only one time this message. + def get_warnings(self): + """Get last warnings messages in self._warning. + We can get only one time those messages. + :returns: {opt: msg, opt1: msg1} """ ret = self._warning - self._warning = None + self._warning = {} return ret @@ -558,9 +564,9 @@ class Multi(list): def _validate(self, value): if value is not None: try: - self.context().cfgimpl_get_values()._warning = \ + self.context().cfgimpl_get_values()._setwarning( self.opt.impl_validate(value, context=self.context(), - force_no_multi=True) + force_no_multi=True), self.opt) except ValueError as err: raise ValueError(_("invalid value {0} " "for option {1}: {2}"