Skip to content

Commit

Permalink
Tests and docs for break/continue in templates
Browse files Browse the repository at this point in the history
  • Loading branch information
bdarnell committed Jun 25, 2012
1 parent 3e508b3 commit 9267fa3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
15 changes: 13 additions & 2 deletions tornado/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ def add(x, y):
{% apply linkify %}{{name}} said: {{message}}{% end %}
Note that as an implementation detail apply blocks are implemented
as nested functions and thus may interact strangely with variables
set via ``{% set %}``, or the use of ``{% break %}`` or ``{% continue %}``
within loops.
``{% autoescape *function* %}``
Sets the autoescape mode for the current file. This does not affect
other files, even those referenced by ``{% include %}``. Note that
Expand Down Expand Up @@ -134,7 +139,8 @@ def add(x, y):
tag will be ignored. For an example, see the ``{% block %}`` tag.
``{% for *var* in *expr* %}...{% end %}``
Same as the python ``for`` statement.
Same as the python ``for`` statement. ``{% break %}`` and
``{% continue %}`` may be used inside the loop.
``{% from *x* import *y* %}``
Same as the python ``import`` statement.
Expand Down Expand Up @@ -169,7 +175,8 @@ def add(x, y):
Same as the python ``try`` statement.
``{% while *condition* %}... {% end %}``
Same as the python ``while`` statement.
Same as the python ``while`` statement. ``{% break %}`` and
``{% continue %}`` may be used inside the loop.
"""

from __future__ import absolute_import, division, with_statement
Expand Down Expand Up @@ -817,6 +824,10 @@ def _parse(reader, template, in_block=None, in_loop=None):
# parse inner body recursively
if operator in ("for", "while"):
block_body = _parse(reader, template, operator, operator)
elif operator == "apply":
# apply creates a nested function so syntactically it's not
# in the loop.
block_body = _parse(reader, template, operator, None)
else:
block_body = _parse(reader, template, operator, in_loop)

Expand Down
32 changes: 32 additions & 0 deletions tornado/test/template_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,38 @@ def test_comment_directive(self):
template = Template(utf8("{% comment blah blah %}foo"))
self.assertEqual(template.generate(), b("foo"))

def test_break_continue(self):
template = Template(utf8("""\
{% for i in range(10) %}
{% if i == 2 %}
{% continue %}
{% end %}
{{ i }}
{% if i == 6 %}
{% break %}
{% end %}
{% end %}"""))
result = template.generate()
# remove extraneous whitespace
result = b('').join(result.split())
self.assertEqual(result, b("013456"))

def test_break_outside_loop(self):
try:
Template(utf8("{% break %}"))
raise Exception("Did not get expected exception")
except ParseError:
pass

def test_break_in_apply(self):
# This test verifies current behavior, although of course it would
# be nice if apply didn't cause seemingly unrelated breakage
try:
Template(utf8("{% for i in [] %}{% apply foo %}{% break %}{% end %}{% end %}"))
raise Exception("Did not get expected exception")
except ParseError:
pass


class StackTraceTest(LogTrapTestCase):
def test_error_line_number_expression(self):
Expand Down

0 comments on commit 9267fa3

Please sign in to comment.