blob: 40aae3cdd45473d5ffe80c0eaeb67f3791d47fb2 [file] [log] [blame]
Armin Ronacher07bc6842008-03-31 14:18:49 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.nodes
4 ~~~~~~~~~~~~
5
6 This module implements additional nodes derived from the ast base node.
7
8 It also provides some node tree helper functions like `in_lineno` and
9 `get_nodes` used by the parser and translator in order to normalize
10 python and jinja nodes.
11
12 :copyright: 2007 by Armin Ronacher.
13 :license: BSD, see LICENSE for more details.
14"""
15import operator
16from itertools import chain, izip
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020017from collections import deque
Armin Ronacher07bc6842008-03-31 14:18:49 +020018from copy import copy
19
20
21_binop_to_func = {
22 '*': operator.mul,
23 '/': operator.truediv,
24 '//': operator.floordiv,
25 '**': operator.pow,
26 '%': operator.mod,
27 '+': operator.add,
28 '-': operator.sub
29}
30
31_uaop_to_func = {
32 'not': operator.not_,
33 '+': operator.pos,
34 '-': operator.neg
35}
36
Armin Ronacher625215e2008-04-13 16:31:08 +020037_cmpop_to_func = {
38 'eq': operator.eq,
39 'ne': operator.ne,
40 'gt': operator.gt,
41 'gteq': operator.ge,
42 'lt': operator.lt,
43 'lteq': operator.le,
44 'in': operator.contains,
45 'notin': lambda a, b: not operator.contains(a, b)
46}
47
Armin Ronacher07bc6842008-03-31 14:18:49 +020048
49class Impossible(Exception):
Armin Ronacher8efc5222008-04-08 14:47:40 +020050 """Raised if the node could not perform a requested action."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020051
52
53class NodeType(type):
Armin Ronacher8efc5222008-04-08 14:47:40 +020054 """A metaclass for nodes that handles the field and attribute
55 inheritance. fields and attributes from the parent class are
56 automatically forwarded to the child."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020057
58 def __new__(cls, name, bases, d):
Armin Ronachere791c2a2008-04-07 18:39:54 +020059 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020060 storage = []
61 for base in bases:
62 storage.extend(getattr(base, attr, ()))
63 storage.extend(d.get(attr, ()))
64 assert len(storage) == len(set(storage))
65 d[attr] = tuple(storage)
66 return type.__new__(cls, name, bases, d)
67
68
69class Node(object):
Armin Ronacher8efc5222008-04-08 14:47:40 +020070 """Baseclass for all Jinja nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020071 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020072 fields = ()
Armin Ronacherd55ab532008-04-09 16:13:39 +020073 attributes = ('lineno', 'environment')
Armin Ronacher07bc6842008-03-31 14:18:49 +020074
75 def __init__(self, *args, **kw):
76 if args:
Armin Ronachere791c2a2008-04-07 18:39:54 +020077 if len(args) != len(self.fields):
78 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020079 raise TypeError('%r takes 0 arguments' %
80 self.__class__.__name__)
81 raise TypeError('%r takes 0 or %d argument%s' % (
82 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +020083 len(self.fields),
84 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +020085 ))
Armin Ronachere791c2a2008-04-07 18:39:54 +020086 for name, arg in izip(self.fields, args):
Armin Ronacher07bc6842008-03-31 14:18:49 +020087 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +020088 for attr in self.attributes:
Armin Ronacher07bc6842008-03-31 14:18:49 +020089 setattr(self, attr, kw.pop(attr, None))
90 if kw:
91 raise TypeError('unknown keyword argument %r' %
92 iter(kw).next())
93
94 def iter_fields(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020095 """Iterate over all fields."""
96 for name in self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020097 try:
98 yield name, getattr(self, name)
99 except AttributeError:
100 pass
101
102 def iter_child_nodes(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200103 """Iterate over all child nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200104 for field, item in self.iter_fields():
105 if isinstance(item, list):
106 for n in item:
107 if isinstance(n, Node):
108 yield n
109 elif isinstance(item, Node):
110 yield item
111
Armin Ronachere791c2a2008-04-07 18:39:54 +0200112 def find(self, node_type):
113 """Find the first node of a given type."""
114 for result in self.find_all(node_type):
115 return result
116
117 def find_all(self, node_type):
118 """Find all the nodes of a given type."""
119 for child in self.iter_child_nodes():
120 if isinstance(child, node_type):
121 yield child
122 for result in child.find_all(node_type):
123 yield result
124
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200125 def copy(self):
126 """Return a deep copy of the node."""
127 result = object.__new__(self.__class__)
128 for field, value in self.iter_fields():
129 if isinstance(value, Node):
130 new_value = value.copy()
131 elif isinstance(value, list):
132 new_value = []
Armin Ronacherd436e982008-04-09 16:31:20 +0200133 for item in value:
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200134 if isinstance(item, Node):
135 item = item.copy()
136 else:
137 item = copy(item)
138 new_value.append(item)
139 else:
Armin Ronacherd436e982008-04-09 16:31:20 +0200140 new_value = copy(value)
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200141 setattr(result, field, new_value)
142 for attr in self.attributes:
143 try:
144 setattr(result, attr, getattr(self, attr))
145 except AttributeError:
146 pass
147 return result
148
Armin Ronachere791c2a2008-04-07 18:39:54 +0200149 def set_ctx(self, ctx):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200150 """Reset the context of a node and all child nodes. Per default the
151 parser will all generate nodes that have a 'load' context as it's the
152 most common one. This method is used in the parser to set assignment
153 targets and other nodes to a store context.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200154 """
155 todo = deque([self])
156 while todo:
157 node = todo.popleft()
158 if 'ctx' in node.fields:
159 node.ctx = ctx
160 todo.extend(node.iter_child_nodes())
161
Armin Ronacherd55ab532008-04-09 16:13:39 +0200162 def set_environment(self, environment):
163 """Set the environment for all nodes."""
164 todo = deque([self])
165 while todo:
166 node = todo.popleft()
167 node.environment = environment
168 todo.extend(node.iter_child_nodes())
169
Armin Ronacher07bc6842008-03-31 14:18:49 +0200170 def __repr__(self):
171 return '%s(%s)' % (
172 self.__class__.__name__,
173 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200174 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200175 )
176
177
178class Stmt(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200179 """Base node for all statements."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200180
181
182class Helper(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200183 """Nodes that exist in a specific context only."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200184
185
186class Template(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200187 """Node that represents a template."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200188 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200189
190
191class Output(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200192 """A node that holds multiple expressions which are then printed out.
193 This is used both for the `print` statement and the regular template data.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200194 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200195 fields = ('nodes',)
196
197 def optimized_nodes(self):
198 """Try to optimize the nodes."""
199 buffer = []
200 for node in self.nodes:
201 try:
202 const = unicode(node.as_const())
203 except:
204 buffer.append(node)
205 else:
206 if buffer and isinstance(buffer[-1], unicode):
207 buffer[-1] += const
208 else:
209 buffer.append(const)
210 return buffer
Armin Ronacher07bc6842008-03-31 14:18:49 +0200211
212
213class Extends(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200214 """Represents an extends statement."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200215 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200216
217
218class For(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200219 """A node that represents a for loop"""
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200220 fields = ('target', 'iter', 'body', 'else_', 'test')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200221
222
223class If(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200224 """A node that represents an if condition."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200225 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200226
227
228class Macro(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200229 """A node that represents a macro."""
230 fields = ('name', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200231
232
233class CallBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200234 """A node that represents am extended macro call."""
Armin Ronacher71082072008-04-12 14:19:36 +0200235 fields = ('call', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200236
237
238class Set(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200239 """Allows defining own variables."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200240 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200241
242
243class FilterBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200244 """Node for filter sections."""
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200245 fields = ('body', 'filter')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200246
247
248class Block(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200249 """A node that represents a block."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200250 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200251
252
253class Include(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200254 """A node that represents the include tag."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200255 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200256
257
258class Trans(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200259 """A node for translatable sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200260 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200261
262
263class ExprStmt(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200264 """A statement that evaluates an expression to None."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200265 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200266
267
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200268class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200269 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200270 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200271
272
Armin Ronacher07bc6842008-03-31 14:18:49 +0200273class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200274 """Baseclass for all expressions."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200275
276 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200277 """Return the value of the expression as constant or raise
278 `Impossible` if this was not possible.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200279 """
280 raise Impossible()
281
282 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200283 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200284 return False
285
286
287class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200288 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200289 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200290 operator = None
291
292 def as_const(self):
293 f = _binop_to_func[self.operator]
294 try:
295 return f(self.left.as_const(), self.right.as_const())
296 except:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200297 raise Impossible()
298
299
300class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200301 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200302 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200303 operator = None
304
305 def as_const(self):
306 f = _uaop_to_func[self.operator]
307 try:
308 return f(self.node.as_const())
309 except:
310 raise Impossible()
311
312
313class Name(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200314 """any name such as {{ foo }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200315 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200316
317 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200318 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200319
320
321class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200322 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200323
324
325class Const(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200326 """any constat such as {{ "foo" }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200327 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200328
329 def as_const(self):
330 return self.value
331
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200332 @classmethod
Armin Ronacherd55ab532008-04-09 16:13:39 +0200333 def from_untrusted(cls, value, lineno=None, environment=None):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200334 """Return a const object if the value is representable as
335 constant value in the generated code, otherwise it will raise
336 an `Impossible` exception."""
337 from compiler import has_safe_repr
338 if not has_safe_repr(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200339 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200340 return cls(value, lineno=lineno, environment=environment)
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200341
Armin Ronacher07bc6842008-03-31 14:18:49 +0200342
343class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200344 """For loop unpacking and some other things like multiple arguments
Armin Ronacher07bc6842008-03-31 14:18:49 +0200345 for subscripts.
346 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200347 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200348
349 def as_const(self):
350 return tuple(x.as_const() for x in self.items)
351
352 def can_assign(self):
353 for item in self.items:
354 if not item.can_assign():
355 return False
356 return True
357
358
359class List(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200360 """any list literal such as {{ [1, 2, 3] }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200361 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200362
363 def as_const(self):
364 return [x.as_const() for x in self.items]
365
366
367class Dict(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200368 """any dict literal such as {{ {1: 2, 3: 4} }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200369 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200370
371 def as_const(self):
372 return dict(x.as_const() for x in self.items)
373
374
375class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200376 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200377 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200378
379 def as_const(self):
380 return self.key.as_const(), self.value.as_const()
381
382
Armin Ronacher8efc5222008-04-08 14:47:40 +0200383class Keyword(Helper):
384 """A key, value pair for keyword arguments."""
385 fields = ('key', 'value')
386
387
Armin Ronacher07bc6842008-03-31 14:18:49 +0200388class CondExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200389 """{{ foo if bar else baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200390 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200391
392 def as_const(self):
393 if self.test.as_const():
394 return self.expr1.as_const()
395 return self.expr2.as_const()
396
397
398class Filter(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200399 """{{ foo|bar|baz }}"""
Armin Ronacherd55ab532008-04-09 16:13:39 +0200400 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200401
Armin Ronacher00d5d212008-04-13 01:10:18 +0200402 def as_const(self, obj=None):
403 if self.node is obj is None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200404 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200405 filter = self.environment.filters.get(self.name)
406 if filter is None or getattr(filter, 'contextfilter', False):
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200407 raise Impossible()
Armin Ronacher00d5d212008-04-13 01:10:18 +0200408 if obj is None:
409 obj = self.node.as_const()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200410 args = [x.as_const() for x in self.args]
411 kwargs = dict(x.as_const() for x in self.kwargs)
412 if self.dyn_args is not None:
413 try:
414 args.extend(self.dyn_args.as_const())
415 except:
416 raise Impossible()
417 if self.dyn_kwargs is not None:
418 try:
419 kwargs.update(self.dyn_kwargs.as_const())
420 except:
421 raise Impossible()
422 try:
423 return filter(obj, *args, **kwargs)
424 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200425 raise Impossible()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200426
427
Armin Ronacher07bc6842008-03-31 14:18:49 +0200428class Test(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200429 """{{ foo is lower }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200430 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200431
432
433class Call(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200434 """{{ foo(bar) }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200435 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200436
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200437 def as_const(self):
438 obj = self.node.as_const()
439 args = [x.as_const() for x in self.args]
440 kwargs = dict(x.as_const() for x in self.kwargs)
441 if self.dyn_args is not None:
442 try:
443 args.extend(self.dyn_args.as_const())
444 except:
445 raise Impossible()
446 if self.dyn_kwargs is not None:
447 try:
Armin Ronacherd55ab532008-04-09 16:13:39 +0200448 kwargs.update(self.dyn_kwargs.as_const())
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200449 except:
450 raise Impossible()
451 try:
452 return obj(*args, **kwargs)
453 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200454 raise Impossible()
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200455
Armin Ronacher07bc6842008-03-31 14:18:49 +0200456
457class Subscript(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200458 """{{ foo.bar }} and {{ foo['bar'] }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200459 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200460
461 def as_const(self):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200462 if self.ctx != 'load':
463 raise Impossible()
Armin Ronacher07bc6842008-03-31 14:18:49 +0200464 try:
Armin Ronacherc63243e2008-04-14 22:53:58 +0200465 return environmen.subscribe(self.node.as_const(), self.arg.as_const())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200466 except:
467 raise Impossible()
468
469 def can_assign(self):
470 return True
471
472
473class Slice(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200474 """1:2:3 etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200475 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200476
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200477 def as_const(self):
478 def const(obj):
479 if obj is None:
480 return obj
481 return obj.as_const()
482 return slice(const(self.start), const(self.stop), const(self.step))
483
Armin Ronacher07bc6842008-03-31 14:18:49 +0200484
485class Concat(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200486 """For {{ foo ~ bar }}. Concatenates strings."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200487 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200488
489 def as_const(self):
490 return ''.join(unicode(x.as_const()) for x in self.nodes)
491
492
493class Compare(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200494 """{{ foo == bar }}, {{ foo >= bar }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200495 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200496
Armin Ronacher625215e2008-04-13 16:31:08 +0200497 def as_const(self):
498 result = value = self.expr.as_const()
499 for op in self.ops:
500 new_value = op.expr.as_const()
501 result = _cmpop_to_func[op.op](value, new_value)
502 value = new_value
503 return result
504
Armin Ronacher07bc6842008-03-31 14:18:49 +0200505
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200506class Operand(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200507 """Operator + expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200508 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200509
510
Armin Ronacher07bc6842008-03-31 14:18:49 +0200511class Mul(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200512 """{{ foo * bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200513 operator = '*'
514
515
516class Div(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200517 """{{ foo / bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200518 operator = '/'
519
520
521class FloorDiv(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200522 """{{ foo // bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200523 operator = '//'
524
525
526class Add(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200527 """{{ foo + bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200528 operator = '+'
529
530
531class Sub(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200532 """{{ foo - bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200533 operator = '-'
534
535
536class Mod(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200537 """{{ foo % bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200538 operator = '%'
539
540
541class Pow(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200542 """{{ foo ** bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200543 operator = '**'
544
545
546class And(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200547 """{{ foo and bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200548 operator = 'and'
549
550 def as_const(self):
551 return self.left.as_const() and self.right.as_const()
552
553
554class Or(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200555 """{{ foo or bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200556 operator = 'or'
557
558 def as_const(self):
559 return self.left.as_const() or self.right.as_const()
560
561
562class Not(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200563 """{{ not foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200564 operator = 'not'
565
566
Armin Ronachere791c2a2008-04-07 18:39:54 +0200567class Neg(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200568 """{{ -foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200569 operator = '-'
570
571
Armin Ronachere791c2a2008-04-07 18:39:54 +0200572class Pos(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200573 """{{ +foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200574 operator = '+'