Permalink
Browse files

Made it possible to refer to names from outer scopes in included temp…

…lates

that were unused in the callers frame (#327).

--HG--
branch : trunk
  • Loading branch information...
1 parent 7850dc5 commit 7887a8c63c482d99efcb9a2b69eefd2d70afd327 @mitsuhiko mitsuhiko committed Feb 8, 2009
Showing with 31 additions and 1 deletion.
  1. +2 −0 CHANGES
  2. +14 −0 jinja2/compiler.py
  3. +15 −1 tests/test_imports.py
View
@@ -13,6 +13,8 @@ Version 2.2
- Fixed a bug that caused syntax errors when defining macros or using the
`{% call %}` tag inside loops.
- Fixed a bug in the parser that made ``{{ foo[1, 2] }}`` impossible.
+- Made it possible to refer to names from outer scopes in included templates
+ that were unused in the callers frame (#327)
Version 2.1.1
-------------
View
@@ -520,6 +520,16 @@ def pull_dependencies(self, nodes):
self.writeline('%s = environment.%s[%r]' %
(mapping[name], dependency, name))
+ def unoptimize_scope(self, frame):
+ """Disable Python optimizations for the frame."""
+ # XXX: this is not that nice but it has no real overhead. It
+ # mainly works because python finds the locals before dead code
+ # is removed. If that breaks we have to add a dummy function
+ # that just accepts the arguments and does nothing.
+ if frame.identifiers.declared:
+ self.writeline('if 0: dummy(%s)' % ', '.join(
+ 'l_' + name for name in frame.identifiers.declared))
+
def push_scope(self, frame, extra_vars=()):
"""This function returns all the shadowed variables in a dict
in the form name: alias and will write the required assignments
@@ -821,6 +831,8 @@ def visit_Extends(self, node, frame):
def visit_Include(self, node, frame):
"""Handles includes."""
+ if node.with_context:
+ self.unoptimize_scope(frame)
if node.ignore_missing:
self.writeline('try:')
self.indent()
@@ -852,6 +864,8 @@ def visit_Include(self, node, frame):
def visit_Import(self, node, frame):
"""Visit regular imports."""
+ if node.with_context:
+ self.unoptimize_scope(frame)
self.writeline('l_%s = ' % node.target, node)
if frame.toplevel:
self.write('context.vars[%r] = ' % node.target)
View
@@ -13,7 +13,8 @@
test_env = Environment(loader=DictLoader(dict(
module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
- header='[{{ foo }}|{{ 23 }}]'
+ header='[{{ foo }}|{{ 23 }}]',
+ o_printer='({{ o }})'
)))
test_env.globals['bar'] = 23
@@ -80,3 +81,16 @@ def test_exports():
assert not hasattr(m, '__missing')
assert m.variable == 42
assert not hasattr(m, 'notthere')
+
+
+def test_unoptimized_scopes():
+ t = test_env.from_string("""
+ {% macro outer(o) %}
+ {% macro inner() %}
+ {% include "o_printer" %}
+ {% endmacro %}
+ {{ inner() }}
+ {% endmacro %}
+ {{ outer("FOO") }}
+ """)
+ assert t.render().strip() == '(FOO)'

0 comments on commit 7887a8c

Please sign in to comment.