blob: b3255d54f11f9b35445b00f3727d7d8d47535809 [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
Armin Ronacher4f7d2d52008-04-22 10:40:26 +020012 :copyright: 2008 by Armin Ronacher.
Armin Ronacher07bc6842008-03-31 14:18:49 +020013 :license: BSD, see LICENSE for more details.
14"""
15import operator
Armin Ronacher4f7d2d52008-04-22 10:40:26 +020016from types import FunctionType
Armin Ronacher07bc6842008-03-31 14:18:49 +020017from itertools import chain, izip
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020018from collections import deque
Armin Ronacher07bc6842008-03-31 14:18:49 +020019from copy import copy
Armin Ronacherd84ec462008-04-29 13:43:16 +020020from jinja2.utils import Markup
Armin Ronacher07bc6842008-03-31 14:18:49 +020021
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
Armin Ronacher625215e2008-04-13 16:31:08 +020039_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,
Armin Ronacherb5124e62008-04-25 00:36:14 +020046 'in': lambda a, b: a in b,
47 'notin': lambda a, b: a not in b
Armin Ronacher625215e2008-04-13 16:31:08 +020048}
49
Armin Ronacher07bc6842008-03-31 14:18:49 +020050
51class Impossible(Exception):
Armin Ronacher8efc5222008-04-08 14:47:40 +020052 """Raised if the node could not perform a requested action."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020053
54
55class NodeType(type):
Armin Ronacher8efc5222008-04-08 14:47:40 +020056 """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."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020059
60 def __new__(cls, name, bases, d):
Armin Ronachere791c2a2008-04-07 18:39:54 +020061 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020062 storage = []
Armin Ronacher7324eb82008-04-21 07:55:52 +020063 storage.extend(getattr(bases[0], attr, ()))
Armin Ronacher07bc6842008-03-31 14:18:49 +020064 storage.extend(d.get(attr, ()))
Armin Ronacher7324eb82008-04-21 07:55:52 +020065 assert len(bases) == 1, 'multiple inheritance not allowed'
66 assert len(storage) == len(set(storage)), 'layout conflict'
Armin Ronacher07bc6842008-03-31 14:18:49 +020067 d[attr] = tuple(storage)
Armin Ronacher7324eb82008-04-21 07:55:52 +020068 return type.__new__(cls, name, bases, d)
Armin Ronacher07bc6842008-03-31 14:18:49 +020069
70
71class Node(object):
Armin Ronacher8efc5222008-04-08 14:47:40 +020072 """Baseclass for all Jinja nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020073 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020074 fields = ()
Armin Ronacherd55ab532008-04-09 16:13:39 +020075 attributes = ('lineno', 'environment')
Armin Ronacher07bc6842008-03-31 14:18:49 +020076
77 def __init__(self, *args, **kw):
78 if args:
Armin Ronachere791c2a2008-04-07 18:39:54 +020079 if len(args) != len(self.fields):
80 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020081 raise TypeError('%r takes 0 arguments' %
82 self.__class__.__name__)
83 raise TypeError('%r takes 0 or %d argument%s' % (
84 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +020085 len(self.fields),
86 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +020087 ))
Armin Ronachere791c2a2008-04-07 18:39:54 +020088 for name, arg in izip(self.fields, args):
Armin Ronacher07bc6842008-03-31 14:18:49 +020089 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +020090 for attr in self.attributes:
Armin Ronacher07bc6842008-03-31 14:18:49 +020091 setattr(self, attr, kw.pop(attr, None))
92 if kw:
93 raise TypeError('unknown keyword argument %r' %
94 iter(kw).next())
95
Armin Ronacher2feed1d2008-04-26 16:26:52 +020096 def iter_fields(self, exclude=()):
Armin Ronachere791c2a2008-04-07 18:39:54 +020097 """Iterate over all fields."""
98 for name in self.fields:
Armin Ronacher2feed1d2008-04-26 16:26:52 +020099 if name not in exclude:
100 try:
101 yield name, getattr(self, name)
102 except AttributeError:
103 pass
Armin Ronacher07bc6842008-03-31 14:18:49 +0200104
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200105 def iter_child_nodes(self, exclude=()):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200106 """Iterate over all child nodes."""
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200107 for field, item in self.iter_fields(exclude):
Armin Ronacher07bc6842008-03-31 14:18:49 +0200108 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
Armin Ronachere791c2a2008-04-07 18:39:54 +0200115 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
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200128 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 = []
Armin Ronacherd436e982008-04-09 16:31:20 +0200136 for item in value:
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200137 if isinstance(item, Node):
138 item = item.copy()
139 else:
140 item = copy(item)
141 new_value.append(item)
142 else:
Armin Ronacherd436e982008-04-09 16:31:20 +0200143 new_value = copy(value)
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200144 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
Armin Ronachere791c2a2008-04-07 18:39:54 +0200152 def set_ctx(self, ctx):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200153 """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.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200157 """
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
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200165 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
Armin Ronacherd55ab532008-04-09 16:13:39 +0200175 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
Armin Ronacher07bc6842008-03-31 14:18:49 +0200183 def __repr__(self):
184 return '%s(%s)' % (
185 self.__class__.__name__,
186 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200187 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200188 )
189
190
191class Stmt(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200192 """Base node for all statements."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200193
194
195class Helper(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200196 """Nodes that exist in a specific context only."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200197
198
199class Template(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200200 """Node that represents a template."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200201 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200202
203
204class Output(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200205 """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.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200207 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200208 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
Armin Ronacher07bc6842008-03-31 14:18:49 +0200224
225
226class Extends(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200227 """Represents an extends statement."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200228 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200229
230
231class For(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200232 """A node that represents a for loop"""
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200233 fields = ('target', 'iter', 'body', 'else_', 'test')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200234
235
236class If(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200237 """A node that represents an if condition."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200238 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200239
240
241class Macro(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200242 """A node that represents a macro."""
243 fields = ('name', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200244
245
246class CallBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200247 """A node that represents am extended macro call."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200248 fields = ('call', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200249
250
251class Set(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200252 """Allows defining own variables."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200253 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200254
255
256class FilterBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200257 """Node for filter sections."""
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200258 fields = ('body', 'filter')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200259
260
261class Block(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200262 """A node that represents a block."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200263 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200264
265
266class Include(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200267 """A node that represents the include tag."""
Armin Ronacher0611e492008-04-25 23:44:14 +0200268 fields = ('template',)
269
270
271class Import(Stmt):
272 """A node that represents the import tag."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200273 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200274
275
Armin Ronacher0611e492008-04-25 23:44:14 +0200276class 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.
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200284
285 The list of names may contain tuples if aliases are wanted.
Armin Ronacher0611e492008-04-25 23:44:14 +0200286 """
287 fields = ('template', 'names')
288
289
Armin Ronacher07bc6842008-03-31 14:18:49 +0200290class Trans(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200291 """A node for translatable sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200292 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200293
294
295class ExprStmt(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200296 """A statement that evaluates an expression to None."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200297 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200298
299
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200300class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200301 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200302 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200303
304
Armin Ronacher07bc6842008-03-31 14:18:49 +0200305class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200306 """Baseclass for all expressions."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200307
308 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200309 """Return the value of the expression as constant or raise
310 `Impossible` if this was not possible.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200311 """
312 raise Impossible()
313
314 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200315 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200316 return False
317
318
319class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200320 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200321 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200322 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:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200329 raise Impossible()
330
331
332class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200333 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200334 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200335 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
345class Name(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200346 """any name such as {{ foo }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200347 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200348
349 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200350 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200351
352
Armin Ronacherd84ec462008-04-29 13:43:16 +0200353class 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
Armin Ronacher07bc6842008-03-31 14:18:49 +0200361class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200362 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200363
364
365class Const(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200366 """any constat such as {{ "foo" }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200367 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200368
369 def as_const(self):
370 return self.value
371
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200372 @classmethod
Armin Ronacherd55ab532008-04-09 16:13:39 +0200373 def from_untrusted(cls, value, lineno=None, environment=None):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200374 """Return a const object if the value is representable as
375 constant value in the generated code, otherwise it will raise
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200376 an `Impossible` exception.
377 """
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200378 from compiler import has_safe_repr
379 if not has_safe_repr(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200380 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200381 return cls(value, lineno=lineno, environment=environment)
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200382
Armin Ronacher07bc6842008-03-31 14:18:49 +0200383
384class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200385 """For loop unpacking and some other things like multiple arguments
Armin Ronacher07bc6842008-03-31 14:18:49 +0200386 for subscripts.
387 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200388 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200389
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
400class List(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200401 """any list literal such as {{ [1, 2, 3] }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200402 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200403
404 def as_const(self):
405 return [x.as_const() for x in self.items]
406
407
408class Dict(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200409 """any dict literal such as {{ {1: 2, 3: 4} }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200410 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200411
412 def as_const(self):
413 return dict(x.as_const() for x in self.items)
414
415
416class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200417 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200418 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200419
420 def as_const(self):
421 return self.key.as_const(), self.value.as_const()
422
423
Armin Ronacher8efc5222008-04-08 14:47:40 +0200424class Keyword(Helper):
425 """A key, value pair for keyword arguments."""
426 fields = ('key', 'value')
427
428
Armin Ronacher07bc6842008-03-31 14:18:49 +0200429class CondExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200430 """{{ foo if bar else baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200431 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200432
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
439class Filter(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200440 """{{ foo|bar|baz }}"""
Armin Ronacherd55ab532008-04-09 16:13:39 +0200441 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200442
Armin Ronacher00d5d212008-04-13 01:10:18 +0200443 def as_const(self, obj=None):
444 if self.node is obj is None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200445 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200446 filter = self.environment.filters.get(self.name)
447 if filter is None or getattr(filter, 'contextfilter', False):
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200448 raise Impossible()
Armin Ronacher00d5d212008-04-13 01:10:18 +0200449 if obj is None:
450 obj = self.node.as_const()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200451 args = [x.as_const() for x in self.args]
Armin Ronacher9a027f42008-04-17 11:13:40 +0200452 if getattr(filter, 'environmentfilter', False):
453 args.insert(0, self.environment)
Armin Ronacherd55ab532008-04-09 16:13:39 +0200454 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:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200468 raise Impossible()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200469
470
Armin Ronacher07bc6842008-03-31 14:18:49 +0200471class Test(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200472 """{{ foo is lower }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200473 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200474
475
476class Call(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200477 """{{ foo(bar) }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200478 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200479
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200480 def as_const(self):
481 obj = self.node.as_const()
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200482
483 # don't evaluate context functions
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200484 args = [x.as_const() for x in self.args]
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200485 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
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200491 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:
Armin Ronacherd55ab532008-04-09 16:13:39 +0200499 kwargs.update(self.dyn_kwargs.as_const())
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200500 except:
501 raise Impossible()
502 try:
503 return obj(*args, **kwargs)
504 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200505 raise Impossible()
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200506
Armin Ronacher07bc6842008-03-31 14:18:49 +0200507
508class Subscript(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200509 """{{ foo.bar }} and {{ foo['bar'] }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200510 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200511
512 def as_const(self):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200513 if self.ctx != 'load':
514 raise Impossible()
Armin Ronacher07bc6842008-03-31 14:18:49 +0200515 try:
Benjamin Wieganda3152742008-04-28 18:07:52 +0200516 return self.environment.subscribe(self.node.as_const(),
517 self.arg.as_const())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200518 except:
519 raise Impossible()
520
521 def can_assign(self):
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200522 return False
Armin Ronacher07bc6842008-03-31 14:18:49 +0200523
524
525class Slice(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200526 """1:2:3 etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200527 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200528
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200529 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
Armin Ronacher07bc6842008-03-31 14:18:49 +0200536
537class Concat(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200538 """For {{ foo ~ bar }}. Concatenates strings."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200539 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200540
541 def as_const(self):
542 return ''.join(unicode(x.as_const()) for x in self.nodes)
543
544
545class Compare(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200546 """{{ foo == bar }}, {{ foo >= bar }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200547 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200548
Armin Ronacher625215e2008-04-13 16:31:08 +0200549 def as_const(self):
550 result = value = self.expr.as_const()
Armin Ronacherb5124e62008-04-25 00:36:14 +0200551 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()
Armin Ronacher625215e2008-04-13 16:31:08 +0200558 return result
559
Armin Ronacher07bc6842008-03-31 14:18:49 +0200560
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200561class Operand(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200562 """Operator + expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200563 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200564
565
Armin Ronacher07bc6842008-03-31 14:18:49 +0200566class Mul(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200567 """{{ foo * bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200568 operator = '*'
569
570
571class Div(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200572 """{{ foo / bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200573 operator = '/'
574
575
576class FloorDiv(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200577 """{{ foo // bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200578 operator = '//'
579
580
581class Add(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200582 """{{ foo + bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200583 operator = '+'
584
585
586class Sub(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200587 """{{ foo - bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200588 operator = '-'
589
590
591class Mod(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200592 """{{ foo % bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200593 operator = '%'
594
595
596class Pow(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200597 """{{ foo ** bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200598 operator = '**'
599
600
601class And(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200602 """{{ foo and bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200603 operator = 'and'
604
605 def as_const(self):
606 return self.left.as_const() and self.right.as_const()
607
608
609class Or(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200610 """{{ foo or bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200611 operator = 'or'
612
613 def as_const(self):
614 return self.left.as_const() or self.right.as_const()
615
616
617class Not(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200618 """{{ not foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200619 operator = 'not'
620
621
Armin Ronachere791c2a2008-04-07 18:39:54 +0200622class Neg(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200623 """{{ -foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200624 operator = '-'
625
626
Armin Ronachere791c2a2008-04-07 18:39:54 +0200627class Pos(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200628 """{{ +foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200629 operator = '+'