Commits

Andriy Kornatskyy committed 9f015ca

Added support for None return type from value provider.

  • Participants
  • Parent commits f22815c

Comments (0)

Files changed (5)

i18n/en/LC_MESSAGES/validation.po

 msgid "Multiple input was not in a correct format."
 msgstr "Multiple input was not in a correct format."
 
-#: src/wheezy/validation/model.py:146 src/wheezy/validation/model.py:147
-#: src/wheezy/validation/model.py:150
-#, python-format
-msgid "The value '%s' is not in one of supported formats."
-msgstr "The value '%s' is not in one of supported formats."
-
-#: src/wheezy/validation/model.py:154 src/wheezy/validation/model.py:155
-#: src/wheezy/validation/model.py:158
-#, python-format
-msgid "The value '%s' is invalid."
-msgstr "The value '%s' is invalid."
-
-#: src/wheezy/validation/model.py:157 src/wheezy/validation/model.py:159
-#: src/wheezy/validation/model.py:161
+#: src/wheezy/validation/model.py:144 src/wheezy/validation/model.py:157
+#: src/wheezy/validation/model.py:159 src/wheezy/validation/model.py:161
 msgid "Input was not in a correct format."
 msgstr "Input was not in a correct format."
 
 msgid "Required field cannot be left blank."
 msgstr "Required field cannot be left blank."
 
-#: src/wheezy/validation/rules.py:77
+#: src/wheezy/validation/rules.py:77 src/wheezy/validation/rules.py:79
 msgid "Field cannot have a value."
 msgstr "Field cannot have a value."
 
 #: src/wheezy/validation/rules.py:95 src/wheezy/validation/rules.py:98
-#: src/wheezy/validation/rules.py:147
+#: src/wheezy/validation/rules.py:147 src/wheezy/validation/rules.py:150
 #, python-format
 msgid "Required to be a minimum of %(min)d characters in length."
 msgstr "Required to be a minimum of %(min)d characters in length."
 
 #: src/wheezy/validation/rules.py:100 src/wheezy/validation/rules.py:103
-#: src/wheezy/validation/rules.py:152
+#: src/wheezy/validation/rules.py:152 src/wheezy/validation/rules.py:156
 #, python-format
 msgid "The length must fall within the range %(min)d - %(max)d characters."
 msgstr "The length must fall within the range %(min)d - %(max)d characters."
 
 #: src/wheezy/validation/rules.py:107 src/wheezy/validation/rules.py:110
-#: src/wheezy/validation/rules.py:159
+#: src/wheezy/validation/rules.py:159 src/wheezy/validation/rules.py:163
 #, python-format
 msgid "Exceeds maximum length of %(max)d."
 msgstr "Exceeds maximum length of %(max)d."
 
 #: src/wheezy/validation/rules.py:232 src/wheezy/validation/rules.py:235
-#: src/wheezy/validation/rules.py:284
+#: src/wheezy/validation/rules.py:284 src/wheezy/validation/rules.py:297
 #, python-format
 msgid "The value failed equality comparison with \"%(comparand)s\"."
 msgstr "The value failed equality comparison with \"%(comparand)s\"."
 
 #: src/wheezy/validation/rules.py:238 src/wheezy/validation/rules.py:290
+#: src/wheezy/validation/rules.py:303
 #, python-format
 msgid "The value failed not equal comparison with \"%(comparand)s\"."
 msgstr "The value failed not equal comparison with \"%(comparand)s\"."
 
 #: src/wheezy/validation/rules.py:324 src/wheezy/validation/rules.py:330
-#: src/wheezy/validation/rules.py:382
+#: src/wheezy/validation/rules.py:382 src/wheezy/validation/rules.py:396
 msgid "Required to match validation pattern."
 msgstr "Required to match validation pattern."
 
 #: src/wheezy/validation/rules.py:326 src/wheezy/validation/rules.py:378
+#: src/wheezy/validation/rules.py:392
 msgid "Required to not match validation pattern."
 msgstr "Required to not match validation pattern."
 
 #: src/wheezy/validation/rules.py:354 src/wheezy/validation/rules.py:375
