summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2008-09-23 22:52:46 +0200
committerArmin Ronacher <armin.ronacher@active-4.com>2008-09-23 22:52:46 +0200
commit7966895d0dd38ca2c2362640e528933d55686b51 (patch)
treef76b961a0b84ecc5b04fad9110d338204b8595d9
parent234cad6f6100ebdeb35ab8bd9307cd328cd4c1d9 (diff)
downloadjinja2-7966895d0dd38ca2c2362640e528933d55686b51.tar.gz
The hopefully final fix for the bug apollo13 spotted earlier.
--HG-- branch : trunk
-rw-r--r--jinja2/compiler.py20
-rw-r--r--tests/test_old_bugs.py14
2 files changed, 22 insertions, 12 deletions
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index f3b8d6d..0686c84 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -138,9 +138,9 @@ class Frame(object):
# situations.
self.rootlevel = False
- # An extends statement flags the frame as silent if it occours.
- # This is used to suppress unwanted output.
- self.silent = False
+ # in some dynamic inheritance situations the compiler needs to add
+ # write tests around output statements.
+ self.require_output_check = parent and parent.require_output_check
# inside some tags we are using a buffer rather than yield statements.
# this for example affects {% filter %} or {% macro %}. If a frame
@@ -682,6 +682,7 @@ class CodeGenerator(NodeVisitor):
frame = Frame()
frame.inspect(node.body)
frame.toplevel = frame.rootlevel = True
+ frame.require_output_check = have_extends and not self.has_known_extends
self.indent()
if have_extends:
self.writeline('parent_template = None')
@@ -757,7 +758,6 @@ class CodeGenerator(NodeVisitor):
if not frame.toplevel:
self.fail('cannot use extend from a non top-level scope',
node.lineno)
- frame.silent = True
# if the number of extends statements in general is zero so
# far, we don't have to add a check if something extended
@@ -773,12 +773,12 @@ class CodeGenerator(NodeVisitor):
self.indent()
self.writeline('raise TemplateRuntimeError(%r)' %
'extended multiple times')
+ self.outdent()
# if we have a known extends already we don't need that code here
# as we know that the template execution will end here.
if self.has_known_extends:
raise CompilerExit()
- self.outdent()
self.writeline('parent_template = environment.get_template(', node)
self.visit(node.template, frame)
@@ -1058,8 +1058,8 @@ class CodeGenerator(NodeVisitor):
def visit_Output(self, node, frame):
# if we have a known extends statement, we don't output anything
- # if we are in a silent section
- if self.has_known_extends and frame.silent:
+ # if we are in a require_output_check section
+ if self.has_known_extends and frame.require_output_check:
return
if self.environment.finalize:
@@ -1069,11 +1069,9 @@ class CodeGenerator(NodeVisitor):
self.newline(node)
- # if we are not in a block and there was already an extends
- # statement we have to add a check that disables our yield(s) here
- # so that they don't appear in the output.
+ # if we are inside a frame that requires output checking, we do so
outdent_later = False
- if frame.silent and self.extends_so_far != 0:
+ if frame.require_output_check:
self.writeline('if parent_template is None:')
self.indent()
outdent_later = True
diff --git a/tests/test_old_bugs.py b/tests/test_old_bugs.py
index 08db225..62a9cd6 100644
--- a/tests/test_old_bugs.py
+++ b/tests/test_old_bugs.py
@@ -8,7 +8,8 @@
:copyright: Copyright 2008 by Armin Ronacher.
:license: BSD.
"""
-from jinja2 import Environment
+from jinja2 import Environment, DictLoader
+
def test_keyword_folding():
env = Environment()
@@ -16,3 +17,14 @@ def test_keyword_folding():
assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
.render() == 'teststuff'
+
+def test_extends_output_bugs():
+ env = Environment(loader=DictLoader({
+ 'parent.html': '(({% block title %}{% endblock %}))'
+ }))
+
+ t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
+ '[[{% block title %}title{% endblock %}]]'
+ '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
+ assert t.render(expr=False) == '[[title]](1)(2)(3)'
+ assert t.render(expr=True) == '((title))'