Reverted [73b04625ab54]. The old behavior is the new behavior, the other
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 26 Oct 2009 10:53:27 +0000 (11:53 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 26 Oct 2009 10:53:27 +0000 (11:53 +0100)
is not consistenly implementable.

--HG--
branch : trunk

CHANGES
docs/faq.rst
jinja2/compiler.py
jinja2/runtime.py
setup.py
tests/test_old_bugs.py

diff --git a/CHANGES b/CHANGES
index 97b9b54d6fe5d97e5a0f0f19904c712b6cce4a9c..17d3d69724118746b16e3d5b128e68910794c299 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,15 +1,12 @@
 Jinja2 Changelog
 ================
 
-Version 2.3
------------
-(codename Gnok, release date to be selected.)
+Version 2.2.2
+-------------
+(bugfix release, release date to be selected.)
 
 - fixes issue with code generator that causes unbound variables
   to be generated if set was used in if-blocks.
-- added a deprecation warning for a variable assignment, scope bug
-  that exists since 2.0, code could depend on.  See :ref:`jinja-scoping-bug`
-  for more information on this problem.
 
 Version 2.2.1
 -------------
index e8ddc6a42143c7e748494e54662d0400c690ed38..5f49087e9f4249ebda4dd02662212e71674fc8be 100644 (file)
@@ -152,14 +152,10 @@ harder to maintain the code for older Python versions.  If you really need
 Python 2.3 support you either have to use `Jinja 1`_ or other templating
 engines that still support 2.3.
 
-.. _jinja-scoping-bug:
-
-Scoping Bug in Jinja2
----------------------
+My Macros are overriden by something
+------------------------------------
 
-Jinja2 currently has a scoping bug that causes confusing behavior.  If you
-have a layout template that defines a macro, and a child template that
-does the same thing, it will see the macro from the layout template:
+In some situations the Jinja scoping appears arbitrary:
 
 layout.tmpl:
 
@@ -176,17 +172,10 @@ child.tmpl:
     {% macro foo() %}CHILD{% endmacro %}
     {% block body %}{{ foo() }}{% endblock %}
 
-This will print ``LAYOUT`` in Jinja2 versions older than 2.5.  Starting
-with Jinja 2.2.2, there will however be a deprecation warning for this
-behavior.  Starting with Jinja 2.5, this behavior will change so that
-``CHILD`` is printed instead.
-
-The reason why it was not changed right away is that some templates could
-depend on macros or variables defined in the layout template to be
-available in a child template.  This however was undocumented behavior and
-is considered a bug.
-
-If you depend on this behavior, move your macros into a different file and
-import it into the layout and child template.
+This will print ``LAYOUT`` in Jinja2.  This is a side effect of having
+the parent template evaluated after the child one.  This allows child
+templates passing information to the parent template.  To avoid this
+issue rename the macro or variable in the parent template to have an
+uncommon prefix.
 
 .. _Jinja 1: http://jinja.pocoo.org/1/
index a6f26a59219558333ef140a3b8f90c6d399474ac..523b7bf8f08356970d6c59dc5e0774a5ce45863c 100644 (file)
@@ -356,6 +356,7 @@ class CodeGenerator(NodeVisitor):
         self.name = name
         self.filename = filename
         self.stream = stream
+        self.created_block_context = False
 
         # aliases for imports
         self.import_aliases = {}
@@ -736,9 +737,6 @@ class CodeGenerator(NodeVisitor):
         # overhead by just not processing any inheritance code.
         have_extends = node.find(nodes.Extends) is not None
 
-        # are there any block tags?  If yes, we need a copy of the scope.
-        have_blocks = node.find(nodes.Block) is not None
-
         # find all blocks
         for block in node.find_all(nodes.Block):
             if block.name in self.blocks:
@@ -771,8 +769,6 @@ class CodeGenerator(NodeVisitor):
         self.indent()
         if have_extends:
             self.writeline('parent_template = None')
-        if have_blocks:
-            self.writeline('block_context = context._block()')
         if 'self' in find_undeclared(node.body, ('self',)):
             frame.identifiers.add_special('self')
             self.writeline('l_self = TemplateReference(context)')
@@ -805,8 +801,6 @@ class CodeGenerator(NodeVisitor):
             if 'self' in undeclared:
                 block_frame.identifiers.add_special('self')
                 self.writeline('l_self = TemplateReference(context)')
-            if block.find(nodes.Block) is not None:
-                self.writeline('block_context = context._block(%r)' % name)
             if 'super' in undeclared:
                 block_frame.identifiers.add_special('super')
                 self.writeline('l_super = context.super(%r, '
@@ -836,10 +830,7 @@ class CodeGenerator(NodeVisitor):
                 self.writeline('if parent_template is None:')
                 self.indent()
                 level += 1
-        if node.scoped:
-            context = 'block_context.derived(locals())'
-        else:
-            context = 'block_context'
+        context = node.scoped and 'context.derived(locals())' or 'context'
         self.writeline('for event in context.blocks[%r][0](%s):' % (
                        node.name, context), node)
         self.indent()
index 4a61bf9e5b88ae443e051957fa808d38a60e85d7..b06b39cf02b4704106c74e5aa13cd72cfdf3a647 100644 (file)
@@ -111,7 +111,7 @@ class Context(object):
 
     def __init__(self, environment, parent, name, blocks):
         self.parent = parent
-        self.vars = vars = {}
+        self.vars = {}
         self.environment = environment
         self.exported_vars = set()
         self.name = name
@@ -185,16 +185,6 @@ class Context(object):
         context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
         return context
 
-    def _block(self, block=None):
-        """Creates a context that is used for block execution.  Currently this
-        returns a special `_BlockContext` that warns about changed behavior.
-        In Jinja 2.5, this will instead just return a new context with the same
-        resolve behavior.  Do not call from anywhere but the generated code!
-
-        :private:
-        """
-        return _BlockContext(self, block)
-
     def _all(meth):
         proxy = lambda self: getattr(self.get_all(), meth)()
         proxy.__doc__ = getattr(dict, meth).__doc__
@@ -232,39 +222,6 @@ class Context(object):
         )
 
 
-class _BlockContext(Context):
-    """Implements a deprecation warning for the changed block assignments."""
-    __slots__ = ('real_context', 'block_name')
-
-    def __init__(self, real_context, block_name):
-        super(_BlockContext, self).__init__(real_context.environment,
-                                            real_context.parent,
-                                            real_context.name, {})
-        self.vars = dict(real_context.vars)
-        self.exported_vars = set(real_context.exported_vars)
-        self.blocks = real_context.blocks
-        self.real_context = real_context
-        self.block_name = block_name
-
-    def resolve(self, key):
-        self_rv = super(_BlockContext, self).resolve(key)
-        base_rv = self.real_context.resolve(key)
-        if self_rv != base_rv and not isinstance(base_rv, Undefined):
-            from warnings import warn
-            if self.block_name is not None:
-                detail = 'accessing %r from inside block %r' \
-                    % (key, self.block_name)
-            else:
-                detail = 'accessing %r toplevel' % key
-            detail += ', in template %s' % self.name
-            warn(DeprecationWarning('variables set in a base template '
-                                    'will no longer leak into the child '
-                                    'context in future versions.  Happened '
-                                    'when ' + detail))
-            return base_rv
-        return self_rv
-
-
 # register the context as mapping if possible
 try:
     from collections import Mapping
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 3e80c03bdb6db378ebc5893fa917170d427fd3f1..110b73759533fb78c41ab239166bfbe857193e92 100644 (file)
@@ -78,18 +78,6 @@ def test_partial_conditional_assignments():
     assert tmpl.render(b=True) == '42'
 
 
-def test_local_macros_first():
-    raise SkipTest('Behavior will change in 2.3')
-    env = Environment(loader=DictLoader({
-        'layout.html': ('{% macro foo() %}LAYOUT{% endmacro %}'
-                        '{% block body %}{% endblock %}'),
-        'child.html': ('{% extends "layout.html" %}'
-                       '{% macro foo() %}CHILD{% endmacro %}'
-                       '{% block body %}{{ foo() }}{% endblock %}')
-    }))
-    assert env.get_template('child.html').render() == 'CHILD'
-
-
 def test_stacked_locals_scoping_bug():
     env = Environment(line_statement_prefix='#')
     t = env.from_string('''\