-#: src/wheezy/validation/rules.py:427
+#: src/wheezy/validation/rules.py:427 src/wheezy/validation/rules.py:450
 msgid ""
 "Invalid slug. The value must consist of letters, digits, underscopes and/or "
 "hyphens."
 "hyphens."
 
 #: src/wheezy/validation/rules.py:384 src/wheezy/validation/rules.py:405
-#: src/wheezy/validation/rules.py:457
+#: src/wheezy/validation/rules.py:457 src/wheezy/validation/rules.py:481
 msgid "Required to be a valid email address."
 msgstr "Required to be a valid email address."
 
 #: src/wheezy/validation/rules.py:430 src/wheezy/validation/rules.py:451
-#: src/wheezy/validation/rules.py:503
+#: src/wheezy/validation/rules.py:503 src/wheezy/validation/rules.py:528
 #, python-format
 msgid "Required to be greater or equal to %(min)s."
 msgstr "Required to be greater or equal to %(min)s."
 
 #: src/wheezy/validation/rules.py:434 src/wheezy/validation/rules.py:455
-#: src/wheezy/validation/rules.py:507
+#: src/wheezy/validation/rules.py:507 src/wheezy/validation/rules.py:533
 #, python-format
 msgid "The value must fall within the range %(min)s - %(max)s"
 msgstr "The value must fall within the range %(min)s - %(max)s"
 
 #: src/wheezy/validation/rules.py:441 src/wheezy/validation/rules.py:462
-#: src/wheezy/validation/rules.py:514
+#: src/wheezy/validation/rules.py:514 src/wheezy/validation/rules.py:540
 #, python-format
 msgid "Exceeds maximum allowed value of %(max)s."
 msgstr "Exceeds maximum allowed value of %(max)s."
 
 #: src/wheezy/validation/rules.py:655 src/wheezy/validation/rules.py:688
 #: src/wheezy/validation/rules.py:709 src/wheezy/validation/rules.py:761
+#: src/wheezy/validation/rules.py:812
 msgid "Required to be above a minimum allowed."
 msgstr "Required to be above a minimum allowed."
 
 #: src/wheezy/validation/rules.py:658 src/wheezy/validation/rules.py:679
-#: src/wheezy/validation/rules.py:731
+#: src/wheezy/validation/rules.py:731 src/wheezy/validation/rules.py:781
 msgid "The value does not belong to the list of known items."
 msgstr "The value does not belong to the list of known items."
 
 #: src/wheezy/validation/rules.py:659 src/wheezy/validation/rules.py:692
 #: src/wheezy/validation/rules.py:713 src/wheezy/validation/rules.py:765
+#: src/wheezy/validation/rules.py:817
 msgid "Must fall within a valid range."
 msgstr "Must fall within a valid range."
 
 #: src/wheezy/validation/rules.py:665 src/wheezy/validation/rules.py:698
 #: src/wheezy/validation/rules.py:719 src/wheezy/validation/rules.py:771
+#: src/wheezy/validation/rules.py:823
 msgid "Exceeds maximum allowed."
 msgstr "Exceeds maximum allowed."

i18n/ru/LC_MESSAGES/validation.po

 "%d.%m.%Y %H:%M:%S|%d.%m.%y %H:%M|%d.%m.%y %H:%M:%S|%Y-%m-%d %H:%M|"
 "%Y-%m-%d %H:%M:%S"
 
-
-#: src/wheezy/validation/model.py:70
-#, python-format
-msgid "The value '%s' is invalid."
-msgstr "Значение '%s' является неверным."
-
-#: src/wheezy/validation/model.py:108
-#, python-format
-msgid "The value '%s' is not in one of supported formats."
-msgstr "Значение '%s' не соответсвует ни одному из поддеживаемых форматов."
-
 #: src/wheezy/validation/model.py:112
 msgid "Input was not in a correct format."
 msgstr "Ввод не в правильном формате."

i18n/validation.po

 msgid "Multiple input was not in a correct format."
 msgstr "Multiple input was not in a correct format."
 
