From: Ben Darnell Date: Mon, 25 Jun 2012 02:52:53 +0000 (-0700) Subject: Tests and docs for break/continue in templates X-Git-Tag: v2.4.0~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9267fa3bb09dfe77468f1a33be20d8cb12c05897;p=thirdparty%2Ftornado.git Tests and docs for break/continue in templates --- diff --git a/tornado/template.py b/tornado/template.py index 64d8391ea..13eb78081 100644 --- a/tornado/template.py +++ b/tornado/template.py @@ -101,6 +101,11 @@ with ``{# ... #}``. {% 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 @@ -134,7 +139,8 @@ with ``{# ... #}``. 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. @@ -169,7 +175,8 @@ with ``{# ... #}``. 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 @@ -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) diff --git a/tornado/test/template_test.py b/tornado/test/template_test.py index d70e4875c..a4b9453b7 100644 --- a/tornado/test/template_test.py +++ b/tornado/test/template_test.py @@ -115,6 +115,38 @@ try{% set y = 1/x %} 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):