Fixed a bug that caused syntax errors when defining macros or using the
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 4 Feb 2009 18:13:58 +0000 (19:13 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 4 Feb 2009 18:13:58 +0000 (19:13 +0100)
`{% call %}` tag inside loops.

This fixes #323.

--HG--
branch : trunk

CHANGES
jinja2/compiler.py
jinja2/debug.py
tests/test_forloop.py

diff --git a/CHANGES b/CHANGES
index 99113013c22a6d06e5603e27717d3681dea4804c..bf7853e074f1ca3496354fb4fb6a038e77c91122 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -10,6 +10,8 @@ Version 2.2
 - Priority of `not` raised.  It's now possible to write `not foo in bar`
   as an alias to `foo not in bar` like in python.  Previously the grammar
   required parentheses (`not (foo in bar)`) which was odd.
+- Fixed a bug that caused syntax errors when defining macros or using the
+  `{% call %}` tag inside loops.
 
 Version 2.1.1
 -------------
index 0e74faf2734c2630ab227c815b88e2a74cb6b2a0..8d605c725b675307ac85e93b885b9e2d056aaab1 100644 (file)
@@ -551,7 +551,10 @@ class CodeGenerator(NodeVisitor):
             if name not in aliases:
                 to_delete.add('l_' + name)
         if to_delete:
-            self.writeline('del ' + ', '.join(to_delete))
+            # we cannot use the del statement here because enclosed
+            # scopes can trigger a SyntaxError:
+            #   a = 42; b = lambda: a; del a
+            self.writeline(' = '.join(to_delete) + ' = missing')
 
     def function_scoping(self, node, frame, children=None,
                          find_special=True):
index 38fa012fd4f62147a07e6965645e668a6b062bec..bfd00f1037c34b6516b73782a6a5e28be0b11025 100644 (file)
@@ -11,7 +11,7 @@
     :license: BSD.
 """
 import sys
-from jinja2.utils import CodeType
+from jinja2.utils import CodeType, missing
 
 
 def translate_exception(exc_info):
@@ -47,7 +47,7 @@ def fake_exc_info(exc_info, filename, lineno, tb_back=None):
     else:
         locals = {}
     for name, value in real_locals.iteritems():
-        if name.startswith('l_'):
+        if name.startswith('l_') and value is not missing:
             locals[name[2:]] = value
 
     # if there is a local called __jinja_exception__, we get
index fa1e03bdaebc5c8a1504b33ddc1098fc63185c04..b7079c882105b50e9a727d085b44acdb684f40ba 100644 (file)
@@ -160,3 +160,18 @@ def test_recursive_empty_loop_iter(env):
     {%- for item in foo recursive -%}{%- endfor -%}
     ''')
     assert t.render(dict(foo=[])) == ''
+
+
+def test_call_in_loop(env):
+    t = env.from_string('''
+    {%- macro do_something() -%}
+        [{{ caller() }}]
+    {%- endmacro %}
+
+    {%- for i in [1, 2, 3] %}
+        {%- call do_something() -%}
+            {{ i }}
+        {%- endcall %}
+    {%- endfor -%}
+    ''')
+    assert t.render() == '[1][2][3]'