Author: mtredinnick
Date: 2007-07-13 04:09:59 -0500 (Fri, 13 Jul 2007)
New Revision: 5680

Modified:
   django/trunk/django/core/validators.py
   django/trunk/django/newforms/fields.py
   django/trunk/tests/regressiontests/forms/tests.py
Log:
Fixed #4807 -- Fixed a couple of corner cases in decimal form input validation.
Based on a suggestion from Chriss Moffit.


Modified: django/trunk/django/core/validators.py
===================================================================
--- django/trunk/django/core/validators.py      2007-07-13 08:52:07 UTC (rev 
5679)
+++ django/trunk/django/core/validators.py      2007-07-13 09:09:59 UTC (rev 
5680)
@@ -14,6 +14,10 @@
 from django.utils.functional import Promise, lazy
 from django.utils.encoding import force_unicode
 import re
+try:
+    from decimal import Decimal, DecimalException
+except ImportError:
+    from django.utils._decimal import Decimal, DecimalException    # Python 2.3
 
 _datere = r'\d{4}-\d{1,2}-\d{1,2}'
 _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?'
@@ -26,7 +30,6 @@
     r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # 
dot-atom
     
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
 # quoted-string
     r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
-decimal_re = re.compile(r'^-?(?P<digits>\d+)(\.(?P<decimals>\d+))?$')
 integer_re = re.compile(r'^-?\d+$')
 ip4_re = 
re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
 phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', 
re.IGNORECASE)
@@ -415,13 +418,15 @@
         self.max_digits, self.decimal_places = max_digits, decimal_places
 
     def __call__(self, field_data, all_data):
-        match = decimal_re.search(str(field_data))
-        if not match:
+        try:
+            val = Decimal(field_data)
+        except DecimalException:
             raise ValidationError, _("Please enter a valid decimal number.")
-        
-        digits = len(match.group('digits') or '')
-        decimals = len(match.group('decimals') or '')
-        
+
+        pieces = str(val).split('.')
+        decimals = (len(pieces) == 2) and len(pieces[1]) or 0
+        digits = len(pieces[0])
+
         if digits + decimals > self.max_digits:
             raise ValidationError, ungettext("Please enter a valid decimal 
number with at most %s total digit.",
                 "Please enter a valid decimal number with at most %s total 
digits.", self.max_digits) % self.max_digits

Modified: django/trunk/django/newforms/fields.py
===================================================================
--- django/trunk/django/newforms/fields.py      2007-07-13 08:52:07 UTC (rev 
5679)
+++ django/trunk/django/newforms/fields.py      2007-07-13 09:09:59 UTC (rev 
5680)
@@ -12,6 +12,11 @@
 from util import ErrorList, ValidationError
 from widgets import TextInput, PasswordInput, HiddenInput, 
MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple
 
+try:
+    from decimal import Decimal, DecimalException
+except ImportError:
+    from django.utils._decimal import Decimal, DecimalException
+
 __all__ = (
     'Field', 'CharField', 'IntegerField',
     'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
@@ -162,8 +167,6 @@
             raise ValidationError(ugettext('Ensure this value is greater than 
or equal to %s.') % self.min_value)
         return value
 
-decimal_re = re.compile(r'^-?(?P<digits>\d+)(\.(?P<decimals>\d+))?$')
-
 class DecimalField(Field):
     def __init__(self, max_value=None, min_value=None, max_digits=None, 
decimal_places=None, *args, **kwargs):
         self.max_value, self.min_value = max_value, min_value
@@ -181,13 +184,13 @@
         if not self.required and value in EMPTY_VALUES:
             return None
         value = value.strip()
-        match = decimal_re.search(value)
-        if not match:
+        try:
+            value = Decimal(value)
+        except DecimalException:
             raise ValidationError(ugettext('Enter a number.'))
-        else:
-            value = Decimal(value)
-        digits = len(match.group('digits') or '')
-        decimals = len(match.group('decimals') or '')
+        pieces = str(value).split('.')
+        decimals = (len(pieces) == 2) and len(pieces[1]) or 0
+        digits = len(pieces[0])
         if self.max_value is not None and value > self.max_value:
             raise ValidationError(ugettext('Ensure this value is less than or 
equal to %s.') % self.max_value)
         if self.min_value is not None and value < self.min_value:

Modified: django/trunk/tests/regressiontests/forms/tests.py
===================================================================
--- django/trunk/tests/regressiontests/forms/tests.py   2007-07-13 08:52:07 UTC 
(rev 5679)
+++ django/trunk/tests/regressiontests/forms/tests.py   2007-07-13 09:09:59 UTC 
(rev 5680)
@@ -1176,6 +1176,10 @@
 Decimal("1.5")
 >>> f.clean('0.5')
 Decimal("0.5")
+>>> f.clean('.5')
+Decimal("0.5")
+>>> f.clean('00.50')
+Decimal("0.50")
 
 # DateField ###################################################################
 


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to