d0372e808a02b200d696c9f4eff4ffcecbc5b134
[jinja2.git] / jinja2 / nodes.py
1 # -*- 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: 2008 by Armin Ronacher.
13     :license: BSD, see LICENSE for more details.
14 """
15 import operator
16 from types import FunctionType
17 from itertools import chain, izip
18 from collections import deque
19 from copy import copy
20 from jinja2.utils import Markup
21
22
23 _binop_to_func = {
24     '*':        operator.mul,
25     '/':        operator.truediv,
26     '//':       operator.floordiv,
27     '**':       operator.pow,
28     '%':        operator.mod,
29     '+':        operator.add,
30     '-':        operator.sub
31 }
32
33 _uaop_to_func = {
34     'not':      operator.not_,
35     '+':        operator.pos,
36     '-':        operator.neg
37 }
38
39 _cmpop_to_func = {
40     'eq':       operator.eq,
41     'ne':       operator.ne,
42     'gt':       operator.gt,
43     'gteq':     operator.ge,
44     'lt':       operator.lt,
45     'lteq':     operator.le,
46     'in':       lambda a, b: a in b,
47     'notin':    lambda a, b: a not in b
48 }
49
50
51 class Impossible(Exception):
52     """Raised if the node could not perform a requested action."""
53
54
55 class NodeType(type):
56     """A metaclass for nodes that handles the field and attribute
57     inheritance.  fields and attributes from the parent class are
58     automatically forwarded to the child."""
59
60     def __new__(cls, name, bases, d):
61         for attr in 'fields', 'attributes':
62             storage = []
63             storage.extend(getattr(bases[0], attr, ()))
64             storage.extend(d.get(attr, ()))
65             assert len(bases) == 1, 'multiple inheritance not allowed'
66             assert len(storage) == len(set(storage)), 'layout conflict'
67             d[attr] = tuple(storage)
68         return type.__new__(cls, name, bases, d)
69
70
71 class Node(object):
72     """Baseclass for all Jinja nodes."""
73     __metaclass__ = NodeType
74     fields = ()
75     attributes = ('lineno', 'environment')
76
77     def __init__(self, *args, **kw):
78         if args:
79             if len(args) != len(self.fields):
80                 if not self.fields:
81                     raise TypeError('%r takes 0 arguments' %
82                                     self.__class__.__name__)
83                 raise TypeError('%r takes 0 or %d argument%s' % (
84                     self.__class__.__name__,
85                     len(self.fields),
86                     len(self.fields) != 1 and 's' or ''
87                 ))
88             for name, arg in izip(self.fields, args):
89                 setattr(self, name, arg)
90         for attr in self.attributes:
91             setattr(self, attr, kw.pop(attr, None))
92         if kw:
93             raise TypeError('unknown keyword argument %r' %
94                             iter(kw).next())
95
96     def iter_fields(self, exclude=()):
97         """Iterate over all fields."""
98         for name in self.fields:
99             if name not in exclude:
100                 try:
101                     yield name, getattr(self, name)
102                 except AttributeError:
103                     pass
104
105     def iter_child_nodes(self, exclude=()):
106         """Iterate over all child nodes."""
107         for field, item in self.iter_fields(exclude):
108             if isinstance(item, list):
109                 for n in item:
110                     if isinstance(n, Node):
111                         yield n
112             elif isinstance(item, Node):
113                 yield item
114
115     def find(self, node_type):
116         """Find the first node of a given type."""
117         for result in self.find_all(node_type):
118             return result
119
120     def find_all(self, node_type):
121         """Find all the nodes of a given type."""
122         for child in self.iter_child_nodes():
123             if isinstance(child, node_type):
124                 yield child
125             for result in child.find_all(node_type):
126                 yield result
127
128     def copy(self):
129         """Return a deep copy of the node."""
130         result = object.__new__(self.__class__)
131         for field, value in self.iter_fields():
132             if isinstance(value, Node):
133                 new_value = value.copy()
134             elif isinstance(value, list):
135                 new_value = []
136                 for item in value:
137                     if isinstance(item, Node):
138                         item = item.copy()
139                     else:
140                         item = copy(item)
141                     new_value.append(item)
142             else:
143                 new_value = copy(value)
144             setattr(result, field, new_value)
145         for attr in self.attributes:
146             try:
147                 setattr(result, attr, getattr(self, attr))
148             except AttributeError:
149                 pass
150         return result
151
152     def set_ctx(self, ctx):
153         """Reset the context of a node and all child nodes.  Per default the
154         parser will all generate nodes that have a 'load' context as it's the
155         most common one.  This method is used in the parser to set assignment
156         targets and other nodes to a store context.
157         """
158         todo = deque([self])
159         while todo:
160             node = todo.popleft()
161             if 'ctx' in node.fields:
162                 node.ctx = ctx
163             todo.extend(node.iter_child_nodes())
164
165     def set_lineno(self, lineno, override=False):
166         """Set the line numbers of the node and children."""
167         todo = deque([self])
168         while todo:
169             node = todo.popleft()
170             if 'lineno' in node.attributes:
171                 if node.lineno is None or override:
172                     node.lineno = lineno
173             todo.extend(node.iter_child_nodes())
174
175     def set_environment(self, environment):
176         """Set the environment for all nodes."""
177         todo = deque([self])
178         while todo:
179             node = todo.popleft()
180             node.environment = environment
181             todo.extend(node.iter_child_nodes())
182
183     def __repr__(self):
184         return '%s(%s)' % (
185             self.__class__.__name__,
186             ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
187                       arg in self.fields)
188         )
189
190
191 class Stmt(Node):
192     """Base node for all statements."""
193
194
195 class Helper(Node):
196     """Nodes that exist in a specific context only."""
197
198
199 class Template(Node):
200     """Node that represents a template."""
201     fields = ('body',)
202
203
204 class Output(Stmt):
205     """A node that holds multiple expressions which are then printed out.
206     This is used both for the `print` statement and the regular template data.
207     """
208     fields = ('nodes',)
209
210     def optimized_nodes(self):
211         """Try to optimize the nodes."""
212         buffer = []
213         for node in self.nodes:
214             try:
215                 const = unicode(node.as_const())
216             except:
217                 buffer.append(node)
218             else:
219                 if buffer and isinstance(buffer[-1], unicode):
220                     buffer[-1] += const
221                 else:
222                     buffer.append(const)
223         return buffer
224
225
226 class Extends(Stmt):
227     """Represents an extends statement."""
228     fields = ('template',)
229
230
231 class For(Stmt):
232     """A node that represents a for loop"""
233     fields = ('target', 'iter', 'body', 'else_', 'test')
234
235
236 class If(Stmt):
237     """A node that represents an if condition."""
238     fields = ('test', 'body', 'else_')
239
240
241 class Macro(Stmt):
242     """A node that represents a macro."""
243     fields = ('name', 'args', 'defaults', 'body')
244
245
246 class CallBlock(Stmt):
247     """A node that represents am extended macro call."""
248     fields = ('call', 'args', 'defaults', 'body')
249
250
251 class Set(Stmt):
252     """Allows defining own variables."""
253     fields = ('name', 'expr')
254
255
256 class FilterBlock(Stmt):
257     """Node for filter sections."""
258     fields = ('body', 'filter')
259
260
261 class Block(Stmt):
262     """A node that represents a block."""
263     fields = ('name', 'body')
264
265
266 class Include(Stmt):
267     """A node that represents the include tag."""
268     fields = ('template', 'with_context')
269
270
271 class Import(Stmt):
272     """A node that represents the import tag."""
273     fields = ('template', 'target', 'with_context')
274
275
276 class FromImport(Stmt):
277     """A node that represents the from import tag.  It's important to not
278     pass unsafe names to the name attribute.  The compiler translates the
279     attribute lookups directly into getattr calls and does *not* use the
280     subscribe callback of the interface.  As exported variables may not
281     start with double underscores (which the parser asserts) this is not a
282     problem for regular Jinja code, but if this node is used in an extension
283     extra care must be taken.
284
285     The list of names may contain tuples if aliases are wanted.
286     """
287     fields = ('template', 'names', 'with_context')
288
289
290 class Trans(Stmt):
291     """A node for translatable sections."""
292     fields = ('singular', 'plural', 'indicator', 'replacements')
293
294
295 class ExprStmt(Stmt):
296     """A statement that evaluates an expression to None."""
297     fields = ('node',)
298
299
300 class Assign(Stmt):
301     """Assigns an expression to a target."""
302     fields = ('target', 'node')
303
304
305 class Expr(Node):
306     """Baseclass for all expressions."""
307
308     def as_const(self):
309         """Return the value of the expression as constant or raise
310         `Impossible` if this was not possible.
311         """
312         raise Impossible()
313
314     def can_assign(self):
315         """Check if it's possible to assign something to this node."""
316         return False
317
318
319 class BinExpr(Expr):
320     """Baseclass for all binary expressions."""
321     fields = ('left', 'right')
322     operator = None
323
324     def as_const(self):
325         f = _binop_to_func[self.operator]
326         try:
327             return f(self.left.as_const(), self.right.as_const())
328         except:
329             raise Impossible()
330
331
332 class UnaryExpr(Expr):
333     """Baseclass for all unary expressions."""
334     fields = ('node',)
335     operator = None
336
337     def as_const(self):
338         f = _uaop_to_func[self.operator]
339         try:
340             return f(self.node.as_const())
341         except:
342             raise Impossible()
343
344
345 class Name(Expr):
346     """any name such as {{ foo }}"""
347     fields = ('name', 'ctx')
348
349     def can_assign(self):
350         return self.name not in ('true', 'false', 'none')
351
352
353 class MarkSafe(Expr):
354     """Mark the wrapped expression as safe (Markup)"""
355     fields = ('expr',)
356
357     def as_const(self):
358         return Markup(self.expr.as_const())
359
360
361 class Literal(Expr):
362     """Baseclass for literals."""
363
364
365 class Const(Literal):
366     """any constat such as {{ "foo" }}"""
367     fields = ('value',)
368
369     def as_const(self):
370         return self.value
371
372     @classmethod
373     def from_untrusted(cls, value, lineno=None, environment=None):
374         """Return a const object if the value is representable as
375         constant value in the generated code, otherwise it will raise
376         an `Impossible` exception.
377         """
378         from compiler import has_safe_repr
379         if not has_safe_repr(value):
380             raise Impossible()
381         return cls(value, lineno=lineno, environment=environment)
382
383
384 class Tuple(Literal):
385     """For loop unpacking and some other things like multiple arguments
386     for subscripts.
387     """
388     fields = ('items', 'ctx')
389
390     def as_const(self):
391         return tuple(x.as_const() for x in self.items)
392
393     def can_assign(self):
394         for item in self.items:
395             if not item.can_assign():
396                 return False
397         return True
398
399
400 class List(Literal):
401     """any list literal such as {{ [1, 2, 3] }}"""
402     fields = ('items',)
403
404     def as_const(self):
405         return [x.as_const() for x in self.items]
406
407
408 class Dict(Literal):
409     """any dict literal such as {{ {1: 2, 3: 4} }}"""
410     fields = ('items',)
411
412     def as_const(self):
413         return dict(x.as_const() for x in self.items)
414
415
416 class Pair(Helper):
417     """A key, value pair for dicts."""
418     fields = ('key', 'value')
419
420     def as_const(self):
421         return self.key.as_const(), self.value.as_const()
422
423
424 class Keyword(Helper):
425     """A key, value pair for keyword arguments."""
426     fields = ('key', 'value')
427
428
429 class CondExpr(Expr):
430     """{{ foo if bar else baz }}"""
431     fields = ('test', 'expr1', 'expr2')
432
433     def as_const(self):
434         if self.test.as_const():
435             return self.expr1.as_const()
436         return self.expr2.as_const()
437
438
439 class Filter(Expr):
440     """{{ foo|bar|baz }}"""
441     fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
442
443     def as_const(self, obj=None):
444         if self.node is obj is None:
445             raise Impossible()
446         filter = self.environment.filters.get(self.name)
447         if filter is None or getattr(filter, 'contextfilter', False):
448             raise Impossible()
449         if obj is None:
450             obj = self.node.as_const()
451         args = [x.as_const() for x in self.args]
452         if getattr(filter, 'environmentfilter', False):
453             args.insert(0, self.environment)
454         kwargs = dict(x.as_const() for x in self.kwargs)
455         if self.dyn_args is not None:
456             try:
457                 args.extend(self.dyn_args.as_const())
458             except:
459                 raise Impossible()
460         if self.dyn_kwargs is not None:
461             try:
462                 kwargs.update(self.dyn_kwargs.as_const())
463             except:
464                 raise Impossible()
465         try:
466             return filter(obj, *args, **kwargs)
467         except:
468             raise Impossible()
469
470
471 class Test(Expr):
472     """{{ foo is lower }}"""
473     fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
474
475
476 class Call(Expr):
477     """{{ foo(bar) }}"""
478     fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
479
480     def as_const(self):
481         obj = self.node.as_const()
482
483         # don't evaluate context functions
484         args = [x.as_const() for x in self.args]
485         if type(obj) is FunctionType:
486             if getattr(obj, 'contextfunction', False):
487                 raise Impossible()
488             elif obj.environmentfunction:
489                 args.insert(0, self.environment)
490
491         kwargs = dict(x.as_const() for x in self.kwargs)
492         if self.dyn_args is not None:
493             try:
494                 args.extend(self.dyn_args.as_const())
495             except:
496                 raise Impossible()
497         if self.dyn_kwargs is not None:
498             try:
499                 kwargs.update(self.dyn_kwargs.as_const())
500             except:
501                 raise Impossible()
502         try:
503             return obj(*args, **kwargs)
504         except:
505             raise Impossible()
506
507
508 class Subscript(Expr):
509     """{{ foo.bar }} and {{ foo['bar'] }} etc."""
510     fields = ('node', 'arg', 'ctx')
511
512     def as_const(self):
513         if self.ctx != 'load':
514             raise Impossible()
515         try:
516             return self.environment.subscribe(self.node.as_const(),
517                                               self.arg.as_const())
518         except:
519             raise Impossible()
520
521     def can_assign(self):
522         return False
523
524
525 class Slice(Expr):
526     """1:2:3 etc."""
527     fields = ('start', 'stop', 'step')
528
529     def as_const(self):
530         def const(obj):
531             if obj is None:
532                 return obj
533             return obj.as_const()
534         return slice(const(self.start), const(self.stop), const(self.step))
535
536
537 class Concat(Expr):
538     """For {{ foo ~ bar }}.  Concatenates strings."""
539     fields = ('nodes',)
540
541     def as_const(self):
542         return ''.join(unicode(x.as_const()) for x in self.nodes)
543
544
545 class Compare(Expr):
546     """{{ foo == bar }}, {{ foo >= bar }} etc."""
547     fields = ('expr', 'ops')
548
549     def as_const(self):
550         result = value = self.expr.as_const()
551         try:
552             for op in self.ops:
553                 new_value = op.expr.as_const()
554                 result = _cmpop_to_func[op.op](value, new_value)
555                 value = new_value
556         except:
557             raise Impossible()
558         return result
559
560
561 class Operand(Helper):
562     """Operator + expression."""
563     fields = ('op', 'expr')
564
565
566 class Mul(BinExpr):
567     """{{ foo * bar }}"""
568     operator = '*'
569
570
571 class Div(BinExpr):
572     """{{ foo / bar }}"""
573     operator = '/'
574
575
576 class FloorDiv(BinExpr):
577     """{{ foo // bar }}"""
578     operator = '//'
579
580
581 class Add(BinExpr):
582     """{{ foo + bar }}"""
583     operator = '+'
584
585
586 class Sub(BinExpr):
587     """{{ foo - bar }}"""
588     operator = '-'
589
590
591 class Mod(BinExpr):
592     """{{ foo % bar }}"""
593     operator = '%'
594
595
596 class Pow(BinExpr):
597     """{{ foo ** bar }}"""
598     operator = '**'
599
600
601 class And(BinExpr):
602     """{{ foo and bar }}"""
603     operator = 'and'
604
605     def as_const(self):
606         return self.left.as_const() and self.right.as_const()
607
608
609 class Or(BinExpr):
610     """{{ foo or bar }}"""
611     operator = 'or'
612
613     def as_const(self):
614         return self.left.as_const() or self.right.as_const()
615
616
617 class Not(UnaryExpr):
618     """{{ not foo }}"""
619     operator = 'not'
620
621
622 class Neg(UnaryExpr):
623     """{{ -foo }}"""
624     operator = '-'
625
626
627 class Pos(UnaryExpr):
628     """{{ +foo }}"""
629     operator = '+'