blob: 0d921a7b5ea507d7bcd5ba866be19208c6e998cf [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 Ronacher7ceced52008-05-03 10:15:31 +020016from copy import copy
Armin Ronacher4f7d2d52008-04-22 10:40:26 +020017from types import FunctionType
Armin Ronacher07bc6842008-03-31 14:18:49 +020018from itertools import chain, izip
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020019from collections import deque
Armin Ronacherd84ec462008-04-29 13:43:16 +020020from jinja2.utils import Markup
Armin Ronacher07bc6842008-03-31 14:18:49 +020021
22
23_binop_to_func = {
24 '*': operator.mul,
25 '/': operator.truediv,
26 '//': operator.floordiv,
27 '**': operator.pow,
28 '%': operator.mod,
29 '+': operator.add,
30 '-': operator.sub
31}
32
33_uaop_to_func = {
34 'not': operator.not_,
35 '+': operator.pos,
36 '-': operator.neg
37}
38
Armin Ronacher625215e2008-04-13 16:31:08 +020039_cmpop_to_func = {
40 'eq': operator.eq,
41 'ne': operator.ne,
42 'gt': operator.gt,
43 'gteq': operator.ge,
44 'lt': operator.lt,
45 'lteq': operator.le,
Armin Ronacherb5124e62008-04-25 00:36:14 +020046 'in': lambda a, b: a in b,
47 'notin': lambda a, b: a not in b
Armin Ronacher625215e2008-04-13 16:31:08 +020048}
49
Armin Ronacher07bc6842008-03-31 14:18:49 +020050
Armin Ronacher023b5e92008-05-08 11:03:10 +020051# if this is `True` no new Node classes can be created.
52_node_setup_finished = False
53
54
Armin Ronacher07bc6842008-03-31 14:18:49 +020055class Impossible(Exception):
Armin Ronacher8efc5222008-04-08 14:47:40 +020056 """Raised if the node could not perform a requested action."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020057
58
59class NodeType(type):
Armin Ronacher8efc5222008-04-08 14:47:40 +020060 """A metaclass for nodes that handles the field and attribute
61 inheritance. fields and attributes from the parent class are
62 automatically forwarded to the child."""
Armin Ronacher07bc6842008-03-31 14:18:49 +020063
64 def __new__(cls, name, bases, d):
Armin Ronacher023b5e92008-05-08 11:03:10 +020065 if __debug__ and _node_setup_finished:
66 raise TypeError('Can\'t create custom node types.')
Armin Ronachere791c2a2008-04-07 18:39:54 +020067 for attr in 'fields', 'attributes':
Armin Ronacher07bc6842008-03-31 14:18:49 +020068 storage = []
Armin Ronacher7324eb82008-04-21 07:55:52 +020069 storage.extend(getattr(bases[0], attr, ()))
Armin Ronacher07bc6842008-03-31 14:18:49 +020070 storage.extend(d.get(attr, ()))
Armin Ronacher7324eb82008-04-21 07:55:52 +020071 assert len(bases) == 1, 'multiple inheritance not allowed'
72 assert len(storage) == len(set(storage)), 'layout conflict'
Armin Ronacher07bc6842008-03-31 14:18:49 +020073 d[attr] = tuple(storage)
Armin Ronacher023b5e92008-05-08 11:03:10 +020074 d.setdefault('abstract', False)
Armin Ronacher7324eb82008-04-21 07:55:52 +020075 return type.__new__(cls, name, bases, d)
Armin Ronacher07bc6842008-03-31 14:18:49 +020076
77
78class Node(object):
Armin Ronacher023b5e92008-05-08 11:03:10 +020079 """Baseclass for all Jinja2 nodes. There are a number of nodes available
80 of different types. There are three major types:
81
82 - :class:`Stmt`: statements
83 - :class:`Expr`: expressions
84 - :class:`Helper`: helper nodes
85 - :class:`Template`: the outermost wrapper node
86
87 All nodes have fields and attributes. Fields may be other nodes, lists,
88 or arbitrary values. Fields are passed to the constructor as regular
89 positional arguments, attributes as keyword arguments. Each node has
90 two attributes: `lineno` (the line number of the node) and `environment`.
91 The `environment` attribute is set at the end of the parsing process for
92 all nodes automatically.
93 """
Armin Ronacher07bc6842008-03-31 14:18:49 +020094 __metaclass__ = NodeType
Armin Ronachere791c2a2008-04-07 18:39:54 +020095 fields = ()
Armin Ronacherd55ab532008-04-09 16:13:39 +020096 attributes = ('lineno', 'environment')
Armin Ronacher023b5e92008-05-08 11:03:10 +020097 abstract = True
Armin Ronacher07bc6842008-03-31 14:18:49 +020098
Armin Ronacher023b5e92008-05-08 11:03:10 +020099 def __init__(self, *fields, **attributes):
100 if fields:
101 if len(fields) != len(self.fields):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200102 if not self.fields:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200103 raise TypeError('%r takes 0 arguments' %
104 self.__class__.__name__)
105 raise TypeError('%r takes 0 or %d argument%s' % (
106 self.__class__.__name__,
Armin Ronachere791c2a2008-04-07 18:39:54 +0200107 len(self.fields),
108 len(self.fields) != 1 and 's' or ''
Armin Ronacher07bc6842008-03-31 14:18:49 +0200109 ))
Armin Ronacher023b5e92008-05-08 11:03:10 +0200110 for name, arg in izip(self.fields, fields):
Armin Ronacher07bc6842008-03-31 14:18:49 +0200111 setattr(self, name, arg)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200112 for attr in self.attributes:
Armin Ronacher023b5e92008-05-08 11:03:10 +0200113 setattr(self, attr, attributes.pop(attr, None))
114 if attributes:
115 raise TypeError('unknown attribute %r' %
116 iter(attributes).next())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200117
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200118 def iter_fields(self, exclude=()):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200119 """This method iterates over all fields that are defined and yields
120 ``(key, value)`` tuples. Optionally a parameter of ignored fields
121 can be provided.
122 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200123 for name in self.fields:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200124 if name not in exclude:
125 try:
126 yield name, getattr(self, name)
127 except AttributeError:
128 pass
Armin Ronacher07bc6842008-03-31 14:18:49 +0200129
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200130 def iter_child_nodes(self, exclude=()):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200131 """Iterates over all direct child nodes of the node. This iterates
132 over all fields and yields the values of they are nodes. If the value
133 of a field is a list all the nodes in that list are returned.
134 """
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200135 for field, item in self.iter_fields(exclude):
Armin Ronacher07bc6842008-03-31 14:18:49 +0200136 if isinstance(item, list):
137 for n in item:
138 if isinstance(n, Node):
139 yield n
140 elif isinstance(item, Node):
141 yield item
142
Armin Ronachere791c2a2008-04-07 18:39:54 +0200143 def find(self, node_type):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200144 """Find the first node of a given type. If no such node exists the
145 return value is `None`.
146 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200147 for result in self.find_all(node_type):
148 return result
149
150 def find_all(self, node_type):
151 """Find all the nodes of a given type."""
152 for child in self.iter_child_nodes():
153 if isinstance(child, node_type):
154 yield child
155 for result in child.find_all(node_type):
156 yield result
157
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200158 def copy(self):
159 """Return a deep copy of the node."""
160 result = object.__new__(self.__class__)
161 for field, value in self.iter_fields():
162 if isinstance(value, Node):
163 new_value = value.copy()
164 elif isinstance(value, list):
165 new_value = []
Armin Ronacherd436e982008-04-09 16:31:20 +0200166 for item in value:
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200167 if isinstance(item, Node):
168 item = item.copy()
169 else:
170 item = copy(item)
171 new_value.append(item)
172 else:
Armin Ronacherd436e982008-04-09 16:31:20 +0200173 new_value = copy(value)
Armin Ronacher0ecb8592008-04-09 16:29:47 +0200174 setattr(result, field, new_value)
175 for attr in self.attributes:
176 try:
177 setattr(result, attr, getattr(self, attr))
178 except AttributeError:
179 pass
180 return result
181
Armin Ronachere791c2a2008-04-07 18:39:54 +0200182 def set_ctx(self, ctx):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200183 """Reset the context of a node and all child nodes. Per default the
184 parser will all generate nodes that have a 'load' context as it's the
185 most common one. This method is used in the parser to set assignment
186 targets and other nodes to a store context.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200187 """
188 todo = deque([self])
189 while todo:
190 node = todo.popleft()
191 if 'ctx' in node.fields:
192 node.ctx = ctx
193 todo.extend(node.iter_child_nodes())
Armin Ronacher023b5e92008-05-08 11:03:10 +0200194 return self
Armin Ronachere791c2a2008-04-07 18:39:54 +0200195
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200196 def set_lineno(self, lineno, override=False):
197 """Set the line numbers of the node and children."""
198 todo = deque([self])
199 while todo:
200 node = todo.popleft()
201 if 'lineno' in node.attributes:
202 if node.lineno is None or override:
203 node.lineno = lineno
204 todo.extend(node.iter_child_nodes())
Armin Ronacher023b5e92008-05-08 11:03:10 +0200205 return self
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200206
Armin Ronacherd55ab532008-04-09 16:13:39 +0200207 def set_environment(self, environment):
208 """Set the environment for all nodes."""
209 todo = deque([self])
210 while todo:
211 node = todo.popleft()
212 node.environment = environment
213 todo.extend(node.iter_child_nodes())
Armin Ronacher023b5e92008-05-08 11:03:10 +0200214 return self
Armin Ronacherd55ab532008-04-09 16:13:39 +0200215
Armin Ronacher07bc6842008-03-31 14:18:49 +0200216 def __repr__(self):
217 return '%s(%s)' % (
218 self.__class__.__name__,
219 ', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
Armin Ronachere791c2a2008-04-07 18:39:54 +0200220 arg in self.fields)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200221 )
222
223
224class Stmt(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200225 """Base node for all statements."""
Armin Ronacher023b5e92008-05-08 11:03:10 +0200226 abstract = True
Armin Ronacher07bc6842008-03-31 14:18:49 +0200227
228
229class Helper(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200230 """Nodes that exist in a specific context only."""
Armin Ronacher023b5e92008-05-08 11:03:10 +0200231 abstract = True
Armin Ronacher07bc6842008-03-31 14:18:49 +0200232
233
234class Template(Node):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200235 """Node that represents a template. This must be the outermost node that
236 is passed to the compiler.
237 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200238 fields = ('body',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200239
240
241class Output(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200242 """A node that holds multiple expressions which are then printed out.
243 This is used both for the `print` statement and the regular template data.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200244 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200245 fields = ('nodes',)
246
247 def optimized_nodes(self):
248 """Try to optimize the nodes."""
249 buffer = []
250 for node in self.nodes:
251 try:
252 const = unicode(node.as_const())
253 except:
254 buffer.append(node)
255 else:
256 if buffer and isinstance(buffer[-1], unicode):
257 buffer[-1] += const
258 else:
259 buffer.append(const)
260 return buffer
Armin Ronacher07bc6842008-03-31 14:18:49 +0200261
262
263class Extends(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200264 """Represents an extends statement."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200265 fields = ('template',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200266
267
268class For(Stmt):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200269 """The for loop. `target` is the target for the iteration (usually a
270 :class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list
271 of nodes that are used as loop-body, and `else_` a list of nodes for the
272 `else` block. If no else node exists it has to be an empty list.
273
274 For filtered nodes an expression can be stored as `test`, otherwise `None`.
275 """
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200276 fields = ('target', 'iter', 'body', 'else_', 'test')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200277
278
279class If(Stmt):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200280 """If `test` is true, `body` is rendered, else `else_`."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200281 fields = ('test', 'body', 'else_')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200282
283
284class Macro(Stmt):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200285 """A macro definition. `name` is the name of the macro, `args` a list of
286 arguments and `defaults` a list of defaults if there are any. `body` is
287 a list of nodes for the macro body.
288 """
Armin Ronacher8efc5222008-04-08 14:47:40 +0200289 fields = ('name', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200290
291
292class CallBlock(Stmt):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200293 """Like a macro without a name but a call instead. `call` is called with
294 the unnamed macro as `caller` argument this node holds.
295 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200296 fields = ('call', 'args', 'defaults', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200297
298
299class Set(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200300 """Allows defining own variables."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200301 fields = ('name', 'expr')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200302
303
304class FilterBlock(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200305 """Node for filter sections."""
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200306 fields = ('body', 'filter')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200307
308
309class Block(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200310 """A node that represents a block."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200311 fields = ('name', 'body')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200312
313
314class Include(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200315 """A node that represents the include tag."""
Armin Ronacherea847c52008-05-02 20:04:32 +0200316 fields = ('template', 'with_context')
Armin Ronacher0611e492008-04-25 23:44:14 +0200317
318
319class Import(Stmt):
320 """A node that represents the import tag."""
Armin Ronacherea847c52008-05-02 20:04:32 +0200321 fields = ('template', 'target', 'with_context')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200322
323
Armin Ronacher0611e492008-04-25 23:44:14 +0200324class FromImport(Stmt):
325 """A node that represents the from import tag. It's important to not
326 pass unsafe names to the name attribute. The compiler translates the
327 attribute lookups directly into getattr calls and does *not* use the
328 subscribe callback of the interface. As exported variables may not
329 start with double underscores (which the parser asserts) this is not a
330 problem for regular Jinja code, but if this node is used in an extension
331 extra care must be taken.
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200332
333 The list of names may contain tuples if aliases are wanted.
Armin Ronacher0611e492008-04-25 23:44:14 +0200334 """
Armin Ronacherea847c52008-05-02 20:04:32 +0200335 fields = ('template', 'names', 'with_context')
Armin Ronacher0611e492008-04-25 23:44:14 +0200336
337
Armin Ronacher07bc6842008-03-31 14:18:49 +0200338class ExprStmt(Stmt):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200339 """A statement that evaluates an expression and discards the result."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200340 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200341
342
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200343class Assign(Stmt):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200344 """Assigns an expression to a target."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200345 fields = ('target', 'node')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200346
347
Armin Ronacher07bc6842008-03-31 14:18:49 +0200348class Expr(Node):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200349 """Baseclass for all expressions."""
Armin Ronacher023b5e92008-05-08 11:03:10 +0200350 abstract = True
Armin Ronacher07bc6842008-03-31 14:18:49 +0200351
352 def as_const(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200353 """Return the value of the expression as constant or raise
Armin Ronacher023b5e92008-05-08 11:03:10 +0200354 :exc:`Impossible` if this was not possible:
355
356 >>> Add(Const(23), Const(42)).as_const()
357 65
358 >>> Add(Const(23), Name('var', 'load')).as_const()
359 Traceback (most recent call last):
360 ...
361 Impossible
362
363 This requires the `environment` attribute of all nodes to be
364 set to the environment that created the nodes.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200365 """
366 raise Impossible()
367
368 def can_assign(self):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200369 """Check if it's possible to assign something to this node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200370 return False
371
372
373class BinExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200374 """Baseclass for all binary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200375 fields = ('left', 'right')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200376 operator = None
377
378 def as_const(self):
379 f = _binop_to_func[self.operator]
380 try:
381 return f(self.left.as_const(), self.right.as_const())
382 except:
Armin Ronacher07bc6842008-03-31 14:18:49 +0200383 raise Impossible()
384
385
386class UnaryExpr(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200387 """Baseclass for all unary expressions."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200388 fields = ('node',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200389 operator = None
390
391 def as_const(self):
392 f = _uaop_to_func[self.operator]
393 try:
394 return f(self.node.as_const())
395 except:
396 raise Impossible()
397
398
399class Name(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200400 """Looks up a name or stores a value in a name.
401 The `ctx` of the node can be one of the following values:
402
403 - `store`: store a value in the name
404 - `load`: load that name
405 - `param`: like `store` but if the name was defined as function parameter.
406 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200407 fields = ('name', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200408
409 def can_assign(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200410 return self.name not in ('true', 'false', 'none')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200411
412
413class Literal(Expr):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200414 """Baseclass for literals."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200415
416
417class Const(Literal):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200418 """All constant values. The parser will return this node for simple
419 constants such as ``42`` or ``"foo"`` but it can be used to store more
420 complex values such as lists too. Only constants with a safe
421 representation (objects where ``eval(repr(x)) == x`` is true).
422 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200423 fields = ('value',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200424
425 def as_const(self):
426 return self.value
427
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200428 @classmethod
Armin Ronacherd55ab532008-04-09 16:13:39 +0200429 def from_untrusted(cls, value, lineno=None, environment=None):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200430 """Return a const object if the value is representable as
431 constant value in the generated code, otherwise it will raise
Armin Ronacher2e9396b2008-04-16 14:21:57 +0200432 an `Impossible` exception.
433 """
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200434 from compiler import has_safe_repr
435 if not has_safe_repr(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200436 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200437 return cls(value, lineno=lineno, environment=environment)
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200438
Armin Ronacher07bc6842008-03-31 14:18:49 +0200439
440class Tuple(Literal):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200441 """For loop unpacking and some other things like multiple arguments
Armin Ronacher023b5e92008-05-08 11:03:10 +0200442 for subscripts. Like for :class:`Name` `ctx` specifies if the tuple
443 is used for loading the names or storing.
Armin Ronacher07bc6842008-03-31 14:18:49 +0200444 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200445 fields = ('items', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200446
447 def as_const(self):
448 return tuple(x.as_const() for x in self.items)
449
450 def can_assign(self):
451 for item in self.items:
452 if not item.can_assign():
453 return False
454 return True
455
456
457class List(Literal):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200458 """Any list literal such as ``[1, 2, 3]``"""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200459 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200460
461 def as_const(self):
462 return [x.as_const() for x in self.items]
463
464
465class Dict(Literal):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200466 """Any dict literal such as ``{1: 2, 3: 4}``. The items must be a list of
467 :class:`Pair` nodes.
468 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200469 fields = ('items',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200470
471 def as_const(self):
472 return dict(x.as_const() for x in self.items)
473
474
475class Pair(Helper):
Armin Ronacher8efc5222008-04-08 14:47:40 +0200476 """A key, value pair for dicts."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200477 fields = ('key', 'value')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200478
479 def as_const(self):
480 return self.key.as_const(), self.value.as_const()
481
482
Armin Ronacher8efc5222008-04-08 14:47:40 +0200483class Keyword(Helper):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200484 """A key, value pair for keyword arguments where key is a string."""
Armin Ronacher8efc5222008-04-08 14:47:40 +0200485 fields = ('key', 'value')
486
487
Armin Ronacher07bc6842008-03-31 14:18:49 +0200488class CondExpr(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200489 """A conditional expression (inline if expression). (``{{
490 foo if bar else baz }}``)
491 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200492 fields = ('test', 'expr1', 'expr2')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200493
494 def as_const(self):
495 if self.test.as_const():
496 return self.expr1.as_const()
497 return self.expr2.as_const()
498
499
500class Filter(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200501 """This node applies a filter on an expression. `name` is the name of
502 the filter, the rest of the fields are the same as for :class:`Call`.
503 """
Armin Ronacherd55ab532008-04-09 16:13:39 +0200504 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200505
Armin Ronacher00d5d212008-04-13 01:10:18 +0200506 def as_const(self, obj=None):
507 if self.node is obj is None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200508 raise Impossible()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200509 filter = self.environment.filters.get(self.name)
510 if filter is None or getattr(filter, 'contextfilter', False):
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200511 raise Impossible()
Armin Ronacher00d5d212008-04-13 01:10:18 +0200512 if obj is None:
513 obj = self.node.as_const()
Armin Ronacherd55ab532008-04-09 16:13:39 +0200514 args = [x.as_const() for x in self.args]
Armin Ronacher9a027f42008-04-17 11:13:40 +0200515 if getattr(filter, 'environmentfilter', False):
516 args.insert(0, self.environment)
Armin Ronacherd55ab532008-04-09 16:13:39 +0200517 kwargs = dict(x.as_const() for x in self.kwargs)
518 if self.dyn_args is not None:
519 try:
520 args.extend(self.dyn_args.as_const())
521 except:
522 raise Impossible()
523 if self.dyn_kwargs is not None:
524 try:
525 kwargs.update(self.dyn_kwargs.as_const())
526 except:
527 raise Impossible()
528 try:
529 return filter(obj, *args, **kwargs)
530 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200531 raise Impossible()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200532
533
Armin Ronacher07bc6842008-03-31 14:18:49 +0200534class Test(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200535 """Applies a test on an expression. `name` is the name of the test, the
536 rest of the fields are the same as for :class:`Call`.
537 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200538 fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200539
540
541class Call(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200542 """Calls an expression. `args` is a list of arguments, `kwargs` a list
543 of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
544 and `dyn_kwargs` has to be either `None` or a node that is used as
545 node for dynamic positional (``*args``) or keyword (``**kwargs``)
546 arguments.
547 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200548 fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200549
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200550 def as_const(self):
551 obj = self.node.as_const()
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200552
553 # don't evaluate context functions
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200554 args = [x.as_const() for x in self.args]
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200555 if type(obj) is FunctionType:
556 if getattr(obj, 'contextfunction', False):
557 raise Impossible()
558 elif obj.environmentfunction:
559 args.insert(0, self.environment)
560
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200561 kwargs = dict(x.as_const() for x in self.kwargs)
562 if self.dyn_args is not None:
563 try:
564 args.extend(self.dyn_args.as_const())
565 except:
566 raise Impossible()
567 if self.dyn_kwargs is not None:
568 try:
Armin Ronacherd55ab532008-04-09 16:13:39 +0200569 kwargs.update(self.dyn_kwargs.as_const())
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200570 except:
571 raise Impossible()
572 try:
573 return obj(*args, **kwargs)
574 except:
Christoph Hacke9e43bb2008-04-13 23:35:48 +0200575 raise Impossible()
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200576
Armin Ronacher07bc6842008-03-31 14:18:49 +0200577
578class Subscript(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200579 """Subscribe an expression by an argument. This node performs a dict
580 and an attribute lookup on the object whatever succeeds.
581 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200582 fields = ('node', 'arg', 'ctx')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200583
584 def as_const(self):
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200585 if self.ctx != 'load':
586 raise Impossible()
Armin Ronacher07bc6842008-03-31 14:18:49 +0200587 try:
Benjamin Wieganda3152742008-04-28 18:07:52 +0200588 return self.environment.subscribe(self.node.as_const(),
589 self.arg.as_const())
Armin Ronacher07bc6842008-03-31 14:18:49 +0200590 except:
591 raise Impossible()
592
593 def can_assign(self):
Armin Ronacher4f7d2d52008-04-22 10:40:26 +0200594 return False
Armin Ronacher07bc6842008-03-31 14:18:49 +0200595
596
597class Slice(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200598 """Represents a slice object. This must only be used as argument for
599 :class:`Subscript`.
600 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200601 fields = ('start', 'stop', 'step')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200602
Armin Ronacher4dfc9752008-04-09 15:03:29 +0200603 def as_const(self):
604 def const(obj):
605 if obj is None:
606 return obj
607 return obj.as_const()
608 return slice(const(self.start), const(self.stop), const(self.step))
609
Armin Ronacher07bc6842008-03-31 14:18:49 +0200610
611class Concat(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200612 """Concatenates the list of expressions provided after converting them to
613 unicode.
614 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200615 fields = ('nodes',)
Armin Ronacher07bc6842008-03-31 14:18:49 +0200616
617 def as_const(self):
618 return ''.join(unicode(x.as_const()) for x in self.nodes)
619
620
621class Compare(Expr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200622 """Compares an expression with some other expressions. `ops` must be a
623 list of :class:`Operand`\s.
624 """
Armin Ronachere791c2a2008-04-07 18:39:54 +0200625 fields = ('expr', 'ops')
Armin Ronacher07bc6842008-03-31 14:18:49 +0200626
Armin Ronacher625215e2008-04-13 16:31:08 +0200627 def as_const(self):
628 result = value = self.expr.as_const()
Armin Ronacherb5124e62008-04-25 00:36:14 +0200629 try:
630 for op in self.ops:
631 new_value = op.expr.as_const()
632 result = _cmpop_to_func[op.op](value, new_value)
633 value = new_value
634 except:
635 raise Impossible()
Armin Ronacher625215e2008-04-13 16:31:08 +0200636 return result
637
Armin Ronacher07bc6842008-03-31 14:18:49 +0200638
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200639class Operand(Helper):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200640 """Holds an operator and an expression."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200641 fields = ('op', 'expr')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200642
Armin Ronacher023b5e92008-05-08 11:03:10 +0200643if __debug__:
644 Operand.__doc__ += '\nThe following operators are available: ' + \
645 ', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
646 set(_uaop_to_func) | set(_cmpop_to_func)))
647
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200648
Armin Ronacher07bc6842008-03-31 14:18:49 +0200649class Mul(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200650 """Multiplies the left with the right node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200651 operator = '*'
652
653
654class Div(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200655 """Divides the left by the right node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200656 operator = '/'
657
658
659class FloorDiv(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200660 """Divides the left by the right node and truncates conver the
661 result into an integer by truncating.
662 """
Armin Ronacher07bc6842008-03-31 14:18:49 +0200663 operator = '//'
664
665
666class Add(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200667 """Add the left to the right node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200668 operator = '+'
669
670
671class Sub(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200672 """Substract the right from the left node."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200673 operator = '-'
674
675
676class Mod(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200677 """Left modulo right."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200678 operator = '%'
679
680
681class Pow(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200682 """Left to the power of right."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200683 operator = '**'
684
685
686class And(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200687 """Short circuited AND."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200688 operator = 'and'
689
690 def as_const(self):
691 return self.left.as_const() and self.right.as_const()
692
693
694class Or(BinExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200695 """Short circuited OR."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200696 operator = 'or'
697
698 def as_const(self):
699 return self.left.as_const() or self.right.as_const()
700
701
702class Not(UnaryExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200703 """Negate the expression."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200704 operator = 'not'
705
706
Armin Ronachere791c2a2008-04-07 18:39:54 +0200707class Neg(UnaryExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200708 """Make the expression negative."""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200709 operator = '-'
710
711
Armin Ronachere791c2a2008-04-07 18:39:54 +0200712class Pos(UnaryExpr):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200713 """Make the expression positive (noop for most expressions)"""
Armin Ronacher07bc6842008-03-31 14:18:49 +0200714 operator = '+'
Armin Ronacher023b5e92008-05-08 11:03:10 +0200715
716
717# Helpers for extensions
718
719
720class EnvironmentAttribute(Expr):
721 """Loads an attribute from the environment object. This is useful for
722 extensions that want to call a callback stored on the environment.
723 """
724 fields = ('name',)
725
726
727class ExtensionAttribute(Expr):
728 """Returns the attribute of an extension bound to the environment.
729 The identifier is the identifier of the :class:`Extension`.
730 """
731 fields = ('identifier', 'attr')
732
733
734class ImportedName(Expr):
735 """If created with an import name the import name is returned on node
736 access. For example ``ImportedName('cgi.escape')`` returns the `escape`
737 function from the cgi module on evaluation. Imports are optimized by the
738 compiler so there is no need to assign them to local variables.
739 """
740 fields = ('importname',)
741
742
743class InternalName(Expr):
744 """An internal name in the compiler. You cannot create these nodes
745 yourself but the parser provides a `free_identifier` method that creates
746 a new identifier for you. This identifier is not available from the
747 template and is not threated specially by the compiler.
748 """
749 fields = ('name',)
750
751 def __init__(self):
752 raise TypeError('Can\'t create internal names. Use the '
753 '`free_identifier` method on a parser.')
754
755
756class MarkSafe(Expr):
757 """Mark the wrapped expression as safe (wrap it as `Markup`)."""
758 fields = ('expr',)
759
760 def as_const(self):
761 return Markup(self.expr.as_const())
762
763
764# and close down
765_node_setup_finished = True