Skip to content

Commit

Permalink
Fixed #11206 -- Ensure that the floatformat template filter doesn't s…
Browse files Browse the repository at this point in the history
…witch to scientific notation when asked to format a zero value with more than six decimal places. Thanks Tai Lee for the report and fix and Facundo Batista for his help when Decimal module expertise was needed.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15736 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
ramiro committed Mar 3, 2011
1 parent 9428c23 commit 3ecf628
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
14 changes: 12 additions & 2 deletions django/template/defaultfilters.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -149,9 +149,19 @@ def floatformat(text, arg=-1):
if p == 0: if p == 0:
exp = Decimal(1) exp = Decimal(1)
else: else:
exp = Decimal('1.0') / (Decimal(10) ** abs(p)) exp = Decimal(u'1.0') / (Decimal(10) ** abs(p))
try: try:
return mark_safe(formats.number_format(u'%s' % str(d.quantize(exp, ROUND_HALF_UP)), abs(p))) # 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()
digits = [unicode(digit) for digit in reversed(digits)]
while len(digits) <= abs(exponent):
digits.append(u'0')
digits.insert(-exponent, u'.')
if sign:
digits.append(u'-')
number = u''.join(reversed(digits))
return mark_safe(formats.number_format(number, abs(p)))
except InvalidOperation: except InvalidOperation:
return input_val return input_val
floatformat.is_safe = True floatformat.is_safe = True
Expand Down
16 changes: 15 additions & 1 deletion tests/regressiontests/defaultfilters/tests.py
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime import datetime
import unittest from django.utils import unittest


from django.template.defaultfilters import * from django.template.defaultfilters import *


Expand Down Expand Up @@ -29,6 +29,13 @@ def test_floatformat(self):
self.assertEqual(floatformat(u'¿Cómo esta usted?'), u'') self.assertEqual(floatformat(u'¿Cómo esta usted?'), u'')
self.assertEqual(floatformat(None), u'') self.assertEqual(floatformat(None), u'')


# Check that we're not converting to scientific notation.
self.assertEqual(floatformat(0, 6), u'0.000000')
self.assertEqual(floatformat(0, 7), u'0.0000000')
self.assertEqual(floatformat(0, 10), u'0.0000000000')
self.assertEqual(floatformat(0.000000000000000000015, 20),
u'0.00000000000000000002')

pos_inf = float(1e30000) pos_inf = float(1e30000)
self.assertEqual(floatformat(pos_inf), unicode(pos_inf)) self.assertEqual(floatformat(pos_inf), unicode(pos_inf))


Expand All @@ -46,6 +53,13 @@ def __float__(self):


self.assertEqual(floatformat(FloatWrapper(11.000001), -2), u'11.00') self.assertEqual(floatformat(FloatWrapper(11.000001), -2), u'11.00')


# 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.
@unittest.expectedFailure
def test_floatformat_fail(self):
self.assertEqual(floatformat(1.00000000000000015, 16), u'1.0000000000000002')

def test_addslashes(self): def test_addslashes(self):
self.assertEqual(addslashes(u'"double quotes" and \'single quotes\''), self.assertEqual(addslashes(u'"double quotes" and \'single quotes\''),
u'\\"double quotes\\" and \\\'single quotes\\\'') u'\\"double quotes\\" and \\\'single quotes\\\'')
Expand Down

0 comments on commit 3ecf628

Please sign in to comment.