From 9ec7d8e514e09636b0ab4bcac74b5f7a5be335a3 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 21 Oct 2017 12:24:20 +0200 Subject: [PATCH] Fixed #28730 -- Fixed loss of precision for large integer literals in templates Thanks Fraser Nevett for the report and Tim Graham for patch edits. --- django/template/base.py | 19 +++++++++---------- tests/template_tests/test_base.py | 7 ++++++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/django/template/base.py b/django/template/base.py index 10a1f11464..9c81a361f2 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -762,17 +762,16 @@ class Variable: # Note that this could cause an OverflowError here that we're not # catching. Since this should only happen at compile time, that's # probably OK. - self.literal = float(var) - - # So it's a float... is it an int? If the original value contained a - # dot or an "e" then it was a float, not an int. - if '.' not in var and 'e' not in var.lower(): - self.literal = int(self.literal) - - # "2." is invalid - if var.endswith('.'): - raise ValueError + # Try to interpret values containg a period or an 'e'/'E' + # (possibly scientific notation) as a float; otherwise, try int. + if '.' in var or 'e' in var.lower(): + self.literal = float(var) + # "2." is invalid + if var.endswith('.'): + raise ValueError + else: + self.literal = int(var) except ValueError: # A ValueError means that the variable isn't a number. if var.startswith('_(') and var.endswith(')'): diff --git a/tests/template_tests/test_base.py b/tests/template_tests/test_base.py index 5320af5e9a..4012a89f7d 100644 --- a/tests/template_tests/test_base.py +++ b/tests/template_tests/test_base.py @@ -1,4 +1,4 @@ -from django.template.base import VariableDoesNotExist +from django.template.base import Variable, VariableDoesNotExist from django.test import SimpleTestCase @@ -6,3 +6,8 @@ class VariableDoesNotExistTests(SimpleTestCase): def test_str(self): exc = VariableDoesNotExist(msg='Failed lookup in %r', params=({'foo': 'bar'},)) self.assertEqual(str(exc), "Failed lookup in {'foo': 'bar'}") + + +class VariableTests(SimpleTestCase): + def test_integer_literals(self): + self.assertEqual(Variable('999999999999999999999999999').literal, 999999999999999999999999999)