-#: src/wheezy/validation/model.py:146 src/wheezy/validation/model.py:147
-#: src/wheezy/validation/model.py:150
-#, python-format
-msgid "The value '%s' is not in one of supported formats."
-msgstr "The value '%s' is not in one of supported formats."
-
-#: src/wheezy/validation/model.py:154 src/wheezy/validation/model.py:155
-#: src/wheezy/validation/model.py:158
-#, python-format
-msgid "The value '%s' is invalid."
-msgstr "The value '%s' is invalid."
-
-#: src/wheezy/validation/model.py:157 src/wheezy/validation/model.py:159
-#: src/wheezy/validation/model.py:161
+#: src/wheezy/validation/model.py:144 src/wheezy/validation/model.py:157
+#: src/wheezy/validation/model.py:159 src/wheezy/validation/model.py:161
 msgid "Input was not in a correct format."
 msgstr "Input was not in a correct format."
 
 msgid "Required field cannot be left blank."
 msgstr "Required field cannot be left blank."
 
-#: src/wheezy/validation/rules.py:77
+#: src/wheezy/validation/rules.py:77 src/wheezy/validation/rules.py:79
 msgid "Field cannot have a value."
 msgstr "Field cannot have a value."
 
 #: src/wheezy/validation/rules.py:95 src/wheezy/validation/rules.py:98
-#: src/wheezy/validation/rules.py:147
+#: src/wheezy/validation/rules.py:147 src/wheezy/validation/rules.py:150
 #, python-format
 msgid "Required to be a minimum of %(min)d characters in length."
 msgstr "Required to be a minimum of %(min)d characters in length."
 
 #: src/wheezy/validation/rules.py:100 src/wheezy/validation/rules.py:103
-#: src/wheezy/validation/rules.py:152
+#: src/wheezy/validation/rules.py:152 src/wheezy/validation/rules.py:156
 #, python-format
 msgid "The length must fall within the range %(min)d - %(max)d characters."
 msgstr "The length must fall within the range %(min)d - %(max)d characters."
 
 #: src/wheezy/validation/rules.py:107 src/wheezy/validation/rules.py:110
-#: src/wheezy/validation/rules.py:159
+#: src/wheezy/validation/rules.py:159 src/wheezy/validation/rules.py:163
 #, python-format
 msgid "Exceeds maximum length of %(max)d."
 msgstr "Exceeds maximum length of %(max)d."
 
 #: src/wheezy/validation/rules.py:232 src/wheezy/validation/rules.py:235
-#: src/wheezy/validation/rules.py:284
+#: src/wheezy/validation/rules.py:284 src/wheezy/validation/rules.py:297
 #, python-format
 msgid "The value failed equality comparison with \"%(comparand)s\"."
 msgstr "The value failed equality comparison with \"%(comparand)s\"."
 
 #: src/wheezy/validation/rules.py:238 src/wheezy/validation/rules.py:290
+#: src/wheezy/validation/rules.py:303
 #, python-format
 msgid "The value failed not equal comparison with \"%(comparand)s\"."
 msgstr "The value failed not equal comparison with \"%(comparand)s\"."
 
 #: src/wheezy/validation/rules.py:324 src/wheezy/validation/rules.py:330
-#: src/wheezy/validation/rules.py:382
+#: src/wheezy/validation/rules.py:382 src/wheezy/validation/rules.py:396
 msgid "Required to match validation pattern."
 msgstr "Required to match validation pattern."
 
 #: src/wheezy/validation/rules.py:326 src/wheezy/validation/rules.py:378
+#: src/wheezy/validation/rules.py:392
 msgid "Required to not match validation pattern."
 msgstr "Required to not match validation pattern."
 
 #: src/wheezy/validation/rules.py:354 src/wheezy/validation/rules.py:375
-#: src/wheezy/validation/rules.py:427
+#: src/wheezy/validation/rules.py:427 src/wheezy/validation/rules.py:450
 msgid ""
 "Invalid slug. The value must consist of letters, digits, underscopes and/or "
 "hyphens."
 "hyphens."
 
 #: src/wheezy/validation/rules.py:384 src/wheezy/validation/rules.py:405
