From 62f8a2984c8b2ffc712ae7bbed6cf4e59eaa2dbe Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 13 Apr 2008 23:18:05 +0200 Subject: [PATCH] added super() --HG-- branch : trunk --- examples/inheritance.py | 12 ++++++++++++ jinja2/compiler.py | 2 ++ jinja2/runtime.py | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 examples/inheritance.py diff --git a/examples/inheritance.py b/examples/inheritance.py new file mode 100644 index 0000000..aa687c8 --- /dev/null +++ b/examples/inheritance.py @@ -0,0 +1,12 @@ +from jinja2 import Environment +from jinja2.loaders import DictLoader + + +env = Environment(loader=DictLoader({ +'a': '''[A[{% block body %}{% endblock %}]]''', +'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''', +'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}''' +})) + + +print env.get_template('c').render() diff --git a/jinja2/compiler.py b/jinja2/compiler.py index bf72963..4ddacd9 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -491,6 +491,8 @@ class CodeGenerator(NodeVisitor): block_frame = Frame() block_frame.inspect(block.body) block_frame.block = name + block_frame.identifiers.add_special('super') + block_frame.name_overrides['super'] = 'context.super(%r)' % name self.writeline('def block_%s(context, environment=environment):' % name, block, 1) self.pull_locals(block_frame) diff --git a/jinja2/runtime.py b/jinja2/runtime.py index fb2802e..9a6d9f2 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -56,8 +56,17 @@ class TemplateContext(dict): # are a template context, this template is participating in a template # inheritance chain and we have to copy the blocks over. if not standalone and isinstance(globals, TemplateContext): - for name, parent_blocks in globals.blocks.iteritems(): - self.blocks.setdefault(name, []).extend(parent_blocks) + for name, parent_blocks in globals.blocks.iteritems(): + self.blocks.setdefault(name, []).extend(parent_blocks) + + def super(self, block): + """Render a parent block.""" + try: + func = self.blocks[block][-2] + except LookupError: + return Undefined('super', extra='there is probably no parent ' + 'block with this name') + return SuperBlock(block, self, func) def __setitem__(self, key, value): """If we set items to the dict we track the variables set so @@ -92,6 +101,24 @@ class TemplateContext(dict): ) +class SuperBlock(object): + """When called this renders a parent block.""" + + def __init__(self, name, context, render_func): + self.name = name + self._context = context + self._render_func = render_func + + def __call__(self): + return TemplateData(u''.join(self._render_func(self._context))) + + def __repr__(self): + return '<%s %r>' % ( + self.__class__.__name__, + self.name + ) + + class IncludedTemplate(object): """Represents an included template.""" @@ -256,7 +283,7 @@ class Undefined(object): self._undefined_hint += ' (' + extra + ')' def fail(self, *args, **kwargs): - raise TypeError(self._undefined_hint) + raise NameError(self._undefined_hint) __getattr__ = __getitem__ = __add__ = __mul__ = __div__ = \ __realdiv__ = __floordiv__ = __mod__ = __pos__ = __neg__ = \ __call__ = fail -- 2.26.2