#34363 closed Bug (fixed)
floatformat() crashes on "0.0000"
Reported by: | Takis Issaris | Owned by: | Takis Issaris |
---|---|---|---|
Component: | Template system | Version: | 4.2 |
Severity: | Release blocker | Keywords: | filters |
Cc: | David Wobrock | 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
Similar to #34272 the current Django code (both 4.2b1 and latest git) crash on using the floatformat
template filter with
0 values.
from decimal import Decimal from django.template.defaultfilters import floatformat floatformat('0.0000', 2) floatformat(Decimal('0.0000'), 2)
Both throw ValueError: valid range for prec is [1, MAX_PREC]
Using git bisect
I tracked the bug to commit 08c5a787262c1ae57f6517d4574b54a5fcaad124.
When one uses "0.0000": floatformat:2
the current code results in a precision of 0 which is
not allowed:
tupl = d.as_tuple() # with d being "0.0000" returns (sign=0,digits=(0,),exponent=-4) units = len(tupl[1]) # equals 1 units += -tupl[2] if m else tupl[2] # 1 + (-4) prec = abs(p) + units + 1 # 2 (number of requested decimals) + (-3) + 1 equals 0 rounded_d = d.quantize(exp, ROUND_HALF_UP, Context(prec=prec))
Attachments (1)
Change History (8)
by , 21 months ago
Attachment: | ic-20230222T1222-django-floatformat.diff added |
---|
comment:1 by , 21 months ago
A minimal patch is available on this branch on GitHub:
https://github.com/takis/django/tree/ticket_34363
comment:2 by , 21 months ago
Cc: | added |
---|---|
Owner: | changed from | to
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
Thanks for the report! Please submit PR via GitHub.
comment:4 by , 21 months ago
My actual code was different, but I had tried to keep the patch-size minimal.
The code I was using in a separate test-file in which I factored out the get_precision function for easier
testing. But I figured this might not be OK for performance reasons for Django.
def get_precision(d: Decimal, p: int) -> int: """Return the number of significant digits for a decimal number. d: the decimal number p: the number of decimals requested """ if d == 0: # If the number is zero, the precision is the number of decimals requested return p _, digits, exponent = d.as_tuple() units = len(digits) # total number of digits before_comma = units + exponent # adding 1 for possible rounding up e.g. (99.99, 1) -> 100.0 needs 4 digits prec = abs(p) + before_comma + 1 return max(1, prec) # 1 is the minimum precision for Decimal.quantize()
comment:5 by , 21 months ago
Triage Stage: | Accepted → Ready for checkin |
---|
Fix floatformat for zero values