aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.rst2
-rw-r--r--docs/templates.rst19
-rw-r--r--jinja2/lexer.py9
-rw-r--r--tests/test_lexnparse.py33
4 files changed, 41 insertions, 22 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index ae7f9d60..0ee53241 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -21,6 +21,8 @@ unreleased
- Added a ``default`` parameter for the ``map`` filter. (`#557`_)
- Exclude environment globals from
:func:`meta.find_undeclared_variables`. #931
+- Float literals can be written with scientific notation, like
+ ``{{ 2.56e-3 }}``. #912, #922
.. _#557: https://github.com/pallets/jinja/issues/557
.. _#765: https://github.com/pallets/jinja/issues/765
diff --git a/docs/templates.rst b/docs/templates.rst
index 9da05773..88df9167 100644
--- a/docs/templates.rst
+++ b/docs/templates.rst
@@ -396,7 +396,7 @@ this template, it first locates the parent. The extends tag should be the
first tag in the template. Everything before it is printed out normally and
may cause confusion. For details about this behavior and how to take
advantage of it, see :ref:`null-master-fallback`. Also a block will always be
-filled in regardless of whether the surrounding condition is evaluated to be true
+filled in regardless of whether the surrounding condition is evaluated to be true
or false.
The filename of the template depends on the template loader. For example, the
@@ -1178,17 +1178,12 @@ for Python objects such as strings and numbers. The following literals exist:
template).
42:
- Integers numbers are created by just writing the number down.
- If a dot is present, the number will be considered a float, otherwise an
- integer. Keep in mind that, in Python, ``42`` and ``42.0``
- are different (``int`` and ``float``, respectively).
-
-42.23 / 42e2 / 42E2 / 1e0:
- Floating point numbers are created by just writing the
- number down. Floating points can be written using the dot as a decimal mark,
- or they can be written in scientific notation in which
- case you can use lower case 'e' or upper case 'E' to indicate the exponent
- part.
+ Integers are whole numbers without a decimal part.
+
+42.23 / 42.1e2:
+ Floating point numbers can be written using a '.' as a decimal mark.
+ They can also be written in scientific notation with an upper or
+ lower case 'e' to indicate the exponent part.
['list', 'of', 'objects']:
Everything between two brackets is a list. Lists are useful for storing
diff --git a/jinja2/lexer.py b/jinja2/lexer.py
index 119dc99d..d8812c9b 100644
--- a/jinja2/lexer.py
+++ b/jinja2/lexer.py
@@ -15,6 +15,7 @@
:license: BSD, see LICENSE for more details.
"""
import re
+from ast import literal_eval
from collections import deque
from operator import itemgetter
@@ -22,8 +23,6 @@ from jinja2._compat import implements_iterator, intern, iteritems, text_type
from jinja2.exceptions import TemplateSyntaxError
from jinja2.utils import LRUCache
-from ast import literal_eval # to support scientific notation
-
# cache for the lexers. Exists in order to be able to have multiple
# environments with the same lexer
_lexer_cache = LRUCache(50)
@@ -54,11 +53,7 @@ else:
del jinja2._identifier
del _identifier
-# Note: Float now supports 0 or 1 dots, and must thus be evaluated in the right
-# order so that pure integers are caught first. Floats can now be written with
-# scientific notation.
-float_re = re.compile(r'(?<!\.)\d+\.?\d+(?:e-?\d+)?', re.IGNORECASE)
-
+float_re = re.compile(r'(?<!\.)\d+(?:\.\d+)?(?:e[+\-]?\d+)?', re.IGNORECASE)
newline_re = re.compile(r'(\r\n|\r|\n)')
# internal the tokens and keep references to them
diff --git a/tests/test_lexnparse.py b/tests/test_lexnparse.py
index f3adeb46..454a67b0 100644
--- a/tests/test_lexnparse.py
+++ b/tests/test_lexnparse.py
@@ -336,9 +336,36 @@ class TestSyntax(object):
tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
assert tmpl.render() == 'True|False'
- def test_literals(self, env):
- tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
- assert tmpl.render().lower() == '[]|{}|()'
+ @pytest.mark.parametrize("value", ("[]", "{}", "()"))
+ def test_collection_literal(self, env, value):
+ t = env.from_string("{{ %s }}" % value)
+ assert t.render() == value
+
+ @pytest.mark.parametrize("value", ("1", "123"))
+ def test_int_literal(self, env, value):
+ t = env.from_string("{{ %s }}" % value)
+ assert t.render() == value
+
+ @pytest.mark.parametrize(
+ "value",
+ (
+ "1.2",
+ "34.56",
+ ("1e0", "1.0"),
+ ("10e1", "100.0"),
+ ("2.5e100", "2.5e+100"),
+ "2.5e+100",
+ ("25.6e-10", "2.56e-09"),
+ ),
+ )
+ def test_float_literal(self, env, value):
+ if isinstance(value, tuple):
+ value, expect = value
+ else:
+ expect = value
+
+ t = env.from_string("{{ %s }}" % value)
+ assert t.render() == expect
def test_bool(self, env):
tmpl = env.from_string('{{ true and false }}|{{ false '