Fixed #28562 -- Fixed DecimalValidator handling of positive exponent scientific notation.
This commit is contained in:
parent
4a908c0cd2
commit
e8c4596329
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue