blob: dc8cc0b8819806a3ba251ba3a6bd1fcb0f7edc33 [file] [log] [blame]
Armin Ronacher07bc6842008-03-31 14:18:49 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.nodes
4 ~~~~~~~~~~~~
5
6 This module implements additional nodes derived from the ast base node.
7
8 It also provides some node tree helper functions like `in_lineno` and
9 `get_nodes` used by the parser and translator in order to normalize
10 python and jinja nodes.
11
12 :copyright: 2007 by Armin Ronacher.
13 :license: BSD, see LICENSE for more details.
14"""
15import operator
16from itertools import chain, izip
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020017from collections import deque
Armin Ronacher07bc6842008-03-31 14:18:49 +020018from copy import copy
19
20
21_binop_to_func = {
22 '*': operator.mul,
23 '/': operator.truediv,
24 '//': operator.floordiv,
25 '**': operator.pow,
26 '%': operator.mod,
27 '+': operator.add,
28 '-': operator.sub
29}
30
31_uaop_to_func = {
32 'not': operator.not_,
33 '+': operator.pos,
34 '-': operator.neg
35}
36
37
38class Impossible(Exception):
Armin Ronacher8efc5222008-04-08 14:47:40 +020039 """Raised if the node could not perform a requested action."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020040
41
42class NodeType(type):
Armin Ronacher8efc5222008-04-08 14:47:40 +020043 """A metaclass for nodes that handles the field and attribute
44 inheritance. fields and attributes from the parent class are
45 automatically forwarded to the child."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020046
47 def __new__(cls, name, bases, d):
Armin Ronachere791c2a2008-04-07 18:39:54 +020048 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020049 storage = []
50 for base in bases:
51 storage.extend(getattr(base, attr, ()))
52 storage.extend(d.get(attr, ()))
53 assert len(storage) == len(set(storage))
54 d[attr] = tuple(storage)
55 return type.__new__(cls, name, bases, d)
56
57
58class Node(object):
Armin Ronacher8efc5222008-04-08 14:47:40 +020059 """Baseclass for all Jinja nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020060 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020061 fields = ()
62 attributes = ('lineno',)
Armin Ronacher07bc6842008-03-31 14:18:49 +020063
64 def __init__(self, *args, **kw):
65 if args:
Armin Ronachere791c2a2008-04-07 18:39:54 +020066 if len(args) != len(self.fields):
67 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020068 raise TypeError('%r takes 0 arguments' %
69 self.__class__.__name__)
70 raise TypeError('%r takes 0 or %d argument%s' % (
71 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +020072 len(self.fields),
73 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +020074 ))
Armin Ronachere791c2a2008-04-07 18:39:54 +020075 for name, arg in izip(self.fields, args):
Armin Ronacher07bc6842008-03-31 14:18:49 +020076 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +020077 for attr in self.attributes:
Armin Ronacher07bc6842008-03-31 14:18:49 +020078 setattr(self, attr, kw.pop(attr, None))
79 if kw:
80 raise TypeError('unknown keyword argument %r' %
81 iter(kw).next())
82
83 def iter_fields(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020084 """Iterate over all fields."""
85 for name in self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020086 try:
87 yield name, getattr(self, name)
88 except AttributeError:
89 pass
90
91 def iter_child_nodes(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020092 """Iterate over all child nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020093 for field, item in self.iter_fields():
94 if isinstance(item, list):
95 for n in item:
96 if isinstance(n, Node):
97 yield n
98 elif isinstance(item, Node):
99 yield item
100
Armin Ronachere791c2a2008-04-07 18:39:54 +0200101 def find(self, node_type):
102 """Find the first node of a given type."""
103 for result in self.find_all(node_type):
104 return result
105
106 def find_all(self, node_type):
107 """Find all the nodes of a given type."""
108 for child in self.iter_child_nodes():
109 if isinstance(child, node_type):
110 yield child
111 for result in child.find_all(node_type):
112 yield result
113
114 def set_ctx(self, ctx):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200115 """Reset the context of a node and all child nodes. Per default the
116 parser will all generate nodes that have a 'load' context as it's the
117 most common one. This method is used in the parser to set assignment
118 targets and other nodes to a store context.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200119 """
120 todo = deque([self])
121 while todo:
122 node = todo.popleft()
123 if 'ctx' in node.fields:
124 node.ctx = ctx
125 todo.extend(node.iter_child_nodes())
126
Armin Ronacher07bc6842008-03-31 14:18:49 +0200127 def __repr__(self):
128 return '%s(%s)' % (
129 self.__class__.__name__,
130 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200131 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200132 )
133
134
135class Stmt(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200136 """Base node for all statements."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200137
138
139class Helper(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200140 """Nodes that exist in a specific context only."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200141
142
143class Template(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200144 """Node that represents a template."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200145 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200146
147
148class Output(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200149 """A node that holds multiple expressions which are then printed out.
150 This is used both for the `print` statement and the regular template data.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200151 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200152 fields = ('nodes',)
153
154 def optimized_nodes(self):
155 """Try to optimize the nodes."""
156 buffer = []
157 for node in self.nodes:
158 try:
159 const = unicode(node.as_const())
160 except:
161 buffer.append(node)
162 else:
163 if buffer and isinstance(buffer[-1], unicode):
164 buffer[-1] += const
165 else:
166 buffer.append(const)
167 return buffer
Armin Ronacher07bc6842008-03-31 14:18:49 +0200168
169
170class Extends(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200171 """Represents an extends statement."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200172 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200173
174
175class For(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200176 """A node that represents a for loop"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200177 fields = ('target', 'iter', 'body', 'else_', 'recursive')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200178
179
180class If(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200181 """A node that represents an if condition."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200182 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200183
184
185class Macro(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200186 """A node that represents a macro."""
187 fields = ('name', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200188
189
190class CallBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200191 """A node that represents am extended macro call."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200192 fields = ('call', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200193
194
195class Set(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200196 """Allows defining own variables."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200197 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200198
199
200class FilterBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200201 """Node for filter sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200202 fields = ('body', 'filters')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200203
204
205class Block(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200206 """A node that represents a block."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200207 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200208
209
210class Include(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200211 """A node that represents the include tag."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200212 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200213
214
215class Trans(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200216 """A node for translatable sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200217 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200218
219
220class ExprStmt(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200221 """A statement that evaluates an expression to None."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200222 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200223
224
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200225class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200226 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200227 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200228
229
Armin Ronacher07bc6842008-03-31 14:18:49 +0200230class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200231 """Baseclass for all expressions."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200232
233 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200234 """Return the value of the expression as constant or raise
235 `Impossible` if this was not possible.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200236 """
237 raise Impossible()
238
239 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200240 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200241 return False
242
243
244class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200245 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200246 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200247 operator = None
248
249 def as_const(self):
250 f = _binop_to_func[self.operator]
251 try:
252 return f(self.left.as_const(), self.right.as_const())
253 except:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200254 raise Impossible()
255
256
257class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200258 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200259 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200260 operator = None
261
262 def as_const(self):
263 f = _uaop_to_func[self.operator]
264 try:
265 return f(self.node.as_const())
266 except:
267 raise Impossible()
268
269
270class Name(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200271 """any name such as {{ foo }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200272 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200273
274 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200275 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200276
277
278class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200279 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200280
281
282class Const(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200283 """any constat such as {{ "foo" }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200284 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200285
286 def as_const(self):
287 return self.value
288
289
290class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200291 """For loop unpacking and some other things like multiple arguments
Armin Ronacher07bc6842008-03-31 14:18:49 +0200292 for subscripts.
293 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200294 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200295
296 def as_const(self):
297 return tuple(x.as_const() for x in self.items)
298
299 def can_assign(self):
300 for item in self.items:
301 if not item.can_assign():
302 return False
303 return True
304
305
306class List(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200307 """any list literal such as {{ [1, 2, 3] }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200308 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200309
310 def as_const(self):
311 return [x.as_const() for x in self.items]
312
313
314class Dict(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200315 """any dict literal such as {{ {1: 2, 3: 4} }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200316 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200317
318 def as_const(self):
319 return dict(x.as_const() for x in self.items)
320
321
322class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200323 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200324 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200325
326 def as_const(self):
327 return self.key.as_const(), self.value.as_const()
328
329
Armin Ronacher8efc5222008-04-08 14:47:40 +0200330class Keyword(Helper):
331 """A key, value pair for keyword arguments."""
332 fields = ('key', 'value')
333
334
Armin Ronacher07bc6842008-03-31 14:18:49 +0200335class CondExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200336 """{{ foo if bar else baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200337 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200338
339 def as_const(self):
340 if self.test.as_const():
341 return self.expr1.as_const()
342 return self.expr2.as_const()
343
344
345class Filter(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200346 """{{ foo|bar|baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200347 fields = ('node', 'filters')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200348
349
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200350class FilterCall(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200351 """{{ |bar() }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200352 fields = ('name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200353
354
Armin Ronacher07bc6842008-03-31 14:18:49 +0200355class Test(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200356 """{{ foo is lower }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200357 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200358
359
360class Call(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200361 """{{ foo(bar) }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200362 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200363
364
365class Subscript(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200366 """{{ foo.bar }} and {{ foo['bar'] }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200367 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200368
369 def as_const(self):
370 try:
371 return self.node.as_const()[self.node.as_const()]
372 except:
373 raise Impossible()
374
375 def can_assign(self):
376 return True
377
378
379class Slice(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200380 """1:2:3 etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200381 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200382
383
384class Concat(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200385 """For {{ foo ~ bar }}. Concatenates strings."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200386 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200387
388 def as_const(self):
389 return ''.join(unicode(x.as_const()) for x in self.nodes)
390
391
392class Compare(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200393 """{{ foo == bar }}, {{ foo >= bar }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200394 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200395
396
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200397class Operand(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200398 """Operator + expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200399 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200400
401
Armin Ronacher07bc6842008-03-31 14:18:49 +0200402class Mul(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200403 """{{ foo * bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200404 operator = '*'
405
406
407class Div(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200408 """{{ foo / bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200409 operator = '/'
410
411
412class FloorDiv(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200413 """{{ foo // bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200414 operator = '//'
415
416
417class Add(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200418 """{{ foo + bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200419 operator = '+'
420
421
422class Sub(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200423 """{{ foo - bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200424 operator = '-'
425
426
427class Mod(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200428 """{{ foo % bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200429 operator = '%'
430
431
432class Pow(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200433 """{{ foo ** bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200434 operator = '**'
435
436
437class And(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200438 """{{ foo and bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200439 operator = 'and'
440
441 def as_const(self):
442 return self.left.as_const() and self.right.as_const()
443
444
445class Or(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200446 """{{ foo or bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200447 operator = 'or'
448
449 def as_const(self):
450 return self.left.as_const() or self.right.as_const()
451
452
453class Not(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200454 """{{ not foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200455 operator = 'not'
456
457
Armin Ronachere791c2a2008-04-07 18:39:54 +0200458class Neg(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200459 """{{ -foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200460 operator = '-'
461
462
Armin Ronachere791c2a2008-04-07 18:39:54 +0200463class Pos(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200464 """{{ +foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200465 operator = '+'