diff --git a/docs/templates.rst b/docs/templates.rst index f4f7348e7..0b686865d 100644 --- a/docs/templates.rst +++ b/docs/templates.rst @@ -346,7 +346,6 @@ If you want to print a block multiple times you can however use the special

{{ self.title() }}

{% block body %}{% endblock %} - Unlike Python Jinja does not support multiple inheritance. So you can only have one extends tag called per rendering. @@ -615,6 +614,9 @@ are available on a macro object: This is `true` if the macro accesses the special `caller` variable and may be called from a :ref:`call` tag. +If a macro name starts with an underscore it's not exported and can't +be imported. + .. _call: diff --git a/examples/bench.py b/examples/bench.py index 8696be06c..49b1c752a 100644 --- a/examples/bench.py +++ b/examples/bench.py @@ -61,7 +61,7 @@ def test_jinja(): except ImportError: test_django = None else: - django_template = DjangoTemplate("""\ + django_template = """\ @@ -89,13 +89,16 @@ def test_jinja(): \ -""") +""" def test_django(): c = DjangoContext(context) c['navigation'] = [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')] - django_template.render(c) + # recompile template each rendering because that's what django + # is doing in normal situations too. Django is not thread safe + # so we can't cache it in regular apps either. + DjangoTemplate(django_template).render(c) try: from mako.template import Template as MakoTemplate diff --git a/examples/rwbench/rwbench.py b/examples/rwbench/rwbench.py index 1bde05694..742e0ea91 100644 --- a/examples/rwbench/rwbench.py +++ b/examples/rwbench/rwbench.py @@ -78,8 +78,10 @@ def test_mako(): from djangoext import django_loader, DjangoContext -django_template = django_loader.get_template('index.html') def test_django(): + # not cached because django is not thread safe and does + # not cache by itself so it would be unfair to cache it here. + django_template = django_loader.get_template('index.html') django_template.render(DjangoContext(context)) diff --git a/ext/django2jinja/django2jinja.py b/ext/django2jinja/django2jinja.py index a92781bbc..290d559f1 100644 --- a/ext/django2jinja/django2jinja.py +++ b/ext/django2jinja/django2jinja.py @@ -413,7 +413,7 @@ def if_equal(writer, node): @node(loader_tags.BlockNode) def block(writer, node): - writer.tag('block ' + node.name.replace('-', '_')) + writer.tag('block ' + node.name.replace('-', '_').rstrip('_')) node = node while node.parent is not None: node = node.parent diff --git a/jinja2/runtime.py b/jinja2/runtime.py index bb5d9fdb1..bd7e3057f 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -79,15 +79,13 @@ def super(self, name, current): """Render a parent block.""" try: blocks = self.blocks[name] - block = blocks[blocks.index(current) + 1] + index = blocks.index(current) + 1 + blocks[index] except LookupError: return self.environment.undefined('there is no parent block ' 'called %r.' % name, name='super') - wrap = self.environment.autoescape and Markup or (lambda x: x) - render = lambda: wrap(concat(block(self))) - render.__name__ = render.name = name - return render + return BlockReference(name, self, blocks, index) def get(self, key, default=None): """Returns an item from the template context, if it doesn't exist @@ -182,20 +180,44 @@ def __init__(self, context): self.__context = context def __getitem__(self, name): - func = self.__context.blocks[name][0] + blocks = self.__context.blocks[name] wrap = self.__context.environment.autoescape and \ Markup or (lambda x: x) - render = lambda: wrap(concat(func(self.__context))) - render.__name__ = render.name = name - return render + return BlockReference(name, self.__context, blocks, 0) def __repr__(self): return '<%s %r>' % ( self.__class__.__name__, - self._context.name + self.__context.name ) +class BlockReference(object): + """One block on a template reference.""" + + def __init__(self, name, context, stack, depth): + self.name = name + self._context = context + self._stack = stack + self._depth = depth + + @property + def super(self): + """Super the block.""" + if self._depth + 1 >= len(self._stack): + return self._context.environment. \ + undefined('there is no parent block called %r.' % + self.name, name='super') + return BlockReference(self.name, self._context, self._stack, + self._depth + 1) + + def __call__(self): + rv = concat(self._stack[self._depth](self._context)) + if self._context.environment.autoescape: + rv = Markup(rv) + return rv + + class LoopContext(object): """A loop context for dynamic iteration."""