blob: 5f3aabb0235afe8f9196ec77f0ac321a82c2165c [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 Ronachere791c2a2008-04-07 18:39:54 +0200266 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200267
268
269class Trans(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200270 """A node for translatable sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200271 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200272
273
274class ExprStmt(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200275 """A statement that evaluates an expression to None."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200276 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200277
278
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200279class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200280 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200281 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200282
283
Armin Ronacher07bc6842008-03-31 14:18:49 +0200284class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200285 """Baseclass for all expressions."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200286
287 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200288 """Return the value of the expression as constant or raise
289 `Impossible` if this was not possible.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200290 """
291 raise Impossible()
292
293 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200294 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200295 return False
296
297
298class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200299 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200300 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200301 operator = None
302
303 def as_const(self):
304 f = _binop_to_func[self.operator]
305 try:
306 return f(self.left.as_const(), self.right.as_const())
307 except:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200308 raise Impossible()
309
310
311class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200312 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200313 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200314 operator = None
315
316 def as_const(self):
317 f = _uaop_to_func[self.operator]
318 try:
319 return f(self.node.as_const())
320 except:
321 raise Impossible()
322
323
324class Name(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200325 """any name such as {{ foo }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200326 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200327
328 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200329 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200330
331
332class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200333 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200334
335
336class Const(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200337 """any constat such as {{ "foo" }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200338 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200339
340 def as_const(self):
341 return self.value
342
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200343 @classmethod
Armin Ronacherd55ab532008-04-09 16:13:39 +0200344 def from_untrusted(cls, value, lineno=None, environment=None):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200345 """Return a const object if the value is representable as
346 constant value in the generated code, otherwise it will raise
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200347 an `Impossible` exception.
348 """
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200349 from compiler import has_safe_repr
350 if not has_safe_repr(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200351 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200352 return cls(value, lineno=lineno, environment=environment)
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200353
Armin Ronacher07bc6842008-03-31 14:18:49 +0200354
355class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200356 """For loop unpacking and some other things like multiple arguments
Armin Ronacher07bc6842008-03-31 14:18:49 +0200357 for subscripts.
358 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200359 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200360
361 def as_const(self):
362 return tuple(x.as_const() for x in self.items)
363
364 def can_assign(self):
365 for item in self.items:
366 if not item.can_assign():
367 return False
368 return True
369
370
371class List(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200372 """any list literal such as {{ [1, 2, 3] }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200373 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200374
375 def as_const(self):
376 return [x.as_const() for x in self.items]
377
378
379class Dict(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200380 """any dict literal such as {{ {1: 2, 3: 4} }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200381 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200382
383 def as_const(self):
384 return dict(x.as_const() for x in self.items)
385
386
387class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200388 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200389 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200390
391 def as_const(self):
392 return self.key.as_const(), self.value.as_const()
393
394
Armin Ronacher8efc5222008-04-08 14:47:40 +0200395class Keyword(Helper):
396 """A key, value pair for keyword arguments."""
397 fields = ('key', 'value')
398
399
Armin Ronacher07bc6842008-03-31 14:18:49 +0200400class CondExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200401 """{{ foo if bar else baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200402 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200403
404 def as_const(self):
405 if self.test.as_const():
406 return self.expr1.as_const()
407 return self.expr2.as_const()
408
409
410class Filter(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200411 """{{ foo|bar|baz }}"""
Armin Ronacherd55ab532008-04-09 16:13:39 +0200412 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200413
Armin Ronacher00d5d212008-04-13 01:10:18 +0200414 def as_const(self, obj=None):
415 if self.node is obj is None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200416 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200417 filter = self.environment.filters.get(self.name)
418 if filter is None or getattr(filter, 'contextfilter', False):
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200419 raise Impossible()
Armin Ronacher00d5d212008-04-13 01:10:18 +0200420 if obj is None:
421 obj = self.node.as_const()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200422 args = [x.as_const() for x in self.args]
Armin Ronacher9a027f42008-04-17 11:13:40 +0200423 if getattr(filter, 'environmentfilter', False):
424 args.insert(0, self.environment)
Armin Ronacherd55ab532008-04-09 16:13:39 +0200425 kwargs = dict(x.as_const() for x in self.kwargs)
426 if self.dyn_args is not None:
427 try:
428 args.extend(self.dyn_args.as_const())
429 except:
430 raise Impossible()
431 if self.dyn_kwargs is not None:
432 try:
433 kwargs.update(self.dyn_kwargs.as_const())
434 except:
435 raise Impossible()
436 try:
437 return filter(obj, *args, **kwargs)
438 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200439 raise Impossible()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200440
441
Armin Ronacher07bc6842008-03-31 14:18:49 +0200442class Test(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200443 """{{ foo is lower }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200444 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200445
446
447class Call(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200448 """{{ foo(bar) }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200449 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200450
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200451 def as_const(self):
452 obj = self.node.as_const()
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200453
454 # don't evaluate context functions
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200455 args = [x.as_const() for x in self.args]
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200456 if type(obj) is FunctionType:
457 if getattr(obj, 'contextfunction', False):
458 raise Impossible()
459 elif obj.environmentfunction:
460 args.insert(0, self.environment)
461
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200462 kwargs = dict(x.as_const() for x in self.kwargs)
463 if self.dyn_args is not None:
464 try:
465 args.extend(self.dyn_args.as_const())
466 except:
467 raise Impossible()
468 if self.dyn_kwargs is not None:
469 try:
Armin Ronacherd55ab532008-04-09 16:13:39 +0200470 kwargs.update(self.dyn_kwargs.as_const())
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200471 except:
472 raise Impossible()
473 try:
474 return obj(*args, **kwargs)
475 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200476 raise Impossible()
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200477
Armin Ronacher07bc6842008-03-31 14:18:49 +0200478
479class Subscript(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200480 """{{ foo.bar }} and {{ foo['bar'] }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200481 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200482
483 def as_const(self):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200484 if self.ctx != 'load':
485 raise Impossible()
Armin Ronacher07bc6842008-03-31 14:18:49 +0200486 try:
Armin Ronacherc63243e2008-04-14 22:53:58 +0200487 return environmen.subscribe(self.node.as_const(), self.arg.as_const())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200488 except:
489 raise Impossible()
490
491 def can_assign(self):
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200492 return False
Armin Ronacher07bc6842008-03-31 14:18:49 +0200493
494
495class Slice(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200496 """1:2:3 etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200497 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200498
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200499 def as_const(self):
500 def const(obj):
501 if obj is None:
502 return obj
503 return obj.as_const()
504 return slice(const(self.start), const(self.stop), const(self.step))
505
Armin Ronacher07bc6842008-03-31 14:18:49 +0200506
507class Concat(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200508 """For {{ foo ~ bar }}. Concatenates strings."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200509 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200510
511 def as_const(self):
512 return ''.join(unicode(x.as_const()) for x in self.nodes)
513
514
515class Compare(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200516 """{{ foo == bar }}, {{ foo >= bar }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200517 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200518
Armin Ronacher625215e2008-04-13 16:31:08 +0200519 def as_const(self):
520 result = value = self.expr.as_const()
Armin Ronacherb5124e62008-04-25 00:36:14 +0200521 try:
522 for op in self.ops:
523 new_value = op.expr.as_const()
524 result = _cmpop_to_func[op.op](value, new_value)
525 value = new_value
526 except:
527 raise Impossible()
Armin Ronacher625215e2008-04-13 16:31:08 +0200528 return result
529
Armin Ronacher07bc6842008-03-31 14:18:49 +0200530
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200531class Operand(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200532 """Operator + expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200533 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200534
535
Armin Ronacher07bc6842008-03-31 14:18:49 +0200536class Mul(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200537 """{{ foo * bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200538 operator = '*'
539
540
541class Div(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200542 """{{ foo / bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200543 operator = '/'
544
545
546class FloorDiv(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200547 """{{ foo // bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200548 operator = '//'
549
550
551class Add(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200552 """{{ foo + bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200553 operator = '+'
554
555
556class Sub(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200557 """{{ foo - bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200558 operator = '-'
559
560
561class Mod(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200562 """{{ foo % bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200563 operator = '%'
564
565
566class Pow(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200567 """{{ foo ** bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200568 operator = '**'
569
570
571class And(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200572 """{{ foo and bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200573 operator = 'and'
574
575 def as_const(self):
576 return self.left.as_const() and self.right.as_const()
577
578
579class Or(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200580 """{{ foo or bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200581 operator = 'or'
582
583 def as_const(self):
584 return self.left.as_const() or self.right.as_const()
585
586
587class Not(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200588 """{{ not foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200589 operator = 'not'
590
591
Armin Ronachere791c2a2008-04-07 18:39:54 +0200592class Neg(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200593 """{{ -foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200594 operator = '-'
595
596
Armin Ronachere791c2a2008-04-07 18:39:54 +0200597class Pos(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200598 """{{ +foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200599 operator = '+'