-#: src/wheezy/validation/rules.py:457
+#: src/wheezy/validation/rules.py:457 src/wheezy/validation/rules.py:481
 msgid "Required to be a valid email address."
 msgstr "Required to be a valid email address."
 
 #: src/wheezy/validation/rules.py:430 src/wheezy/validation/rules.py:451
-#: src/wheezy/validation/rules.py:503
+#: src/wheezy/validation/rules.py:503 src/wheezy/validation/rules.py:528
 #, python-format
 msgid "Required to be greater or equal to %(min)s."
 msgstr "Required to be greater or equal to %(min)s."
 
 #: src/wheezy/validation/rules.py:434 src/wheezy/validation/rules.py:455
-#: src/wheezy/validation/rules.py:507
+#: src/wheezy/validation/rules.py:507 src/wheezy/validation/rules.py:533
 #, python-format
 msgid "The value must fall within the range %(min)s - %(max)s"
 msgstr "The value must fall within the range %(min)s - %(max)s"
 
 #: src/wheezy/validation/rules.py:441 src/wheezy/validation/rules.py:462
-#: src/wheezy/validation/rules.py:514
+#: src/wheezy/validation/rules.py:514 src/wheezy/validation/rules.py:540
 #, python-format
 msgid "Exceeds maximum allowed value of %(max)s."
 msgstr "Exceeds maximum allowed value of %(max)s."
 
 #: src/wheezy/validation/rules.py:655 src/wheezy/validation/rules.py:688
 #: src/wheezy/validation/rules.py:709 src/wheezy/validation/rules.py:761
+#: src/wheezy/validation/rules.py:812
 msgid "Required to be above a minimum allowed."
 msgstr "Required to be above a minimum allowed."
 
 #: src/wheezy/validation/rules.py:658 src/wheezy/validation/rules.py:679
-#: src/wheezy/validation/rules.py:731
+#: src/wheezy/validation/rules.py:731 src/wheezy/validation/rules.py:781
 msgid "The value does not belong to the list of known items."
 msgstr "The value does not belong to the list of known items."
 
 #: src/wheezy/validation/rules.py:659 src/wheezy/validation/rules.py:692
 #: src/wheezy/validation/rules.py:713 src/wheezy/validation/rules.py:765
+#: src/wheezy/validation/rules.py:817
 msgid "Must fall within a valid range."
 msgstr "Must fall within a valid range."
 
 #: src/wheezy/validation/rules.py:665 src/wheezy/validation/rules.py:698
 #: src/wheezy/validation/rules.py:719 src/wheezy/validation/rules.py:771
+#: src/wheezy/validation/rules.py:823
 msgid "Exceeds maximum allowed."
 msgstr "Exceeds maximum allowed."

src/wheezy/validation/comp.py

 PY3 = sys.version_info[0] >= 3
 
 if PY3:  # pragma: nocover
-    ntos = lambda s: s
     iterkeys = lambda d: d.keys()
     iteritems = lambda d: d.items()
     copyitems = lambda d: list(d.items())
     regex_pattern = (str,)
 else:  # pragma: nocover
-    ntos = lambda s: s.decode('UTF-8')
     iterkeys = lambda d: d.iterkeys()
     iteritems = lambda d: d.iteritems()
     copyitems = lambda d: d.items()

src/wheezy/validation/model.py

 from decimal import Decimal
 from time import strptime
 
-from wheezy.validation.comp import ntos
 from wheezy.validation.comp import null_translations
 from wheezy.validation.comp import ref_gettext
 from wheezy.validation.format import decimal_separator
 
         Invalid values:
 
