Description
Larger floats are not failing DecimalField
validation.
For example:
>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(200000000000.0)
>>> Decimal('2E+11')
I would expect a ValidationError
to be raised since that number has more than 3 digits. Django's form validation throws the expected error:
>>> forms.DecimalField(max_digits=3, decimal_places=1).clean(200000000000.0)
ValidationError: [u'Ensure that there are no more than 3 digits in total.']
ValidationError
is raised if you drop a zero from the above sample input:
>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(20000000000.0)
ValidationError: [u'Ensure that there are no more than 3 digits in total.']
Similarly, the exception is also raised using the original number but as a Decimal
and int:
>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(200000000000)
ValidationError: [u'Ensure that there are no more than 3 digits in total.']
>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(Decimal('200000000000.0'))
ValidationError: [u'Ensure that there are no more than 3 digits in total.']
A key line recently changed in #2948 but it doesn't seem correct and deviates from Django's forms.DecimalField
validation which otherwise appears to have been copied verbatim:
decimals = exponent * decimal.Decimal(-1) if exponent < 0 else 0
I don't really understand the original issue addressed in #2948 so I don't know why the line changed. I'm more than happy to work on the issue if I understand the original issue.
Below is a patch with a failing test:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 0427873..cf41a5b 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -773,6 +773,7 @@ class TestDecimalField(FieldValues):
(Decimal('Nan'), ["A valid number is required."]),
(Decimal('Inf'), ["A valid number is required."]),
('12.345', ["Ensure that there are no more than 3 digits in total."]),
+ (200000000000.0, ["Ensure that there are no more than 3 digits in total."]),
('0.01', ["Ensure that there are no more than 1 decimal places."]),
(123, ["Ensure that there are no more than 2 digits before the decimal point."])
)