added first code for parser extensions and moved some code in speedups around
--HG--
branch : trunk
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index c579395..8c58959 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -63,7 +63,19 @@
storage.extend(d.get(attr, ()))
assert len(storage) == len(set(storage))
d[attr] = tuple(storage)
- return type.__new__(cls, name, bases, d)
+ rv = type.__new__(cls, name, bases, d)
+
+ # unless the node is a subclass of `CustomNode` it may not
+ # be defined in any other module than the jinja2.nodes module.
+ # the reason for this is that the we don't want users to take
+ # advantage of the fact that the parser is using the node name
+ # only as callback name for non custom nodes. This could lead
+ # to broken code in the future and is disallowed because of this.
+ if rv.__module__ != 'jinja2.nodes' and not \
+ isinstance(rv, CustomStmt):
+ raise TypeError('non builtin node %r is not a subclass of '
+ 'CustomStmt.' % node.__class__.__name__)
+ return rv
class Node(object):
@@ -193,6 +205,15 @@
"""Nodes that exist in a specific context only."""
+class CustomStmt(Stmt):
+ """Custom statements must extend this node."""
+
+ def compile(self, compiler):
+ """The compiler calls this method to get the python sourcecode
+ for the statement.
+ """
+
+
class Template(Node):
"""Node that represents a template."""
fields = ('body',)