better error messages
authorEmmanuel Garette <egarette@cadoles.com>
Sun, 11 Sep 2016 14:18:23 +0000 (16:18 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Sun, 11 Sep 2016 14:18:23 +0000 (16:18 +0200)
tiramisu/option/baseoption.py
tiramisu/option/option.py

index 2ccfd0a..bc639ac 100644 (file)
@@ -490,8 +490,15 @@ class Option(OnlyOption):
                           'submulti_index: {2}'.format(_value, _index,
                                                        submulti_index),
                           exc_info=True)
-                return ValueError(_('invalid value for option {0}: {1}'
-                                    '').format(self.impl_getname(), err))
+                if '{0}'.format(err):
+                    msg = _('{0} is an invalid {1} for option {2}: {3}'
+                            '').format(_value, self.display_name,
+                                       self.impl_getname(), err)
+                else:
+                    msg = _('{0} is an invalid {1} for option {2}'
+                            '').format(_value, self.display_name,
+                                       self.impl_getname())
+                return ValueError(msg)
             warning = None
             error = calculation_validator(_value)
             if not error:
@@ -515,16 +522,23 @@ class Option(OnlyOption):
                     else:
                         return ret
             if warning:
-                msg = _("warning on the value of the option {0}: {1}").format(
-                    self.impl_getname(), warning)
+                msg = _("attention, {0} could be an invalid {1} for option {2}: {3}").format(
+                    _value, self.display_name, self.impl_getname(), warning)
                 if context is undefined or 'warnings' in \
                         context.cfgimpl_get_settings():
                     warnings.warn_explicit(ValueWarning(msg, self),
                                            ValueWarning,
                                            self.__class__.__name__, 0)
             elif error:
-                return ValueError(_("invalid value for option {0}: {1}").format(
-                    self.impl_getname(), error))
+                if '{0}'.format(err):
+                    msg = _("{0} is an invalid {1} for option {2}: {3}"
+                            "").format(_value, self.display_name,
+                                       self.impl_getname(), error)
+                else:
+                    msg = _("{0} is an invalid {1} for option {2}"
+                            "").format(_value, self.display_name,
+                                       self.impl_getname())
+                return ValueError(msg)
 
         # generic calculation
         #if context is not undefined:
@@ -568,7 +582,7 @@ class Option(OnlyOption):
                     return err
             else:
                 return self._valid_consistency(current_opt, None, context,
-                                              None, None)
+                                               None, None)
 
     def impl_is_master_slaves(self, type_='both'):
         """FIXME
index fed1d72..afdd35a 100644 (file)
@@ -37,6 +37,7 @@ class ChoiceOption(Option):
     The option can also have the value ``None``
     """
     __slots__ = tuple()
+    display_name = _('choice')
 
     def __init__(self, name, doc, values, default=None,
                  values_params=None, default_multi=None, requires=None,
@@ -108,6 +109,7 @@ class ChoiceOption(Option):
 class BoolOption(Option):
     "represents a choice between ``True`` and ``False``"
     __slots__ = tuple()
+    display_name = _('boolean')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -118,6 +120,7 @@ class BoolOption(Option):
 class IntOption(Option):
     "represents a choice of an integer"
     __slots__ = tuple()
+    display_name = _('integer')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -128,6 +131,7 @@ class IntOption(Option):
 class FloatOption(Option):
     "represents a choice of a floating point number"
     __slots__ = tuple()
+    display_name = _('float')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -138,6 +142,7 @@ class FloatOption(Option):
 class StrOption(Option):
     "represents the choice of a string"
     __slots__ = tuple()
+    display_name = _('string')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -155,6 +160,7 @@ else:
         "represents the choice of a unicode string"
         __slots__ = tuple()
         _empty = u''
+        display_name = _('string')
 
         def _validate(self, value, context=undefined, current_opt=undefined,
                       returns_raise=False):
@@ -165,6 +171,7 @@ else:
 class PasswordOption(Option):
     "represents the choice of a password"
     __slots__ = tuple()
+    display_name = _('password')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -176,6 +183,7 @@ class PasswordOption(Option):
 class IPOption(Option):
     "represents the choice of an ip"
     __slots__ = tuple()
+    display_name = _('IP')
 
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -204,29 +212,29 @@ class IPOption(Option):
         if err:
             return err
         if value.count('.') != 3:
-            return ValueError(_('invalid IP'))
+            return ValueError()
         for val in value.split('.'):
             if val.startswith("0") and len(val) > 1:
-                return ValueError(_('invalid IP'))  # pragma: optional cover
+                return ValueError()  # pragma: optional cover
         # 'standard' validation
         try:
             IP('{0}/32'.format(value))
         except ValueError:  # pragma: optional cover
-            return ValueError(_('invalid IP'))
+            return ValueError()
 
     def _second_level_validation(self, value, warnings_only):
         ip = IP('{0}/32'.format(value))
         if not self._get_extra('_allow_reserved') and ip.iptype() == 'RESERVED':  # pragma: optional cover
             if warnings_only:
-                msg = _("IP is in reserved class")
+                msg = _("shouldn't in reserved class")
             else:
-                msg = _("invalid IP, mustn't be in reserved class")
+                msg = _("mustn't be in reserved class")
             return ValueError(msg)
         if self._get_extra('_private_only') and not ip.iptype() == 'PRIVATE':  # pragma: optional cover
             if warnings_only:
-                msg = _("IP is not in private class")
+                msg = _("should be in private class")
             else:
-                msg = _("invalid IP, must be in private class")
+                msg = _("must be in private class")
             return ValueError(msg)
 
     def _cons_in_network(self, opts, vals, warnings_only):
@@ -260,6 +268,7 @@ class PortOption(Option):
     """
     __slots__ = tuple()
     port_re = re.compile(r"^[0-9]*$")
+    display_name = _('port')
 
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -290,7 +299,6 @@ class PortOption(Option):
         if extra['_max_value'] is None:
             raise ValueError(_('max value is empty'))  # pragma: optional cover
 
-
         super(PortOption, self).__init__(name, doc, default=default,
                                          default_multi=default_multi,
                                          callback=callback,
@@ -337,6 +345,7 @@ class PortOption(Option):
 class NetworkOption(Option):
     "represents the choice of a network"
     __slots__ = tuple()
+    display_name = _('network')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -366,6 +375,7 @@ class NetworkOption(Option):
 class NetmaskOption(Option):
     "represents the choice of a netmask"
     __slots__ = tuple()
+    display_name = _('netmask')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -422,6 +432,7 @@ class NetmaskOption(Option):
 
 class BroadcastOption(Option):
     __slots__ = tuple()
+    display_name = _('broadcast')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -454,6 +465,7 @@ class DomainnameOption(Option):
     fqdn: with tld, not supported yet
     """
     __slots__ = tuple()
+    display_name = _('domain name')
 
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -552,6 +564,7 @@ class DomainnameOption(Option):
 class EmailOption(DomainnameOption):
     __slots__ = tuple()
     username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
+    display_name = _('email')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -577,6 +590,7 @@ class URLOption(DomainnameOption):
     __slots__ = tuple()
     proto_re = re.compile(r'(http|https)://')
     path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
+    display_name = _('URL')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -624,6 +638,7 @@ class UsernameOption(Option):
     __slots__ = tuple()
     #regexp build with 'man 8 adduser' informations
     username_re = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
+    display_name = _('username')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
@@ -638,6 +653,7 @@ class UsernameOption(Option):
 class FilenameOption(Option):
     __slots__ = tuple()
     path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
+    display_name = _('file name')
 
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):