Opened 2 years ago

Closed 2 years ago

#34014 closed Bug (fixed)

DecimalValidator fails to validate 0 in scientific notation (0E+1 or 0E+2)

Reported by: Shiplu Mokaddim Owned by: Kamil Turek
Component: Core (Other) Version: 2.0
Severity: Normal Keywords: DecimalValidator, Decimal, DecimalField
Cc: Josh Schneier Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Shiplu Mokaddim)

In 1.11.29 DecimalValidator treats 0E+1 as valid decimal

>>> from django.forms.fields import DecimalField
>>> DecimalField(max_digits=8, decimal_places=7).clean('0E+1')
Decimal('0E+1')

But in 2.0.13 it raises ValidatorError.

>>> DecimalField(max_digits=8, decimal_places=7).clean('0E+1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/amokaddim/e/fh/lib/python3.8/site-packages/django/forms/fields.py", line 150, in clean
    self.run_validators(value)
  File "/Users/amokaddim/e/fh/lib/python3.8/site-packages/django/forms/fields.py", line 141, in run_validators
    raise ValidationError(errors)
django.core.exceptions.ValidationError: <exception str() failed>

This was introduced in https://github.com/django/django/commit/7c6590af5f199c9ede970758877b5c1eb7e9b3a6#diff-d9609d8dc8482b30eac30df16213cba134562949fd62c97573927b89e880f85b

Is there any way I can prevent this validation error from happening in Django 2.0? Any flag or option that will prevent this?

Calling Decimal('0E+1').normalize() inside to_python method solves the problem. But that's a workaround!

Here is a reproducible test case.

from unittest import TestCase
from decimal import Decimal
from django.core.validators import DecimalValidator
from django.core.exceptions import ValidationError

class Test(TestCase):
    def test(self):
        value = '0E+1'
        validator = DecimalValidator(8, 7)
        try:
            validator(Decimal(value))
        except ValidationError:
            self.fail("'{}' is an invalid decimal".format(value))

Change History (8)

comment:1 by Shiplu Mokaddim, 2 years ago

Summary: django.forms.fields.DecimalValidator fails to validate 0 in scientific notationdjango.forms.fields.DecimalValidator fails to validate 0 in scientific notation (0E+1 or 0E+2)

comment:2 by Shiplu Mokaddim, 2 years ago

Description: modified (diff)

comment:3 by Mariusz Felisiak, 2 years ago

Cc: Josh Schneier added
Component: FormsCore (Other)
Summary: django.forms.fields.DecimalValidator fails to validate 0 in scientific notation (0E+1 or 0E+2)DecimalValidator fails to validate 0 in scientific notation (0E+1 or 0E+2)
Triage Stage: UnreviewedAccepted

Thanks for the report. We should fix an edge case with 0, maybe:

  • django/core/validators.py

    diff --git a/django/core/validators.py b/django/core/validators.py
    index 473203a67e..446f97af10 100644
    a b class DecimalValidator:  
    487487            )
    488488        if exponent >= 0:
    489489            # A positive exponent adds that many trailing zeros.
    490             digits = len(digit_tuple) + exponent
     490            digits = len(digit_tuple)
     491            if digit_tuple != (0,):
     492                digits += exponent
    491493            decimals = 0
    492494        else:
    493495            # If the absolute value of the negative exponent is larger than the

comment:4 by Kamil Turek, 2 years ago

Owner: changed from nobody to Kamil Turek
Status: newassigned

comment:5 by Kamil Turek, 2 years ago

Has patch: set
Triage Stage: AcceptedReady for checkin

comment:6 by Mariusz Felisiak, 2 years ago

Triage Stage: Ready for checkinAccepted

You shouldn't mark your own PRs as RFC (see docs).

comment:7 by Mariusz Felisiak, 2 years ago

Triage Stage: AcceptedReady for checkin

comment:8 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In ae509f8f:

Fixed #34014 -- Fixed DecimalValidator validating 0 in positive exponent scientific notation.

Thanks Shiplu Mokaddim for the report.

Note: See TracTickets for help on using tickets.
Back to Top