added super()
authorArmin Ronacher <armin.ronacher@active-4.com>
Sun, 13 Apr 2008 21:18:05 +0000 (23:18 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sun, 13 Apr 2008 21:18:05 +0000 (23:18 +0200)
--HG--
branch : trunk

examples/inheritance.py [new file with mode: 0644]
jinja2/compiler.py
jinja2/runtime.py

diff --git a/examples/inheritance.py b/examples/inheritance.py
new file mode 100644 (file)
index 0000000..aa687c8
--- /dev/null
@@ -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()
index bf7296389ad93fff6091f6c997574256a970ea11..4ddacd9084e994183ef77b4edb1338e066cda30a 100644 (file)
@@ -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)
index fb2802ee94538f7eb2ea1a0fcce448a302530722..9a6d9f2864fd2fe76f561ebb5dde0489d84d8a89 100644 (file)
@@ -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