blob: 89c6fa24415e2636888fcfd6a445fc3848a2220d [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
Armin Ronacher4dfc9752008-04-09 15:03:29 +020019from jinja2.runtime import Undefined, subscribe
Armin Ronacher07bc6842008-03-31 14:18:49 +020020
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
38
39class Impossible(Exception):
Armin Ronacher8efc5222008-04-08 14:47:40 +020040 """Raised if the node could not perform a requested action."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020041
42
43class NodeType(type):
Armin Ronacher8efc5222008-04-08 14:47:40 +020044 """A metaclass for nodes that handles the field and attribute
45 inheritance. fields and attributes from the parent class are
46 automatically forwarded to the child."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020047
48 def __new__(cls, name, bases, d):
Armin Ronachere791c2a2008-04-07 18:39:54 +020049 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020050 storage = []
51 for base in bases:
52 storage.extend(getattr(base, attr, ()))
53 storage.extend(d.get(attr, ()))
54 assert len(storage) == len(set(storage))
55 d[attr] = tuple(storage)
56 return type.__new__(cls, name, bases, d)
57
58
59class Node(object):
Armin Ronacher8efc5222008-04-08 14:47:40 +020060 """Baseclass for all Jinja nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020061 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020062 fields = ()
Armin Ronacherd55ab532008-04-09 16:13:39 +020063 attributes = ('lineno', 'environment')
Armin Ronacher07bc6842008-03-31 14:18:49 +020064
65 def __init__(self, *args, **kw):
66 if args:
Armin Ronachere791c2a2008-04-07 18:39:54 +020067 if len(args) != len(self.fields):
68 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020069 raise TypeError('%r takes 0 arguments' %
70 self.__class__.__name__)
71 raise TypeError('%r takes 0 or %d argument%s' % (
72 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +020073 len(self.fields),
74 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +020075 ))
Armin Ronachere791c2a2008-04-07 18:39:54 +020076 for name, arg in izip(self.fields, args):
Armin Ronacher07bc6842008-03-31 14:18:49 +020077 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +020078 for attr in self.attributes:
Armin Ronacher07bc6842008-03-31 14:18:49 +020079 setattr(self, attr, kw.pop(attr, None))
80 if kw:
81 raise TypeError('unknown keyword argument %r' %
82 iter(kw).next())
83
84 def iter_fields(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020085 """Iterate over all fields."""
86 for name in self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +020087 try:
88 yield name, getattr(self, name)
89 except AttributeError:
90 pass
91
92 def iter_child_nodes(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +020093 """Iterate over all child nodes."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020094 for field, item in self.iter_fields():
95 if isinstance(item, list):
96 for n in item:
97 if isinstance(n, Node):
98 yield n
99 elif isinstance(item, Node):
100 yield item
101
Armin Ronachere791c2a2008-04-07 18:39:54 +0200102 def find(self, node_type):
103 """Find the first node of a given type."""
104 for result in self.find_all(node_type):
105 return result
106
107 def find_all(self, node_type):
108 """Find all the nodes of a given type."""
109 for child in self.iter_child_nodes():
110 if isinstance(child, node_type):
111 yield child
112 for result in child.find_all(node_type):
113 yield result
114
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200115 def copy(self):
116 """Return a deep copy of the node."""
117 result = object.__new__(self.__class__)
118 for field, value in self.iter_fields():
119 if isinstance(value, Node):
120 new_value = value.copy()
121 elif isinstance(value, list):
122 new_value = []
Armin Ronacherd436e982008-04-09 16:31:20 +0200123 for item in value:
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200124 if isinstance(item, Node):
125 item = item.copy()
126 else:
127 item = copy(item)
128 new_value.append(item)
129 else:
Armin Ronacherd436e982008-04-09 16:31:20 +0200130 new_value = copy(value)
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200131 setattr(result, field, new_value)
132 for attr in self.attributes:
133 try:
134 setattr(result, attr, getattr(self, attr))
135 except AttributeError:
136 pass
137 return result
138
Armin Ronachere791c2a2008-04-07 18:39:54 +0200139 def set_ctx(self, ctx):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200140 """Reset the context of a node and all child nodes. Per default the
141 parser will all generate nodes that have a 'load' context as it's the
142 most common one. This method is used in the parser to set assignment
143 targets and other nodes to a store context.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200144 """
145 todo = deque([self])
146 while todo:
147 node = todo.popleft()
148 if 'ctx' in node.fields:
149 node.ctx = ctx
150 todo.extend(node.iter_child_nodes())
151
Armin Ronacherd55ab532008-04-09 16:13:39 +0200152 def set_environment(self, environment):
153 """Set the environment for all nodes."""
154 todo = deque([self])
155 while todo:
156 node = todo.popleft()
157 node.environment = environment
158 todo.extend(node.iter_child_nodes())
159
Armin Ronacher07bc6842008-03-31 14:18:49 +0200160 def __repr__(self):
161 return '%s(%s)' % (
162 self.__class__.__name__,
163 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200164 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200165 )
166
167
168class Stmt(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200169 """Base node for all statements."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200170
171
172class Helper(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200173 """Nodes that exist in a specific context only."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200174
175
176class Template(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200177 """Node that represents a template."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200178 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200179
180
181class Output(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200182 """A node that holds multiple expressions which are then printed out.
183 This is used both for the `print` statement and the regular template data.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200184 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200185 fields = ('nodes',)
186
187 def optimized_nodes(self):
188 """Try to optimize the nodes."""
189 buffer = []
190 for node in self.nodes:
191 try:
192 const = unicode(node.as_const())
193 except:
194 buffer.append(node)
195 else:
196 if buffer and isinstance(buffer[-1], unicode):
197 buffer[-1] += const
198 else:
199 buffer.append(const)
200 return buffer
Armin Ronacher07bc6842008-03-31 14:18:49 +0200201
202
203class Extends(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200204 """Represents an extends statement."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200205 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200206
207
208class For(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200209 """A node that represents a for loop"""
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200210 fields = ('target', 'iter', 'body', 'else_', 'test')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200211
212
213class If(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200214 """A node that represents an if condition."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200215 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200216
217
218class Macro(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200219 """A node that represents a macro."""
220 fields = ('name', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200221
222
223class CallBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200224 """A node that represents am extended macro call."""
Armin Ronacher71082072008-04-12 14:19:36 +0200225 fields = ('call', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200226
227
228class Set(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200229 """Allows defining own variables."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200230 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200231
232
233class FilterBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200234 """Node for filter sections."""
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200235 fields = ('body', 'filter')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200236
237
238class Block(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200239 """A node that represents a block."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200240 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200241
242
243class Include(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200244 """A node that represents the include tag."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200245 fields = ('template', 'target')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200246
247
248class Trans(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200249 """A node for translatable sections."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200250 fields = ('singular', 'plural', 'indicator', 'replacements')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200251
252
253class ExprStmt(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200254 """A statement that evaluates an expression to None."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200255 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200256
257
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200258class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200259 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200260 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200261
262
Armin Ronacher07bc6842008-03-31 14:18:49 +0200263class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200264 """Baseclass for all expressions."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200265
266 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200267 """Return the value of the expression as constant or raise
268 `Impossible` if this was not possible.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200269 """
270 raise Impossible()
271
272 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200273 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200274 return False
275
276
277class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200278 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200279 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200280 operator = None
281
282 def as_const(self):
283 f = _binop_to_func[self.operator]
284 try:
285 return f(self.left.as_const(), self.right.as_const())
286 except:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200287 raise Impossible()
288
289
290class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200291 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200292 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200293 operator = None
294
295 def as_const(self):
296 f = _uaop_to_func[self.operator]
297 try:
298 return f(self.node.as_const())
299 except:
300 raise Impossible()
301
302
303class Name(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200304 """any name such as {{ foo }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200305 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200306
307 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200308 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200309
310
311class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200312 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200313
314
315class Const(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200316 """any constat such as {{ "foo" }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200317 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200318
319 def as_const(self):
320 return self.value
321
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200322 @classmethod
Armin Ronacherd55ab532008-04-09 16:13:39 +0200323 def from_untrusted(cls, value, lineno=None, environment=None):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200324 """Return a const object if the value is representable as
325 constant value in the generated code, otherwise it will raise
326 an `Impossible` exception."""
327 from compiler import has_safe_repr
328 if not has_safe_repr(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200329 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200330 return cls(value, lineno=lineno, environment=environment)
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200331
Armin Ronacher07bc6842008-03-31 14:18:49 +0200332
333class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200334 """For loop unpacking and some other things like multiple arguments
Armin Ronacher07bc6842008-03-31 14:18:49 +0200335 for subscripts.
336 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200337 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200338
339 def as_const(self):
340 return tuple(x.as_const() for x in self.items)
341
342 def can_assign(self):
343 for item in self.items:
344 if not item.can_assign():
345 return False
346 return True
347
348
349class List(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200350 """any list literal such as {{ [1, 2, 3] }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200351 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200352
353 def as_const(self):
354 return [x.as_const() for x in self.items]
355
356
357class Dict(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200358 """any dict literal such as {{ {1: 2, 3: 4} }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200359 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200360
361 def as_const(self):
362 return dict(x.as_const() for x in self.items)
363
364
365class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200366 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200367 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200368
369 def as_const(self):
370 return self.key.as_const(), self.value.as_const()
371
372
Armin Ronacher8efc5222008-04-08 14:47:40 +0200373class Keyword(Helper):
374 """A key, value pair for keyword arguments."""
375 fields = ('key', 'value')
376
377
Armin Ronacher07bc6842008-03-31 14:18:49 +0200378class CondExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200379 """{{ foo if bar else baz }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200380 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200381
382 def as_const(self):
383 if self.test.as_const():
384 return self.expr1.as_const()
385 return self.expr2.as_const()
386
387
388class Filter(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200389 """{{ foo|bar|baz }}"""
Armin Ronacherd55ab532008-04-09 16:13:39 +0200390 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200391
Armin Ronacher00d5d212008-04-13 01:10:18 +0200392 def as_const(self, obj=None):
393 if self.node is obj is None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200394 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200395 filter = self.environment.filters.get(self.name)
396 if filter is None or getattr(filter, 'contextfilter', False):
397 raise nodes.Impossible()
Armin Ronacher00d5d212008-04-13 01:10:18 +0200398 if obj is None:
399 obj = self.node.as_const()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200400 args = [x.as_const() for x in self.args]
401 kwargs = dict(x.as_const() for x in self.kwargs)
402 if self.dyn_args is not None:
403 try:
404 args.extend(self.dyn_args.as_const())
405 except:
406 raise Impossible()
407 if self.dyn_kwargs is not None:
408 try:
409 kwargs.update(self.dyn_kwargs.as_const())
410 except:
411 raise Impossible()
412 try:
413 return filter(obj, *args, **kwargs)
414 except:
415 raise nodes.Impossible()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200416
417
Armin Ronacher07bc6842008-03-31 14:18:49 +0200418class Test(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200419 """{{ foo is lower }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200420 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200421
422
423class Call(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200424 """{{ foo(bar) }}"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200425 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200426
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200427 def as_const(self):
428 obj = self.node.as_const()
429 args = [x.as_const() for x in self.args]
430 kwargs = dict(x.as_const() for x in self.kwargs)
431 if self.dyn_args is not None:
432 try:
433 args.extend(self.dyn_args.as_const())
434 except:
435 raise Impossible()
436 if self.dyn_kwargs is not None:
437 try:
Armin Ronacherd55ab532008-04-09 16:13:39 +0200438 kwargs.update(self.dyn_kwargs.as_const())
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200439 except:
440 raise Impossible()
441 try:
442 return obj(*args, **kwargs)
443 except:
444 raise nodes.Impossible()
445
Armin Ronacher07bc6842008-03-31 14:18:49 +0200446
447class Subscript(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200448 """{{ foo.bar }} and {{ foo['bar'] }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200449 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200450
451 def as_const(self):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200452 if self.ctx != 'load':
453 raise Impossible()
Armin Ronacher07bc6842008-03-31 14:18:49 +0200454 try:
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200455 return subscribe(self.node.as_const(), self.arg.as_const())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200456 except:
457 raise Impossible()
458
459 def can_assign(self):
460 return True
461
462
463class Slice(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200464 """1:2:3 etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200465 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200466
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200467 def as_const(self):
468 def const(obj):
469 if obj is None:
470 return obj
471 return obj.as_const()
472 return slice(const(self.start), const(self.stop), const(self.step))
473
Armin Ronacher07bc6842008-03-31 14:18:49 +0200474
475class Concat(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200476 """For {{ foo ~ bar }}. Concatenates strings."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200477 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200478
479 def as_const(self):
480 return ''.join(unicode(x.as_const()) for x in self.nodes)
481
482
483class Compare(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200484 """{{ foo == bar }}, {{ foo >= bar }} etc."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200485 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200486
487
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200488class Operand(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200489 """Operator + expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200490 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200491
492
Armin Ronacher07bc6842008-03-31 14:18:49 +0200493class Mul(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200494 """{{ foo * bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200495 operator = '*'
496
497
498class Div(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200499 """{{ foo / bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200500 operator = '/'
501
502
503class FloorDiv(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200504 """{{ foo // bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200505 operator = '//'
506
507
508class Add(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200509 """{{ foo + bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200510 operator = '+'
511
512
513class Sub(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200514 """{{ foo - bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200515 operator = '-'
516
517
518class Mod(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200519 """{{ foo % bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200520 operator = '%'
521
522
523class Pow(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200524 """{{ foo ** bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200525 operator = '**'
526
527
528class And(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200529 """{{ foo and bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200530 operator = 'and'
531
532 def as_const(self):
533 return self.left.as_const() and self.right.as_const()
534
535
536class Or(BinExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200537 """{{ foo or bar }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200538 operator = 'or'
539
540 def as_const(self):
541 return self.left.as_const() or self.right.as_const()
542
543
544class Not(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200545 """{{ not foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200546 operator = 'not'
547
548
Armin Ronachere791c2a2008-04-07 18:39:54 +0200549class Neg(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200550 """{{ -foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200551 operator = '-'
552
553
Armin Ronachere791c2a2008-04-07 18:39:54 +0200554class Pos(UnaryExpr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200555 """{{ +foo }}"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200556 operator = '+'