fixes issue with code generator that causes unbound variables
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 16 Sep 2009 22:48:41 +0000 (00:48 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 16 Sep 2009 22:48:41 +0000 (00:48 +0200)
to be generated if set was used in if-blocks.

--HG--
branch : trunk

CHANGES
jinja2/compiler.py
setup.py
tests/test_old_bugs.py

diff --git a/CHANGES b/CHANGES
index 65a37b0c1d3c4d68e3ac516d2a5a83b41645e97c..f9f94990b806d83ee46924c66e03d103300abc91 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,13 @@
 Jinja2 Changelog
 ================
 
+Version 2.2.2
+-------------
+(bugfix release, to be released soon)
+
+- fixes issue with code generator that causes unbound variables
+  to be generated if set was used in if-blocks.
+
 Version 2.2.1
 -------------
 (bugfix release, released on September 14th 2009)
index fa79f0ba0a586b091ded67c75352c36687e6bbbf..33aadc3348df102593bddf0da9a1154e2f0e709f 100644 (file)
@@ -265,6 +265,30 @@ class FrameIdentifierVisitor(NodeVisitor):
              self.identifiers.is_declared(node.name, self.hard_scope):
             self.identifiers.undeclared.add(node.name)
 
+    def visit_If(self, node):
+        self.visit(node.test)
+
+        # remember all the names that are locally assigned in the body
+        old_locals = self.identifiers.declared_locally.copy()
+        for subnode in node.body:
+            self.visit(subnode)
+        body = self.identifiers.declared_locally - old_locals
+
+        # same for else.
+        self.identifiers.declared_locally = old_locals.copy()
+        for subnode in node.else_ or ():
+            self.visit(subnode)
+        else_ = self.identifiers.declared_locally - old_locals
+
+        # the differences between the two branches are also pulled as
+        # undeclared variables
+        self.identifiers.undeclared.update(body.symmetric_difference(else_))
+
+        # declared_locally is currently the set of all variables assigned
+        # in the else part, add the new vars from body as well.  That means
+        # that undeclared variables if unbalanced are considered local.
+        self.identifiers.declared_locally.update(body)
+
     def visit_Macro(self, node):
         self.identifiers.declared_locally.add(node.name)
 
index 09998a49744503a39039855b1ad73427a471379b..62cbcf5c2013cff81913b90f71719d2c9bf0fcb1 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -49,7 +49,7 @@ from distutils.errors import CCompilerError, DistutilsPlatformError
 
 setup(
     name='Jinja2',
-    version='2.3',
+    version='2.2.2',
     url='http://jinja.pocoo.org/',
     license='BSD',
     author='Armin Ronacher',
index 92fb43a7fd3c0927429a726f8f0f3e4ed3ddea06..bea07dc2ff30eabd7cd3786312d911f5b9d51fc9 100644 (file)
@@ -69,3 +69,9 @@ def test_old_macro_loop_scoping_bug():
     tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
                            '{% macro i() %}3{% endmacro %}{{ i() }}')
     assert tmpl.render() == '123'
+
+
+def test_partial_conditional_assignments():
+    tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
+    assert tmpl.render(a=23) == '23'
+    assert tmpl.render(b=True) == '42'