-        >>> values = {'balance': ['x'], 'age': [''], 'birthday': ['4.2.12'],
+        >>> values = {'balance': ['x'], 'age': ['x'], 'birthday': ['4.2.12'],
         ...         'prefs2': ['1', 'x']}
         >>> user = User()
         >>> try_update_model(user, values, results)
             # fallback to str provider that leaves value unchanged.
             if attr:
                 provider_name = type(attr[0]).__name__
-                try:
+                if provider_name in value_providers:
                     value_provider = value_providers[provider_name]
-                except KeyError:  # pragma: nocover
+                else:  # pragma: nocover
                     continue
             else:
                 value_provider = value_providers['str']
                 succeed = False
         else:  # A simple value attribute
             provider_name = type(attr).__name__
-            try:
+            if provider_name in value_providers:
                 value_provider = value_providers[provider_name]
-            except KeyError:  # pragma: nocover
-                continue
-            try:
                 if isinstance(value, list):
                     value = value and value[-1] or ''
-                original_value = value
-                value = value_provider(value, gettext)
-                if value is None:
+                try:
+                    value = value_provider(value, gettext)
+                    setter(model, name, value)
+                except (ArithmeticError, ValueError):
                     results[name] = [gettext(
-                        "The value '%s' is not in one of supported formats."
-                        % ntos(original_value))]
+                            "Input was not in a correct format.")]
                     succeed = False
-                else:
-                    setter(model, name, value)
-            except (ArithmeticError, ValueError):
-                if original_value:
-                    results[name] = [gettext(
-                        "The value '%s' is invalid."
-                        ) % ntos(original_value)]
-                else:
-                    results[name] = [gettext(
-                        "Input was not in a correct format.")]
-                succeed = False
     return succeed
 
 
         100
         >>> int_value_provider('1,000', lambda x: x)
         1000
+
+        Empty string value is converted to ``None``.
+
+        >>> int_value_provider(' ', lambda x: x)
     """
-    return int(str_value.replace(thousands_separator(gettext), ''))
+    str_value = str_value.strip()
+    if str_value:
+        return int(str_value.replace(thousands_separator(gettext), ''))
+    else:
+        return None
 
 
 def decimal_value_provider(str_value, gettext):
         ...         lambda x: x)
         >>> assert Decimal('1007.85') == decimal_value_provider('1,007.85',
         ...         lambda x: x)
+
+        Empty string value is converted to ``None``.
+
+        >>> decimal_value_provider(' ', lambda x: x)
     """
-    str_value = str_value.replace(thousands_separator(gettext), '')
-    str_value = '.'.join(str_value.split(decimal_separator(gettext), 1))
-    return Decimal(str_value)
+    str_value = str_value.strip()
+    if str_value:
+        str_value = str_value.replace(thousands_separator(gettext), '')
+        str_value = '.'.join(str_value.split(decimal_separator(gettext), 1))
+        return Decimal(str_value)
+    else:
+        return None
 
 
 BOOLEAN_TRUE_VALUES = ['1', 'True']
 
         >>> bool_value_provider('1', lambda x: x)
         True
-        >>> bool_value_provider('', lambda x: x)
-        False
         >>> bool_value_provider('0', lambda x: x)
         False
+
+        Empty string value is converted to ``False``.
+
+        >>> bool_value_provider(' ', lambda x: x)
+        False
     """
+    str_value = str_value.strip()
     return str_value in BOOLEAN_TRUE_VALUES
 
 
         1.5
         >>> float_value_provider('4,531.5', lambda x: x)
         4531.5
+
+        Empty string value is converted to ``None``.
+
+        >>> float_value_provider(' ', lambda x: x)
     """
-    str_value = str_value.replace(thousands_separator(gettext), '')
-    str_value = '.'.join(str_value.split(decimal_separator(gettext), 1))
-    return float(str_value)
+    str_value = str_value.strip()
+    if str_value:
+        str_value = str_value.replace(thousands_separator(gettext), '')
+        str_value = '.'.join(str_value.split(decimal_separator(gettext), 1))
+        return float(str_value)
+    else:
+        return None
 
 
 def date_value_provider(str_value, gettext):
         >>> date_value_provider('2/4/12', lambda x: x)
         datetime.date(2012, 2, 4)
 
-        If ``str_value`` is empty string, return date.min
+        Empty string value is converted to ``None``.
 
         >>> date_value_provider(' ', lambda x: x)
-        datetime.date(1, 1, 1)
 
-        If none of known formats match return None.
+        If none of known formats match raise ValueError.
 
         >>> date_value_provider('2.4.12', lambda x: x)
