Commits

Anonymous committed 8e69315

Fixed #15789 -- Set the decimal precisio to avoid an exception in the floatformat filter, and added a few more tests. Thanks akaihola for the report, igalarzab for the patch and ptone for the review.

Comments (0)

Files changed (2)

django/template/defaultfilters.py

 import re
 import random as random_module
 import unicodedata
-from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
+from decimal import Decimal, InvalidOperation, Context, ROUND_HALF_UP
 from functools import wraps
 from pprint import pformat
 
     else:
         exp = Decimal(u'1.0') / (Decimal(10) ** abs(p))
     try:
+        # Set the precision high enough to avoid an exception, see #15789.
+        tupl = d.as_tuple()
+        units = len(tupl[1]) - tupl[2]
+        prec = abs(arg) + units + 1
+
         # Avoid conversion to scientific notation by accessing `sign`, `digits`
         # and `exponent` from `Decimal.as_tuple()` directly.
-        sign, digits, exponent = d.quantize(exp, ROUND_HALF_UP).as_tuple()
+        sign, digits, exponent = d.quantize(exp, ROUND_HALF_UP,
+            Context(prec=prec)).as_tuple()
         digits = [unicode(digit) for digit in reversed(digits)]
         while len(digits) <= abs(exponent):
             digits.append(u'0')

tests/regressiontests/defaultfilters/tests.py

 from __future__ import with_statement
 
 import datetime
+import decimal
 
 from django.template.defaultfilters import *
 from django.test import TestCase
         self.assertEqual(floatformat(11.0000, -2), u'11')
         self.assertEqual(floatformat(11.000001, -2), u'11.00')
         self.assertEqual(floatformat(8.2798, 3), u'8.280')
+        self.assertEqual(floatformat(5555.555, 2), u'5555.56')
+        self.assertEqual(floatformat(001.3000, 2), u'1.30')
+        self.assertEqual(floatformat(0.12345, 2), u'0.12')
+        self.assertEqual(floatformat(decimal.Decimal('555.555'), 2), u'555.56')
+        self.assertEqual(floatformat(decimal.Decimal('09.000')), u'9')
         self.assertEqual(floatformat(u'foo'), u'')
         self.assertEqual(floatformat(13.1031, u'bar'), u'13.1031')
         self.assertEqual(floatformat(18.125, 2), u'18.13')
 
         self.assertEqual(floatformat(FloatWrapper(11.000001), -2), u'11.00')
 
+        # Regression for #15789
+        decimal_ctx = decimal.getcontext()
+        old_prec, decimal_ctx.prec = decimal_ctx.prec, 2
+        try:
+            self.assertEqual(floatformat(1.2345, 2), u'1.23')
+            self.assertEqual(floatformat(15.2042, -3), u'15.204')
+            self.assertEqual(floatformat(decimal.Decimal('1.2345'), 2), u'1.23')
+            self.assertEqual(floatformat(decimal.Decimal('15.2042'), -3), u'15.204')
+        finally:
+            decimal_ctx.prec = old_prec
+
+
     # This fails because of Python's float handling. Floats with many zeroes
     # after the decimal point should be passed in as another type such as
     # unicode or Decimal.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.