blob: 3aed350ee061c2cb8f1f166b46033cd97fb860d6 [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
20
21
22_binop_to_func = {
23 '*': operator.mul,
24 '/': operator.truediv,
25 '//': operator.floordiv,
26 '**': operator.pow,
27 '%': operator.mod,
28 '+': operator.add,
29 '-': operator.sub
30}
31
32_uaop_to_func = {
33 'not': operator.not_,
34 '+': operator.pos,
35 '-': operator.neg
36}
37
Armin Ronacher625215e2008-04-13 16:31:08 +020038_cmpop_to_func = {
39 'eq': operator.eq,
40 'ne': operator.ne,
41 'gt': operator.gt,
42 'gteq': operator.ge,
43 'lt': operator.lt,
44 'lteq': operator.le,
Armin Ronacherb5124e62008-04-25 00:36:14 +020045 'in': lambda a, b: a in b,
46 'notin': lambda a, b: a not in b
Armin Ronacher625215e2008-04-13 16:31:08 +020047}
48
Armin Ronacher07bc6842008-03-31 14:18:49 +020049
50class Impossible(Exception):
Armin Ronacher8efc5222008-04-08 14:47:40 +020051 """Raised if the node could not perform a requested action."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020052
53
54class NodeType(type):
Armin Ronacher8efc5222008-04-08 14:47:40 +020055 """A metaclass for nodes that handles the field and attribute
56 inheritance. fields and attributes from the parent class are
57 automatically forwarded to the child."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020058
59 def __new__(cls, name, bases, d):
Armin Ronachere791c2a2008-04-07 18:39:54 +020060 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020061 storage = []
Armin Ronacher7324eb82008-04-21 07:55:52 +020062 storage.extend(getattr(bases[0], attr, ()))
Armin Ronacher07bc6842008-03-31 14:18:49 +020063 storage.extend(d.get(attr, ()))
Armin Ronacher7324eb82008-04-21 07:55:52 +020064 assert len(bases) == 1, 'multiple inheritance not allowed'
65 assert len(storage) == len(set(storage)), 'layout conflict'
Armin Ronacher07bc6842008-03-31 14:18:49 +020066 d[attr] = tuple(storage)
Armin Ronacher7324eb82008-04-21 07:55:52 +020067 return type.__new__(cls, name, bases, d)
Armin Ronacher07bc6842008-03-31 14:18:49 +020068
69
70class Node(object):
Armin Ronacher8efc5222008-04-08 14:47:40 +020071 """Baseclass for all Jinja nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020072 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020073 fields = ()
Armin Ronacherd55ab532008-04-09 16:13:39 +020074 attributes = ('lineno', 'environment')
Armin Ronacher07bc6842008-03-31 14:18:49 +020075
76 def __init__(self, *args, **kw):
77 if args:
Armin Ronachere791c2a2008-04-07 18:39:54 +020078 if len(args) != len(self.fields):
79 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020080 raise TypeError('%r takes 0 arguments' %
81 self.__class__.__name__)
82 raise TypeError('%r takes 0 or %d argument%s' % (
83 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +020084 len(self.fields),
85 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +020086 ))
Armin Ronachere791c2a2008-04-07 18:39:54 +020087 for name, arg in izip(self.fields, args):
Armin Ronacher07bc6842008-03-31 14:18:49 +020088 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +020089 for attr in self.attributes:
Armin Ronacher07bc6842008-03-31 14:18:49 +020090 setattr(self, attr, kw.pop(attr, None))
91 if kw:
92 raise TypeError('unknown keyword argument %r' %
93 iter(kw).next())
94
95 def iter_fields(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020096 """Iterate over all fields."""
97 for name in self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020098 try:
99 yield name, getattr(self, name)
100 except AttributeError:
101 pass
102
103 def iter_child_nodes(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200104 """Iterate over all child nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200105 for field, item in self.iter_fields():
106 if isinstance(item, list):
107 for n in item:
108 if isinstance(n, Node):
109 yield n
110 elif isinstance(item, Node):
111 yield item
112
Armin Ronachere791c2a2008-04-07 18:39:54 +0200113 def find(self, node_type):
114 """Find the first node of a given type."""
115 for result in self.find_all(node_type):
116 return result
117
118 def find_all(self, node_type):
119 """Find all the nodes of a given type."""
120 for child in self.iter_child_nodes():
121 if isinstance(child, node_type):
122 yield child
123 for result in child.find_all(node_type):
124 yield result
125
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200126 def copy(self):
127 """Return a deep copy of the node."""
128 result = object.__new__(self.__class__)
129 for field, value in self.iter_fields():
130 if isinstance(value, Node):
131 new_value = value.copy()
132 elif isinstance(value, list):
133 new_value = []
Armin Ronacherd436e982008-04-09 16:31:20 +0200134 for item in value:
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200135 if isinstance(item, Node):
136 item = item.copy()
137 else:
138 item = copy(item)
139 new_value.append(item)
140 else:
Armin Ronacherd436e982008-04-09 16:31:20 +0200141 new_value = copy(value)
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200142 setattr(result, field, new_value)
143 for attr in self.attributes:
144 try:
145 setattr(result, attr, getattr(self, attr))
146 except AttributeError:
147 pass
148 return result
149
Armin Ronachere791c2a2008-04-07 18:39:54 +0200150 def set_ctx(self, ctx):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200151 """Reset the context of a node and all child nodes. Per default the
152 parser will all generate nodes that have a 'load' context as it's the
153 most common one. This method is used in the parser to set assignment
154 targets and other nodes to a store context.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200155 """
156 todo = deque([self])
157 while todo:
158 node = todo.popleft()
159 if 'ctx' in node.fields:
160 node.ctx = ctx
161 todo.extend(node.iter_child_nodes())
162
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200163 def set_lineno(self, lineno, override=False):
164 """Set the line numbers of the node and children."""
165 todo = deque([self])
166 while todo:
167 node = todo.popleft()
168 if 'lineno' in node.attributes:
169 if node.lineno is None or override:
170 node.lineno = lineno
171 todo.extend(node.iter_child_nodes())
172
Armin Ronacherd55ab532008-04-09 16:13:39 +0200173 def set_environment(self, environment):
174 """Set the environment for all nodes."""
175 todo = deque([self])
176 while todo:
177 node = todo.popleft()
178 node.environment = environment
179 todo.extend(node.iter_child_nodes())
180
Armin Ronacher07bc6842008-03-31 14:18:49 +0200181 def __repr__(self):
182 return '%s(%s)' % (
183 self.__class__.__name__,
184 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200185 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200186 )
187
188
189class Stmt(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200190 """Base node for all statements."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200191
192
193class Helper(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200194 """Nodes that exist in a specific context only."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200195
196
197class Template(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200198 """Node that represents a template."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200199 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200200
201
202class Output(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200203 """A node that holds multiple expressions which are then printed out.
204 This is used both for the `print` statement and the regular template data.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200205 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200206 fields = ('nodes',)
207
208 def optimized_nodes(self):
209 """Try to optimize the nodes."""
210 buffer = []
211 for node in self.nodes:
212 try:
213 const = unicode(node.as_const())
214 except:
215 buffer.append(node)
216 else:
217 if buffer and isinstance(buffer[-1], unicode):
218 buffer[-1] += const
219 else:
220 buffer.append(const)
221 return buffer
Armin Ronacher07bc6842008-03-31 14:18:49 +0200222
223
224class Extends(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200225 """Represents an extends statement."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200226 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200227
228
229class For(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200230 """A node that represents a for loop"""
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200231 fields = ('target', 'iter', 'body', 'else_', 'test')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200232
233
234class If(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200235 """A node that represents an if condition."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200236 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200237
238
239class Macro(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200240 """A node that represents a macro."""
241 fields = ('name', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200242
243
244class CallBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200245 """A node that represents am extended macro call."""
Armin Ronacher71082072008-04-12 14:19:36 +0200246 fields = ('call', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200247
248
249class Set(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200250 """Allows defining own variables."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200251 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200252
253
254class FilterBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200255 """Node for filter sections."""
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200256 fields = ('body', 'filter')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200257
258
259class Block(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200260 """A node that represents a block."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200261 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200262
263
264class Include(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200265 """A node that represents the include tag."""
Armin Ronacher0611e492008-04-25 23:44:14 +0200266 fields = ('template',)
267
268
269class Import(Stmt):
270 """A node that represents the import tag."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200271 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200272
273
Armin Ronacher0611e492008-04-25 23:44:14 +0200274class FromImport(Stmt):
275 """A node that represents the from import tag. It's important to not
276 pass unsafe names to the name attribute. The compiler translates the
277 attribute lookups directly into getattr calls and does *not* use the
278 subscribe callback of the interface. As exported variables may not
279 start with double underscores (which the parser asserts) this is not a
280 problem for regular Jinja code, but if this node is used in an extension
281 extra care must be taken.
282 """
283 fields = ('template', 'names')
284
285
Armin Ronacher07bc6842008-03-31 14:18:49 +0200286class Trans(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200287 """A node for translatable sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200288 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200289
290
291class ExprStmt(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200292 """A statement that evaluates an expression to None."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200293 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200294
295
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200296class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200297 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200298 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200299
300
Armin Ronacher07bc6842008-03-31 14:18:49 +0200301class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200302 """Baseclass for all expressions."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200303
304 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200305 """Return the value of the expression as constant or raise
306 `Impossible` if this was not possible.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200307 """
308 raise Impossible()
309
310 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200311 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200312 return False
313
314
315class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200316 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200317 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200318 operator = None
319
320 def as_const(self):
321 f = _binop_to_func[self.operator]
322 try:
323 return f(self.left.as_const(), self.right.as_const())
324 except:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200325 raise Impossible()
326
327
328class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200329 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200330 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200331 operator = None
332
333 def as_const(self):
334 f = _uaop_to_func[self.operator]
335 try:
336 return f(self.node.as_const())
337 except:
338 raise Impossible()
339
340
341class Name(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200342 """any name such as {{ foo }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200343 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200344
345 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200346 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200347
348
349class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200350 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200351
352
353class Const(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200354 """any constat such as {{ "foo" }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200355 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200356
357 def as_const(self):
358 return self.value
359
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200360 @classmethod
Armin Ronacherd55ab532008-04-09 16:13:39 +0200361 def from_untrusted(cls, value, lineno=None, environment=None):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200362 """Return a const object if the value is representable as
363 constant value in the generated code, otherwise it will raise
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200364 an `Impossible` exception.
365 """
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200366 from compiler import has_safe_repr
367 if not has_safe_repr(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200368 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200369 return cls(value, lineno=lineno, environment=environment)
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200370
Armin Ronacher07bc6842008-03-31 14:18:49 +0200371
372class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200373 """For loop unpacking and some other things like multiple arguments
Armin Ronacher07bc6842008-03-31 14:18:49 +0200374 for subscripts.
375 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200376 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200377
378 def as_const(self):
379 return tuple(x.as_const() for x in self.items)
380
381 def can_assign(self):
382 for item in self.items:
383 if not item.can_assign():
384 return False
385 return True
386
387
388class List(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200389 """any list literal such as {{ [1, 2, 3] }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200390 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200391
392 def as_const(self):
393 return [x.as_const() for x in self.items]
394
395
396class Dict(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200397 """any dict literal such as {{ {1: 2, 3: 4} }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200398 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200399
400 def as_const(self):
401 return dict(x.as_const() for x in self.items)
402
403
404class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200405 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200406 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200407
408 def as_const(self):
409 return self.key.as_const(), self.value.as_const()
410
411
Armin Ronacher8efc5222008-04-08 14:47:40 +0200412class Keyword(Helper):
413 """A key, value pair for keyword arguments."""
414 fields = ('key', 'value')
415
416
Armin Ronacher07bc6842008-03-31 14:18:49 +0200417class CondExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200418 """{{ foo if bar else baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200419 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200420
421 def as_const(self):
422 if self.test.as_const():
423 return self.expr1.as_const()
424 return self.expr2.as_const()
425
426
427class Filter(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200428 """{{ foo|bar|baz }}"""
Armin Ronacherd55ab532008-04-09 16:13:39 +0200429 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200430
Armin Ronacher00d5d212008-04-13 01:10:18 +0200431 def as_const(self, obj=None):
432 if self.node is obj is None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200433 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200434 filter = self.environment.filters.get(self.name)
435 if filter is None or getattr(filter, 'contextfilter', False):
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200436 raise Impossible()
Armin Ronacher00d5d212008-04-13 01:10:18 +0200437 if obj is None:
438 obj = self.node.as_const()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200439 args = [x.as_const() for x in self.args]
Armin Ronacher9a027f42008-04-17 11:13:40 +0200440 if getattr(filter, 'environmentfilter', False):
441 args.insert(0, self.environment)
Armin Ronacherd55ab532008-04-09 16:13:39 +0200442 kwargs = dict(x.as_const() for x in self.kwargs)
443 if self.dyn_args is not None:
444 try:
445 args.extend(self.dyn_args.as_const())
446 except:
447 raise Impossible()
448 if self.dyn_kwargs is not None:
449 try:
450 kwargs.update(self.dyn_kwargs.as_const())
451 except:
452 raise Impossible()
453 try:
454 return filter(obj, *args, **kwargs)
455 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200456 raise Impossible()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200457
458
Armin Ronacher07bc6842008-03-31 14:18:49 +0200459class Test(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200460 """{{ foo is lower }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200461 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200462
463
464class Call(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200465 """{{ foo(bar) }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200466 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200467
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200468 def as_const(self):
469 obj = self.node.as_const()
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200470
471 # don't evaluate context functions
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200472 args = [x.as_const() for x in self.args]
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200473 if type(obj) is FunctionType:
474 if getattr(obj, 'contextfunction', False):
475 raise Impossible()
476 elif obj.environmentfunction:
477 args.insert(0, self.environment)
478
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200479 kwargs = dict(x.as_const() for x in self.kwargs)
480 if self.dyn_args is not None:
481 try:
482 args.extend(self.dyn_args.as_const())
483 except:
484 raise Impossible()
485 if self.dyn_kwargs is not None:
486 try:
Armin Ronacherd55ab532008-04-09 16:13:39 +0200487 kwargs.update(self.dyn_kwargs.as_const())
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200488 except:
489 raise Impossible()
490 try:
491 return obj(*args, **kwargs)
492 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200493 raise Impossible()
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200494
Armin Ronacher07bc6842008-03-31 14:18:49 +0200495
496class Subscript(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200497 """{{ foo.bar }} and {{ foo['bar'] }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200498 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200499
500 def as_const(self):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200501 if self.ctx != 'load':
502 raise Impossible()
Armin Ronacher07bc6842008-03-31 14:18:49 +0200503 try:
Armin Ronacherc63243e2008-04-14 22:53:58 +0200504 return environmen.subscribe(self.node.as_const(), self.arg.as_const())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200505 except:
506 raise Impossible()
507
508 def can_assign(self):
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200509 return False
Armin Ronacher07bc6842008-03-31 14:18:49 +0200510
511
512class Slice(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200513 """1:2:3 etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200514 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200515
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200516 def as_const(self):
517 def const(obj):
518 if obj is None:
519 return obj
520 return obj.as_const()
521 return slice(const(self.start), const(self.stop), const(self.step))
522
Armin Ronacher07bc6842008-03-31 14:18:49 +0200523
524class Concat(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200525 """For {{ foo ~ bar }}. Concatenates strings."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200526 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200527
528 def as_const(self):
529 return ''.join(unicode(x.as_const()) for x in self.nodes)
530
531
532class Compare(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200533 """{{ foo == bar }}, {{ foo >= bar }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200534 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200535
Armin Ronacher625215e2008-04-13 16:31:08 +0200536 def as_const(self):
537 result = value = self.expr.as_const()
Armin Ronacherb5124e62008-04-25 00:36:14 +0200538 try:
539 for op in self.ops:
540 new_value = op.expr.as_const()
541 result = _cmpop_to_func[op.op](value, new_value)
542 value = new_value
543 except:
544 raise Impossible()
Armin Ronacher625215e2008-04-13 16:31:08 +0200545 return result
546
Armin Ronacher07bc6842008-03-31 14:18:49 +0200547
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200548class Operand(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200549 """Operator + expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200550 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200551
552
Armin Ronacher07bc6842008-03-31 14:18:49 +0200553class Mul(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200554 """{{ foo * bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200555 operator = '*'
556
557
558class Div(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200559 """{{ foo / bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200560 operator = '/'
561
562
563class FloorDiv(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200564 """{{ foo // bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200565 operator = '//'
566
567
568class Add(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200569 """{{ foo + bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200570 operator = '+'
571
572
573class Sub(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200574 """{{ foo - bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200575 operator = '-'
576
577
578class Mod(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200579 """{{ foo % bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200580 operator = '%'
581
582
583class Pow(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200584 """{{ foo ** bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200585 operator = '**'
586
587
588class And(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200589 """{{ foo and bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200590 operator = 'and'
591
592 def as_const(self):
593 return self.left.as_const() and self.right.as_const()
594
595
596class Or(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200597 """{{ foo or bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200598 operator = 'or'
599
600 def as_const(self):
601 return self.left.as_const() or self.right.as_const()
602
603
604class Not(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200605 """{{ not foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200606 operator = 'not'
607
608
Armin Ronachere791c2a2008-04-07 18:39:54 +0200609class Neg(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200610 """{{ -foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200611 operator = '-'
612
613
Armin Ronachere791c2a2008-04-07 18:39:54 +0200614class Pos(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200615 """{{ +foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200616 operator = '+'