blob: e6e68a1deb5737dcfc4590dad300b4c29816872a [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
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020038
39
Armin Ronacher07bc6842008-03-31 14:18:49 +020040class Impossible(Exception):
41 """
42 Raised if the node could not perform a requested action.
43 """
44
45
46class NodeType(type):
47
48 def __new__(cls, name, bases, d):
Armin Ronachere791c2a2008-04-07 18:39:54 +020049 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020050 storage = []
51 for base in bases:
52 storage.extend(getattr(base, attr, ()))
53 storage.extend(d.get(attr, ()))
54 assert len(storage) == len(set(storage))
55 d[attr] = tuple(storage)
56 return type.__new__(cls, name, bases, d)
57
58
59class Node(object):
60 """
Armin Ronachere791c2a2008-04-07 18:39:54 +020061 Baseclass for all Jinja nodes.
Armin Ronacher07bc6842008-03-31 14:18:49 +020062 """
63 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020064 fields = ()
65 attributes = ('lineno',)
Armin Ronacher07bc6842008-03-31 14:18:49 +020066
67 def __init__(self, *args, **kw):
68 if args:
Armin Ronachere791c2a2008-04-07 18:39:54 +020069 if len(args) != len(self.fields):
70 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020071 raise TypeError('%r takes 0 arguments' %
72 self.__class__.__name__)
73 raise TypeError('%r takes 0 or %d argument%s' % (
74 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +020075 len(self.fields),
76 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +020077 ))
Armin Ronachere791c2a2008-04-07 18:39:54 +020078 for name, arg in izip(self.fields, args):
Armin Ronacher07bc6842008-03-31 14:18:49 +020079 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +020080 for attr in self.attributes:
Armin Ronacher07bc6842008-03-31 14:18:49 +020081 setattr(self, attr, kw.pop(attr, None))
82 if kw:
83 raise TypeError('unknown keyword argument %r' %
84 iter(kw).next())
85
86 def iter_fields(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020087 """Iterate over all fields."""
88 for name in self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020089 try:
90 yield name, getattr(self, name)
91 except AttributeError:
92 pass
93
94 def iter_child_nodes(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020095 """Iterate over all child nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020096 for field, item in self.iter_fields():
97 if isinstance(item, list):
98 for n in item:
99 if isinstance(n, Node):
100 yield n
101 elif isinstance(item, Node):
102 yield item
103
Armin Ronachere791c2a2008-04-07 18:39:54 +0200104 def find(self, node_type):
105 """Find the first node of a given type."""
106 for result in self.find_all(node_type):
107 return result
108
109 def find_all(self, node_type):
110 """Find all the nodes of a given type."""
111 for child in self.iter_child_nodes():
112 if isinstance(child, node_type):
113 yield child
114 for result in child.find_all(node_type):
115 yield result
116
117 def set_ctx(self, ctx):
118 """
119 Reset the context of a node and all child nodes. Per default the parser
120 will all generate nodes that have a 'load' context as it's the most common
121 one. This method is used in the parser to set assignment targets and
122 other nodes to a store context.
123 """
124 todo = deque([self])
125 while todo:
126 node = todo.popleft()
127 if 'ctx' in node.fields:
128 node.ctx = ctx
129 todo.extend(node.iter_child_nodes())
130
Armin Ronacher07bc6842008-03-31 14:18:49 +0200131 def __repr__(self):
132 return '%s(%s)' % (
133 self.__class__.__name__,
134 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200135 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200136 )
137
138
139class Stmt(Node):
140 """
141 Base node for all statements.
142 """
143
144
145class Helper(Node):
146 """
147 Nodes that exist in a specific context only.
148 """
149
150
151class Template(Node):
152 """
153 Node that represents a template.
154 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200155 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200156
157
158class Output(Stmt):
159 """
160 A node that holds multiple expressions which are then printed out. This
161 is used both for the `print` statement and the regular template data.
162 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200163 fields = ('nodes',)
164
165 def optimized_nodes(self):
166 """Try to optimize the nodes."""
167 buffer = []
168 for node in self.nodes:
169 try:
170 const = unicode(node.as_const())
171 except:
172 buffer.append(node)
173 else:
174 if buffer and isinstance(buffer[-1], unicode):
175 buffer[-1] += const
176 else:
177 buffer.append(const)
178 return buffer
Armin Ronacher07bc6842008-03-31 14:18:49 +0200179
180
181class Extends(Stmt):
182 """
183 Represents an extends statement.
184 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200185 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200186
187
188class For(Stmt):
189 """
190 A node that represents a for loop
191 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200192 fields = ('target', 'iter', 'body', 'else_', 'recursive')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200193
194
195class If(Stmt):
196 """
197 A node that represents an if condition.
198 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200199 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200200
201
202class Macro(Stmt):
203 """
204 A node that represents a macro.
205 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200206 fields = ('name', 'args', 'defaults', 'dyn_args', 'dyn_kwargs', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200207
208
209class CallBlock(Stmt):
210 """
211 A node that represents am extended macro call.
212 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200213 fields = ('call', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200214
215
216class Set(Stmt):
217 """
218 Allows defining own variables.
219 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200220 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200221
222
223class FilterBlock(Stmt):
224 """
225 Node for filter sections.
226 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200227 fields = ('body', 'filters')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200228
229
230class Block(Stmt):
231 """
232 A node that represents a block.
233 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200234 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200235
236
237class Include(Stmt):
238 """
239 A node that represents the include tag.
240 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200241 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200242
243
244class Trans(Stmt):
245 """
246 A node for translatable sections.
247 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200248 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200249
250
251class ExprStmt(Stmt):
252 """
253 A statement that evaluates an expression to None.
254 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200255 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200256
257
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200258class Assign(Stmt):
259 """
260 Assigns an expression to a target.
261 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200262 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200263
264
Armin Ronacher07bc6842008-03-31 14:18:49 +0200265class Expr(Node):
266 """
267 Baseclass for all expressions.
268 """
269
270 def as_const(self):
271 """
272 Return the value of the expression as constant or raise `Impossible`
273 if this was not possible.
274 """
275 raise Impossible()
276
277 def can_assign(self):
278 """
279 Check if it's possible to assign something to this node.
280 """
281 return False
282
283
284class BinExpr(Expr):
285 """
286 Baseclass for all binary expressions.
287 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200288 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200289 operator = None
290
291 def as_const(self):
292 f = _binop_to_func[self.operator]
293 try:
294 return f(self.left.as_const(), self.right.as_const())
295 except:
296 print self.left, f, self.right
297 raise Impossible()
298
299
300class UnaryExpr(Expr):
301 """
302 Baseclass for all unary expressions.
303 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200304 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200305 operator = None
306
307 def as_const(self):
308 f = _uaop_to_func[self.operator]
309 try:
310 return f(self.node.as_const())
311 except:
312 raise Impossible()
313
314
315class Name(Expr):
316 """
317 any name such as {{ foo }}
318 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200319 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200320
321 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200322 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200323
324
325class Literal(Expr):
326 """
327 Baseclass for literals.
328 """
329
330
331class Const(Literal):
332 """
333 any constat such as {{ "foo" }}
334 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200335 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200336
337 def as_const(self):
338 return self.value
339
340
341class Tuple(Literal):
342 """
343 For loop unpacking and some other things like multiple arguments
344 for subscripts.
345 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200346 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200347
348 def as_const(self):
349 return tuple(x.as_const() for x in self.items)
350
351 def can_assign(self):
352 for item in self.items:
353 if not item.can_assign():
354 return False
355 return True
356
357
358class List(Literal):
359 """
360 any list literal such as {{ [1, 2, 3] }}
361 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200362 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200363
364 def as_const(self):
365 return [x.as_const() for x in self.items]
366
367
368class Dict(Literal):
369 """
370 any dict literal such as {{ {1: 2, 3: 4} }}
371 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200372 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200373
374 def as_const(self):
375 return dict(x.as_const() for x in self.items)
376
377
378class Pair(Helper):
379 """
380 A key, value pair for dicts.
381 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200382 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200383
384 def as_const(self):
385 return self.key.as_const(), self.value.as_const()
386
387
388class CondExpr(Expr):
389 """
390 {{ foo if bar else baz }}
391 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200392 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200393
394 def as_const(self):
395 if self.test.as_const():
396 return self.expr1.as_const()
397 return self.expr2.as_const()
398
399
400class Filter(Expr):
401 """
402 {{ foo|bar|baz }}
403 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200404 fields = ('node', 'filters')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200405
406
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200407class FilterCall(Expr):
408 """
409 {{ |bar() }}
410 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200411 fields = ('name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200412
413
Armin Ronacher07bc6842008-03-31 14:18:49 +0200414class Test(Expr):
415 """
416 {{ foo is lower }}
417 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200418 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200419
420
421class Call(Expr):
422 """
423 {{ foo(bar) }}
424 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200425 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200426
427
428class Subscript(Expr):
429 """
430 {{ foo.bar }} and {{ foo['bar'] }} etc.
431 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200432 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200433
434 def as_const(self):
435 try:
436 return self.node.as_const()[self.node.as_const()]
437 except:
438 raise Impossible()
439
440 def can_assign(self):
441 return True
442
443
444class Slice(Expr):
445 """
446 1:2:3 etc.
447 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200448 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200449
450
451class Concat(Expr):
452 """
453 For {{ foo ~ bar }}. Concatenates strings.
454 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200455 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200456
457 def as_const(self):
458 return ''.join(unicode(x.as_const()) for x in self.nodes)
459
460
461class Compare(Expr):
462 """
463 {{ foo == bar }}, {{ foo >= bar }} etc.
464 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200465 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200466
467
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200468class Operand(Helper):
469 """
470 Operator + expression.
471 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200472 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200473
474
Armin Ronacher07bc6842008-03-31 14:18:49 +0200475class Mul(BinExpr):
476 """
477 {{ foo * bar }}
478 """
479 operator = '*'
480
481
482class Div(BinExpr):
483 """
484 {{ foo / bar }}
485 """
486 operator = '/'
487
488
489class FloorDiv(BinExpr):
490 """
491 {{ foo // bar }}
492 """
493 operator = '//'
494
495
496class Add(BinExpr):
497 """
498 {{ foo + bar }}
499 """
500 operator = '+'
501
502
503class Sub(BinExpr):
504 """
505 {{ foo - bar }}
506 """
507 operator = '-'
508
509
510class Mod(BinExpr):
511 """
512 {{ foo % bar }}
513 """
514 operator = '%'
515
516
517class Pow(BinExpr):
518 """
519 {{ foo ** bar }}
520 """
521 operator = '**'
522
523
524class And(BinExpr):
525 """
526 {{ foo and bar }}
527 """
528 operator = 'and'
529
530 def as_const(self):
531 return self.left.as_const() and self.right.as_const()
532
533
534class Or(BinExpr):
535 """
536 {{ foo or bar }}
537 """
538 operator = 'or'
539
540 def as_const(self):
541 return self.left.as_const() or self.right.as_const()
542
543
544class Not(UnaryExpr):
545 """
546 {{ not foo }}
547 """
548 operator = 'not'
549
550
Armin Ronachere791c2a2008-04-07 18:39:54 +0200551class Neg(UnaryExpr):
Armin Ronacher07bc6842008-03-31 14:18:49 +0200552 """
553 {{ -foo }}
554 """
555 operator = '-'
556
557
Armin Ronachere791c2a2008-04-07 18:39:54 +0200558class Pos(UnaryExpr):
Armin Ronacher07bc6842008-03-31 14:18:49 +0200559 """
560 {{ +foo }}
561 """
562 operator = '+'