From 2f0d65917275c29703126bc60f753ebcea9d5a89 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 26 Oct 2009 11:53:27 +0100 Subject: [PATCH] Reverted [73b04625ab54]. The old behavior is the new behavior, the other is not consistenly implementable. --HG-- branch : trunk --- CHANGES | 9 +++------ docs/faq.rst | 27 ++++++++----------------- jinja2/compiler.py | 13 ++---------- jinja2/runtime.py | 45 +----------------------------------------- setup.py | 2 +- tests/test_old_bugs.py | 12 ----------- 6 files changed, 15 insertions(+), 93 deletions(-) diff --git a/CHANGES b/CHANGES index 97b9b54..17d3d69 100644 --- 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 ------------- diff --git a/docs/faq.rst b/docs/faq.rst index e8ddc6a..5f49087 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -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/ diff --git a/jinja2/compiler.py b/jinja2/compiler.py index a6f26a5..523b7bf 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -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() diff --git a/jinja2/runtime.py b/jinja2/runtime.py index 4a61bf9..b06b39c 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -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 diff --git a/setup.py b/setup.py index 09998a4..62cbcf5 100644 --- 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', diff --git a/tests/test_old_bugs.py b/tests/test_old_bugs.py index 3e80c03..110b737 100644 --- a/tests/test_old_bugs.py +++ b/tests/test_old_bugs.py @@ -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('''\ -- 2.26.2