summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Schneier <josh.schneier@gmail.com>2017-09-27 09:42:04 -0400
committerTim Graham <timograham@gmail.com>2017-09-27 09:42:04 -0400
commite8c45963296eb8bf3938bf9ece30b585a8cbb097 (patch)
tree8ca51dc37276b4a99b265c89d52c92bfd369388c
parent4a908c0cd23fa4da621938203ee2d910b179dbf8 (diff)
Fixed #28562 -- Fixed DecimalValidator handling of positive exponent scientific notation.
-rw-r--r--django/core/validators.py24
-rw-r--r--tests/forms_tests/field_tests/test_decimalfield.py9
-rw-r--r--tests/validators/tests.py1
3 files changed, 21 insertions, 13 deletions
diff --git a/django/core/validators.py b/django/core/validators.py
index b36ab60704..07236b7d26 100644
--- a/django/core/validators.py
+++ b/django/core/validators.py
@@ -414,15 +414,21 @@ class DecimalValidator:
def __call__(self, value):
digit_tuple, exponent = value.as_tuple()[1:]
- decimals = abs(exponent)
- # digit_tuple doesn't include any leading zeros.
- digits = len(digit_tuple)
- if decimals > digits:
- # We have leading zeros up to or past the decimal point. Count
- # everything past the decimal point as a digit. We do not count
- # 0 before the decimal point as a digit since that would mean
- # we would not allow max_digits = decimal_places.
- digits = decimals
+ if exponent >= 0:
+ # A positive exponent adds that many trailing zeros.
+ digits = len(digit_tuple) + exponent
+ decimals = 0
+ else:
+ # If the absolute value of the negative exponent is larger than the
+ # number of digits, then it's the same as the number of digits,
+ # because it'll consume all of the digits in digit_tuple and then
+ # add abs(exponent) - len(digit_tuple) leading zeros after the
+ # decimal point.
+ if abs(exponent) > len(digit_tuple):
+ digits = decimals = abs(exponent)
+ else:
+ digits = len(digit_tuple)
+ decimals = abs(exponent)
whole_digits = digits - decimals
if self.max_digits is not None and digits > self.max_digits:
diff --git a/tests/forms_tests/field_tests/test_decimalfield.py b/tests/forms_tests/field_tests/test_decimalfield.py
index 1d5d27c8a0..d3fa222228 100644
--- a/tests/forms_tests/field_tests/test_decimalfield.py
+++ b/tests/forms_tests/field_tests/test_decimalfield.py
@@ -119,11 +119,12 @@ class DecimalFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
f.clean('1.1')
def test_decimalfield_scientific(self):
- f = DecimalField(max_digits=2, decimal_places=2)
- self.assertEqual(f.clean('1E+2'), decimal.Decimal('1E+2'))
- self.assertEqual(f.clean('1e+2'), decimal.Decimal('1E+2'))
+ f = DecimalField(max_digits=4, decimal_places=2)
with self.assertRaisesMessage(ValidationError, "Ensure that there are no more"):
- f.clean('0.546e+2')
+ f.clean('1E+2')
+ self.assertEqual(f.clean('1E+1'), decimal.Decimal('10'))
+ self.assertEqual(f.clean('1E-1'), decimal.Decimal('0.1'))
+ self.assertEqual(f.clean('0.546e+2'), decimal.Decimal('54.6'))
def test_decimalfield_widget_attrs(self):
f = DecimalField(max_digits=6, decimal_places=2)
diff --git a/tests/validators/tests.py b/tests/validators/tests.py
index 4a2fe0b0c4..220219789d 100644
--- a/tests/validators/tests.py
+++ b/tests/validators/tests.py
@@ -265,6 +265,7 @@ TEST_DATA = [
(DecimalValidator(max_digits=3, decimal_places=1), Decimal('999'), ValidationError),
(DecimalValidator(max_digits=4, decimal_places=1), Decimal('999'), None),
(DecimalValidator(max_digits=20, decimal_places=2), Decimal('742403889818000000'), None),
+ (DecimalValidator(20, 2), Decimal('7.42403889818E+17'), None),
(DecimalValidator(max_digits=20, decimal_places=2), Decimal('7424742403889818000000'), ValidationError),
(DecimalValidator(max_digits=5, decimal_places=2), Decimal('7304E-1'), None),
(DecimalValidator(max_digits=5, decimal_places=2), Decimal('7304E-3'), ValidationError),