a clean restart
--HG--
branch : trunk
rename : jinja/__init__.py => jinja2/__init__.py
rename : jinja/_debugger.c => jinja2/_debugger.c
rename : jinja/_native.py => jinja2/_native.py
rename : jinja/_speedups.c => jinja2/_speedups.c
rename : jinja/constants.py => jinja2/constants.py
rename : jinja/contrib/__init__.py => jinja2/contrib/__init__.py
rename : jinja/contrib/_djangosupport.py => jinja2/contrib/_djangosupport.py
rename : jinja/contrib/djangosupport.py => jinja2/contrib/djangosupport.py
rename : jinja/datastructure.py => jinja2/datastructure.py
rename : jinja/defaults.py => jinja2/defaults.py
rename : jinja/environment.py => jinja2/environment.py
rename : jinja/exceptions.py => jinja2/exceptions.py
rename : jinja/filters.py => jinja2/filters.py
rename : jinja/lexer.py => jinja2/lexer.py
rename : jinja/loaders.py => jinja2/loaders.py
rename : jinja/nodes.py => jinja2/nodes.py
rename : jinja/parser.py => jinja2/parser.py
rename : jinja/tests.py => jinja2/tests.py
rename : jinja/translators/__init__.py => jinja2/translators/__init__.py
rename : jinja/translators/python.py => jinja2/translators/python.py
rename : jinja/utils.py => jinja2/utils.py
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
new file mode 100644
index 0000000..1e20096
--- /dev/null
+++ b/jinja2/nodes.py
@@ -0,0 +1,494 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.nodes
+ ~~~~~~~~~~~~
+
+ This module implements additional nodes derived from the ast base node.
+
+ It also provides some node tree helper functions like `in_lineno` and
+ `get_nodes` used by the parser and translator in order to normalize
+ python and jinja nodes.
+
+ :copyright: 2007 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+import operator
+from itertools import chain, izip
+from copy import copy
+
+
+_binop_to_func = {
+ '*': operator.mul,
+ '/': operator.truediv,
+ '//': operator.floordiv,
+ '**': operator.pow,
+ '%': operator.mod,
+ '+': operator.add,
+ '-': operator.sub
+}
+
+_uaop_to_func = {
+ 'not': operator.not_,
+ '+': operator.pos,
+ '-': operator.neg
+}
+
+
+class Impossible(Exception):
+ """
+ Raised if the node could not perform a requested action.
+ """
+
+
+class NodeType(type):
+
+ def __new__(cls, name, bases, d):
+ for attr in '_fields', '_attributes':
+ storage = []
+ for base in bases:
+ storage.extend(getattr(base, attr, ()))
+ storage.extend(d.get(attr, ()))
+ assert len(storage) == len(set(storage))
+ d[attr] = tuple(storage)
+ return type.__new__(cls, name, bases, d)
+
+
+class Node(object):
+ """
+ Base jinja node.
+ """
+ __metaclass__ = NodeType
+ _fields = ()
+ _attributes = ('lineno',)
+
+ def __init__(self, *args, **kw):
+ if args:
+ if len(args) != len(self._fields):
+ if not self._fields:
+ raise TypeError('%r takes 0 arguments' %
+ self.__class__.__name__)
+ raise TypeError('%r takes 0 or %d argument%s' % (
+ self.__class__.__name__,
+ len(self._fields),
+ len(self._fields) != 1 and 's' or ''
+ ))
+ for name, arg in izip(self._fields, args):
+ setattr(self, name, arg)
+ for attr in self._attributes:
+ setattr(self, attr, kw.pop(attr, None))
+ if kw:
+ raise TypeError('unknown keyword argument %r' %
+ iter(kw).next())
+
+ def iter_fields(self):
+ for name in self._fields:
+ try:
+ yield name, getattr(self, name)
+ except AttributeError:
+ pass
+
+ def iter_child_nodes(self):
+ for field, item in self.iter_fields():
+ if isinstance(item, list):
+ for n in item:
+ if isinstance(n, Node):
+ yield n
+ elif isinstance(item, Node):
+ yield item
+
+ def __repr__(self):
+ return '%s(%s)' % (
+ self.__class__.__name__,
+ ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
+ arg in self._fields)
+ )
+
+
+class Stmt(Node):
+ """
+ Base node for all statements.
+ """
+
+
+class Helper(Node):
+ """
+ Nodes that exist in a specific context only.
+ """
+
+
+class Template(Node):
+ """
+ Node that represents a template.
+ """
+ _fields = ('extends', 'body')
+
+
+class Output(Stmt):
+ """
+ A node that holds multiple expressions which are then printed out. This
+ is used both for the `print` statement and the regular template data.
+ """
+ _fields = ('nodes',)
+
+
+class Extends(Stmt):
+ """
+ Represents an extends statement.
+ """
+ _fields = ('extends',)
+
+
+class For(Stmt):
+ """
+ A node that represents a for loop
+ """
+ _fields = ('item', 'seq', 'body', 'else_', 'recursive')
+
+
+class If(Stmt):
+ """
+ A node that represents an if condition.
+ """
+ _fields = ('test', 'body', 'else_')
+
+
+class Macro(Stmt):
+ """
+ A node that represents a macro.
+ """
+ _fields = ('name', 'arguments', 'body')
+
+
+class CallBlock(Stmt):
+ """
+ A node that represents am extended macro call.
+ """
+ _fields = ('expr', 'body')
+
+
+class Set(Stmt):
+ """
+ Allows defining own variables.
+ """
+ _fields = ('name', 'expr')
+
+
+class FilterBlock(Stmt):
+ """
+ Node for filter sections.
+ """
+ _fields = ('body', 'filters')
+
+
+class Block(Stmt):
+ """
+ A node that represents a block.
+ """
+ _fields = ('name', 'body')
+
+
+class Include(Stmt):
+ """
+ A node that represents the include tag.
+ """
+ _fields = ('template',)
+
+
+class Trans(Stmt):
+ """
+ A node for translatable sections.
+ """
+ _fields = ('singular', 'plural', 'indicator', 'replacements')
+
+
+class ExprStmt(Stmt):
+ """
+ A statement that evaluates an expression to None.
+ """
+ _fields = ('node',)
+
+
+class Expr(Node):
+ """
+ Baseclass for all expressions.
+ """
+
+ def as_const(self):
+ """
+ Return the value of the expression as constant or raise `Impossible`
+ if this was not possible.
+ """
+ raise Impossible()
+
+ def can_assign(self):
+ """
+ Check if it's possible to assign something to this node.
+ """
+ return False
+
+
+class BinExpr(Expr):
+ """
+ Baseclass for all binary expressions.
+ """
+ _fields = ('left', 'right')
+ operator = None
+
+ def as_const(self):
+ f = _binop_to_func[self.operator]
+ try:
+ return f(self.left.as_const(), self.right.as_const())
+ except:
+ print self.left, f, self.right
+ raise Impossible()
+
+
+class UnaryExpr(Expr):
+ """
+ Baseclass for all unary expressions.
+ """
+ _fields = ('node',)
+ operator = None
+
+ def as_const(self):
+ f = _uaop_to_func[self.operator]
+ try:
+ return f(self.node.as_const())
+ except:
+ raise Impossible()
+
+
+class Name(Expr):
+ """
+ any name such as {{ foo }}
+ """
+ _fields = ('name',)
+
+ def can_assign(self):
+ return True
+
+
+class Literal(Expr):
+ """
+ Baseclass for literals.
+ """
+
+
+class Const(Literal):
+ """
+ any constat such as {{ "foo" }}
+ """
+ _fields = ('value',)
+
+ def as_const(self):
+ return self.value
+
+
+class Tuple(Literal):
+ """
+ For loop unpacking and some other things like multiple arguments
+ for subscripts.
+ """
+ _fields = ('items',)
+
+ def as_const(self):
+ return tuple(x.as_const() for x in self.items)
+
+ def can_assign(self):
+ for item in self.items:
+ if not item.can_assign():
+ return False
+ return True
+
+
+class List(Literal):
+ """
+ any list literal such as {{ [1, 2, 3] }}
+ """
+ _fields = ('items',)
+
+ def as_const(self):
+ return [x.as_const() for x in self.items]
+
+
+class Dict(Literal):
+ """
+ any dict literal such as {{ {1: 2, 3: 4} }}
+ """
+ _fields = ('items',)
+
+ def as_const(self):
+ return dict(x.as_const() for x in self.items)
+
+
+class Pair(Helper):
+ """
+ A key, value pair for dicts.
+ """
+ _fields = ('key', 'value')
+
+ def as_const(self):
+ return self.key.as_const(), self.value.as_const()
+
+
+class CondExpr(Expr):
+ """
+ {{ foo if bar else baz }}
+ """
+ _fields = ('test', 'expr1', 'expr2')
+
+ def as_const(self):
+ if self.test.as_const():
+ return self.expr1.as_const()
+ return self.expr2.as_const()
+
+
+class Filter(Expr):
+ """
+ {{ foo|bar|baz }}
+ """
+ _fields = ('node', 'filters')
+
+
+class Test(Expr):
+ """
+ {{ foo is lower }}
+ """
+ _fields = ('node', 'name', 'args')
+
+
+class Call(Expr):
+ """
+ {{ foo(bar) }}
+ """
+ _fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
+
+
+class Subscript(Expr):
+ """
+ {{ foo.bar }} and {{ foo['bar'] }} etc.
+ """
+ _fields = ('node', 'arg')
+
+ def as_const(self):
+ try:
+ return self.node.as_const()[self.node.as_const()]
+ except:
+ raise Impossible()
+
+ def can_assign(self):
+ return True
+
+
+class Slice(Expr):
+ """
+ 1:2:3 etc.
+ """
+ _fields = ('start', 'stop', 'step')
+
+
+class Concat(Expr):
+ """
+ For {{ foo ~ bar }}. Concatenates strings.
+ """
+ _fields = ('nodes',)
+
+ def as_const(self):
+ return ''.join(unicode(x.as_const()) for x in self.nodes)
+
+
+class Compare(Expr):
+ """
+ {{ foo == bar }}, {{ foo >= bar }} etc.
+ """
+ _fields = ('expr', 'ops')
+
+
+class Mul(BinExpr):
+ """
+ {{ foo * bar }}
+ """
+ operator = '*'
+
+
+class Div(BinExpr):
+ """
+ {{ foo / bar }}
+ """
+ operator = '/'
+
+
+class FloorDiv(BinExpr):
+ """
+ {{ foo // bar }}
+ """
+ operator = '//'
+
+
+class Add(BinExpr):
+ """
+ {{ foo + bar }}
+ """
+ operator = '+'
+
+
+class Sub(BinExpr):
+ """
+ {{ foo - bar }}
+ """
+ operator = '-'
+
+
+class Mod(BinExpr):
+ """
+ {{ foo % bar }}
+ """
+ operator = '%'
+
+
+class Pow(BinExpr):
+ """
+ {{ foo ** bar }}
+ """
+ operator = '**'
+
+
+class And(BinExpr):
+ """
+ {{ foo and bar }}
+ """
+ operator = 'and'
+
+ def as_const(self):
+ return self.left.as_const() and self.right.as_const()
+
+
+class Or(BinExpr):
+ """
+ {{ foo or bar }}
+ """
+ operator = 'or'
+
+ def as_const(self):
+ return self.left.as_const() or self.right.as_const()
+
+
+class Not(UnaryExpr):
+ """
+ {{ not foo }}
+ """
+ operator = 'not'
+
+
+class NegExpr(UnaryExpr):
+ """
+ {{ -foo }}
+ """
+ operator = '-'
+
+
+class PosExpr(UnaryExpr):
+ """
+ {{ +foo }}
+ """
+ operator = '+'