+        Traceback (most recent call last):
+            ...
+        ValueError
     """
     str_value = str_value.strip()
-    if not str_value:
-        return date.min
-    try:
-        return date(*strptime(
-            str_value,
-            default_date_input_format(gettext))[:3])
-    except ValueError:
-        for fmt in fallback_date_input_formats(gettext).split('|'):
-            try:
-                return date(*strptime(str_value, fmt)[:3])
-            except ValueError:
-                continue
+    if str_value:
+        try:
+            return date(*strptime(
+                str_value,
+                default_date_input_format(gettext))[:3])
+        except ValueError:
+            for fmt in fallback_date_input_formats(gettext).split('|'):
+                try:
+                    return date(*strptime(str_value, fmt)[:3])
+                except ValueError:
+                    continue
+            raise ValueError()
+    else:
         return None
 
 
         >>> time_value_provider('15:40:11', lambda x: x)
         datetime.time(15, 40, 11)
 
-        If ``str_value`` is empty string, return time.min
+        Empty string value is converted to ``None``.
 
         >>> time_value_provider(' ', lambda x: x)
-        datetime.time(0, 0)
 
-        If none of known formats match return None.
+        If none of known formats match raise ValueError.
 
         >>> time_value_provider('2.45.17', lambda x: x)
+        Traceback (most recent call last):
+            ...
+        ValueError
     """
     str_value = str_value.strip()
-    if not str_value:
-        return time.min
-    try:
-        return time(*strptime(
-            str_value,
-            default_time_input_format(gettext))[3:6])
-    except ValueError:
-        for fmt in fallback_time_input_formats(gettext).split('|'):
-            try:
-                return time(*strptime(str_value, fmt)[3:6])
-            except ValueError:
-                continue
+    if str_value:
+        try:
+            return time(*strptime(
+                str_value,
+                default_time_input_format(gettext))[3:6])
+        except ValueError:
+            for fmt in fallback_time_input_formats(gettext).split('|'):
+                try:
+                    return time(*strptime(str_value, fmt)[3:6])
+                except ValueError:
+                    continue
+            raise ValueError()
+    else:
         return None
 
 
         >>> datetime_value_provider('2008/5/18', lambda x: x)
         datetime.datetime(2008, 5, 18, 0, 0)
 
-        If ``str_value`` is empty string, return datetime.min
+        Empty string value is converted to ``None``.
 
         >>> datetime_value_provider(' ', lambda x: x)
-        datetime.datetime(1, 1, 1, 0, 0)
 
-        If none of known formats match return None.
+        If none of known formats match raise ValueError.
 
-        >>> datetime_value_provider('2.45.17', lambda x: x)
+        >>> datetime_value_provider('2.4.12', lambda x: x)
+        Traceback (most recent call last):
+            ...
+        ValueError
 
     """
     str_value = str_value.strip()
-    if not str_value:
-        return datetime.min
-    try:
-        return datetime(*strptime(
-            str_value,
-            default_datetime_input_format(gettext))[:6])
-    except ValueError:
-        for fmt in fallback_datetime_input_formats(gettext).split('|'):
-            try:
-                return datetime(*strptime(str_value, fmt)[:6])
-            except ValueError:
-                continue
-        value = date_value_provider(str_value, gettext)
-        if value is None:
-            return None
-        return datetime(value.year, value.month, value.day)
+    if str_value:
+        try:
+            return datetime(*strptime(
+                str_value,
+                default_datetime_input_format(gettext))[:6])
+        except ValueError:
+            for fmt in fallback_datetime_input_formats(gettext).split('|'):
+                try:
+                    return datetime(*strptime(str_value, fmt)[:6])
+                except ValueError:
+                    continue
+            value = date_value_provider(str_value, gettext)
+            return datetime(value.year, value.month, value.day)
+    else:
+        return None
 
 
 value_providers = {
-        'str': lambda str_value, gettext: str_value,
-        'unicode': lambda str_value, gettext: str_value.decode('UTF-8'),
+        'str': lambda str_value, gettext: str_value.strip(),
+        'unicode': lambda str_value, gettext: \
+                str_value.strip().decode('UTF-8'),
         'int': int_value_provider,
         'Decimal': decimal_value_provider,
         'bool': bool_value_provider,