Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/jinja2/nodes.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 """AST nodes generated by the parser for the compiler. Also provides | |
3 some node tree helper functions used by the parser and compiler in order | |
4 to normalize nodes. | |
5 """ | |
6 import operator | |
7 from collections import deque | |
8 | |
9 from markupsafe import Markup | |
10 | |
11 from ._compat import izip | |
12 from ._compat import PY2 | |
13 from ._compat import text_type | |
14 from ._compat import with_metaclass | |
15 | |
16 _binop_to_func = { | |
17 "*": operator.mul, | |
18 "/": operator.truediv, | |
19 "//": operator.floordiv, | |
20 "**": operator.pow, | |
21 "%": operator.mod, | |
22 "+": operator.add, | |
23 "-": operator.sub, | |
24 } | |
25 | |
26 _uaop_to_func = {"not": operator.not_, "+": operator.pos, "-": operator.neg} | |
27 | |
28 _cmpop_to_func = { | |
29 "eq": operator.eq, | |
30 "ne": operator.ne, | |
31 "gt": operator.gt, | |
32 "gteq": operator.ge, | |
33 "lt": operator.lt, | |
34 "lteq": operator.le, | |
35 "in": lambda a, b: a in b, | |
36 "notin": lambda a, b: a not in b, | |
37 } | |
38 | |
39 | |
40 class Impossible(Exception): | |
41 """Raised if the node could not perform a requested action.""" | |
42 | |
43 | |
44 class NodeType(type): | |
45 """A metaclass for nodes that handles the field and attribute | |
46 inheritance. fields and attributes from the parent class are | |
47 automatically forwarded to the child.""" | |
48 | |
49 def __new__(mcs, name, bases, d): | |
50 for attr in "fields", "attributes": | |
51 storage = [] | |
52 storage.extend(getattr(bases[0], attr, ())) | |
53 storage.extend(d.get(attr, ())) | |
54 assert len(bases) == 1, "multiple inheritance not allowed" | |
55 assert len(storage) == len(set(storage)), "layout conflict" | |
56 d[attr] = tuple(storage) | |
57 d.setdefault("abstract", False) | |
58 return type.__new__(mcs, name, bases, d) | |
59 | |
60 | |
61 class EvalContext(object): | |
62 """Holds evaluation time information. Custom attributes can be attached | |
63 to it in extensions. | |
64 """ | |
65 | |
66 def __init__(self, environment, template_name=None): | |
67 self.environment = environment | |
68 if callable(environment.autoescape): | |
69 self.autoescape = environment.autoescape(template_name) | |
70 else: | |
71 self.autoescape = environment.autoescape | |
72 self.volatile = False | |
73 | |
74 def save(self): | |
75 return self.__dict__.copy() | |
76 | |
77 def revert(self, old): | |
78 self.__dict__.clear() | |
79 self.__dict__.update(old) | |
80 | |
81 | |
82 def get_eval_context(node, ctx): | |
83 if ctx is None: | |
84 if node.environment is None: | |
85 raise RuntimeError( | |
86 "if no eval context is passed, the " | |
87 "node must have an attached " | |
88 "environment." | |
89 ) | |
90 return EvalContext(node.environment) | |
91 return ctx | |
92 | |
93 | |
94 class Node(with_metaclass(NodeType, object)): | |
95 """Baseclass for all Jinja nodes. There are a number of nodes available | |
96 of different types. There are four major types: | |
97 | |
98 - :class:`Stmt`: statements | |
99 - :class:`Expr`: expressions | |
100 - :class:`Helper`: helper nodes | |
101 - :class:`Template`: the outermost wrapper node | |
102 | |
103 All nodes have fields and attributes. Fields may be other nodes, lists, | |
104 or arbitrary values. Fields are passed to the constructor as regular | |
105 positional arguments, attributes as keyword arguments. Each node has | |
106 two attributes: `lineno` (the line number of the node) and `environment`. | |
107 The `environment` attribute is set at the end of the parsing process for | |
108 all nodes automatically. | |
109 """ | |
110 | |
111 fields = () | |
112 attributes = ("lineno", "environment") | |
113 abstract = True | |
114 | |
115 def __init__(self, *fields, **attributes): | |
116 if self.abstract: | |
117 raise TypeError("abstract nodes are not instantiable") | |
118 if fields: | |
119 if len(fields) != len(self.fields): | |
120 if not self.fields: | |
121 raise TypeError("%r takes 0 arguments" % self.__class__.__name__) | |
122 raise TypeError( | |
123 "%r takes 0 or %d argument%s" | |
124 % ( | |
125 self.__class__.__name__, | |
126 len(self.fields), | |
127 len(self.fields) != 1 and "s" or "", | |
128 ) | |
129 ) | |
130 for name, arg in izip(self.fields, fields): | |
131 setattr(self, name, arg) | |
132 for attr in self.attributes: | |
133 setattr(self, attr, attributes.pop(attr, None)) | |
134 if attributes: | |
135 raise TypeError("unknown attribute %r" % next(iter(attributes))) | |
136 | |
137 def iter_fields(self, exclude=None, only=None): | |
138 """This method iterates over all fields that are defined and yields | |
139 ``(key, value)`` tuples. Per default all fields are returned, but | |
140 it's possible to limit that to some fields by providing the `only` | |
141 parameter or to exclude some using the `exclude` parameter. Both | |
142 should be sets or tuples of field names. | |
143 """ | |
144 for name in self.fields: | |
145 if ( | |
146 (exclude is only is None) | |
147 or (exclude is not None and name not in exclude) | |
148 or (only is not None and name in only) | |
149 ): | |
150 try: | |
151 yield name, getattr(self, name) | |
152 except AttributeError: | |
153 pass | |
154 | |
155 def iter_child_nodes(self, exclude=None, only=None): | |
156 """Iterates over all direct child nodes of the node. This iterates | |
157 over all fields and yields the values of they are nodes. If the value | |
158 of a field is a list all the nodes in that list are returned. | |
159 """ | |
160 for _, item in self.iter_fields(exclude, only): | |
161 if isinstance(item, list): | |
162 for n in item: | |
163 if isinstance(n, Node): | |
164 yield n | |
165 elif isinstance(item, Node): | |
166 yield item | |
167 | |
168 def find(self, node_type): | |
169 """Find the first node of a given type. If no such node exists the | |
170 return value is `None`. | |
171 """ | |
172 for result in self.find_all(node_type): | |
173 return result | |
174 | |
175 def find_all(self, node_type): | |
176 """Find all the nodes of a given type. If the type is a tuple, | |
177 the check is performed for any of the tuple items. | |
178 """ | |
179 for child in self.iter_child_nodes(): | |
180 if isinstance(child, node_type): | |
181 yield child | |
182 for result in child.find_all(node_type): | |
183 yield result | |
184 | |
185 def set_ctx(self, ctx): | |
186 """Reset the context of a node and all child nodes. Per default the | |
187 parser will all generate nodes that have a 'load' context as it's the | |
188 most common one. This method is used in the parser to set assignment | |
189 targets and other nodes to a store context. | |
190 """ | |
191 todo = deque([self]) | |
192 while todo: | |
193 node = todo.popleft() | |
194 if "ctx" in node.fields: | |
195 node.ctx = ctx | |
196 todo.extend(node.iter_child_nodes()) | |
197 return self | |
198 | |
199 def set_lineno(self, lineno, override=False): | |
200 """Set the line numbers of the node and children.""" | |
201 todo = deque([self]) | |
202 while todo: | |
203 node = todo.popleft() | |
204 if "lineno" in node.attributes: | |
205 if node.lineno is None or override: | |
206 node.lineno = lineno | |
207 todo.extend(node.iter_child_nodes()) | |
208 return self | |
209 | |
210 def set_environment(self, environment): | |
211 """Set the environment for all nodes.""" | |
212 todo = deque([self]) | |
213 while todo: | |
214 node = todo.popleft() | |
215 node.environment = environment | |
216 todo.extend(node.iter_child_nodes()) | |
217 return self | |
218 | |
219 def __eq__(self, other): | |
220 return type(self) is type(other) and tuple(self.iter_fields()) == tuple( | |
221 other.iter_fields() | |
222 ) | |
223 | |
224 def __ne__(self, other): | |
225 return not self.__eq__(other) | |
226 | |
227 # Restore Python 2 hashing behavior on Python 3 | |
228 __hash__ = object.__hash__ | |
229 | |
230 def __repr__(self): | |
231 return "%s(%s)" % ( | |
232 self.__class__.__name__, | |
233 ", ".join("%s=%r" % (arg, getattr(self, arg, None)) for arg in self.fields), | |
234 ) | |
235 | |
236 def dump(self): | |
237 def _dump(node): | |
238 if not isinstance(node, Node): | |
239 buf.append(repr(node)) | |
240 return | |
241 | |
242 buf.append("nodes.%s(" % node.__class__.__name__) | |
243 if not node.fields: | |
244 buf.append(")") | |
245 return | |
246 for idx, field in enumerate(node.fields): | |
247 if idx: | |
248 buf.append(", ") | |
249 value = getattr(node, field) | |
250 if isinstance(value, list): | |
251 buf.append("[") | |
252 for idx, item in enumerate(value): | |
253 if idx: | |
254 buf.append(", ") | |
255 _dump(item) | |
256 buf.append("]") | |
257 else: | |
258 _dump(value) | |
259 buf.append(")") | |
260 | |
261 buf = [] | |
262 _dump(self) | |
263 return "".join(buf) | |
264 | |
265 | |
266 class Stmt(Node): | |
267 """Base node for all statements.""" | |
268 | |
269 abstract = True | |
270 | |
271 | |
272 class Helper(Node): | |
273 """Nodes that exist in a specific context only.""" | |
274 | |
275 abstract = True | |
276 | |
277 | |
278 class Template(Node): | |
279 """Node that represents a template. This must be the outermost node that | |
280 is passed to the compiler. | |
281 """ | |
282 | |
283 fields = ("body",) | |
284 | |
285 | |
286 class Output(Stmt): | |
287 """A node that holds multiple expressions which are then printed out. | |
288 This is used both for the `print` statement and the regular template data. | |
289 """ | |
290 | |
291 fields = ("nodes",) | |
292 | |
293 | |
294 class Extends(Stmt): | |
295 """Represents an extends statement.""" | |
296 | |
297 fields = ("template",) | |
298 | |
299 | |
300 class For(Stmt): | |
301 """The for loop. `target` is the target for the iteration (usually a | |
302 :class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list | |
303 of nodes that are used as loop-body, and `else_` a list of nodes for the | |
304 `else` block. If no else node exists it has to be an empty list. | |
305 | |
306 For filtered nodes an expression can be stored as `test`, otherwise `None`. | |
307 """ | |
308 | |
309 fields = ("target", "iter", "body", "else_", "test", "recursive") | |
310 | |
311 | |
312 class If(Stmt): | |
313 """If `test` is true, `body` is rendered, else `else_`.""" | |
314 | |
315 fields = ("test", "body", "elif_", "else_") | |
316 | |
317 | |
318 class Macro(Stmt): | |
319 """A macro definition. `name` is the name of the macro, `args` a list of | |
320 arguments and `defaults` a list of defaults if there are any. `body` is | |
321 a list of nodes for the macro body. | |
322 """ | |
323 | |
324 fields = ("name", "args", "defaults", "body") | |
325 | |
326 | |
327 class CallBlock(Stmt): | |
328 """Like a macro without a name but a call instead. `call` is called with | |
329 the unnamed macro as `caller` argument this node holds. | |
330 """ | |
331 | |
332 fields = ("call", "args", "defaults", "body") | |
333 | |
334 | |
335 class FilterBlock(Stmt): | |
336 """Node for filter sections.""" | |
337 | |
338 fields = ("body", "filter") | |
339 | |
340 | |
341 class With(Stmt): | |
342 """Specific node for with statements. In older versions of Jinja the | |
343 with statement was implemented on the base of the `Scope` node instead. | |
344 | |
345 .. versionadded:: 2.9.3 | |
346 """ | |
347 | |
348 fields = ("targets", "values", "body") | |
349 | |
350 | |
351 class Block(Stmt): | |
352 """A node that represents a block.""" | |
353 | |
354 fields = ("name", "body", "scoped") | |
355 | |
356 | |
357 class Include(Stmt): | |
358 """A node that represents the include tag.""" | |
359 | |
360 fields = ("template", "with_context", "ignore_missing") | |
361 | |
362 | |
363 class Import(Stmt): | |
364 """A node that represents the import tag.""" | |
365 | |
366 fields = ("template", "target", "with_context") | |
367 | |
368 | |
369 class FromImport(Stmt): | |
370 """A node that represents the from import tag. It's important to not | |
371 pass unsafe names to the name attribute. The compiler translates the | |
372 attribute lookups directly into getattr calls and does *not* use the | |
373 subscript callback of the interface. As exported variables may not | |
374 start with double underscores (which the parser asserts) this is not a | |
375 problem for regular Jinja code, but if this node is used in an extension | |
376 extra care must be taken. | |
377 | |
378 The list of names may contain tuples if aliases are wanted. | |
379 """ | |
380 | |
381 fields = ("template", "names", "with_context") | |
382 | |
383 | |
384 class ExprStmt(Stmt): | |
385 """A statement that evaluates an expression and discards the result.""" | |
386 | |
387 fields = ("node",) | |
388 | |
389 | |
390 class Assign(Stmt): | |
391 """Assigns an expression to a target.""" | |
392 | |
393 fields = ("target", "node") | |
394 | |
395 | |
396 class AssignBlock(Stmt): | |
397 """Assigns a block to a target.""" | |
398 | |
399 fields = ("target", "filter", "body") | |
400 | |
401 | |
402 class Expr(Node): | |
403 """Baseclass for all expressions.""" | |
404 | |
405 abstract = True | |
406 | |
407 def as_const(self, eval_ctx=None): | |
408 """Return the value of the expression as constant or raise | |
409 :exc:`Impossible` if this was not possible. | |
410 | |
411 An :class:`EvalContext` can be provided, if none is given | |
412 a default context is created which requires the nodes to have | |
413 an attached environment. | |
414 | |
415 .. versionchanged:: 2.4 | |
416 the `eval_ctx` parameter was added. | |
417 """ | |
418 raise Impossible() | |
419 | |
420 def can_assign(self): | |
421 """Check if it's possible to assign something to this node.""" | |
422 return False | |
423 | |
424 | |
425 class BinExpr(Expr): | |
426 """Baseclass for all binary expressions.""" | |
427 | |
428 fields = ("left", "right") | |
429 operator = None | |
430 abstract = True | |
431 | |
432 def as_const(self, eval_ctx=None): | |
433 eval_ctx = get_eval_context(self, eval_ctx) | |
434 # intercepted operators cannot be folded at compile time | |
435 if ( | |
436 self.environment.sandboxed | |
437 and self.operator in self.environment.intercepted_binops | |
438 ): | |
439 raise Impossible() | |
440 f = _binop_to_func[self.operator] | |
441 try: | |
442 return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) | |
443 except Exception: | |
444 raise Impossible() | |
445 | |
446 | |
447 class UnaryExpr(Expr): | |
448 """Baseclass for all unary expressions.""" | |
449 | |
450 fields = ("node",) | |
451 operator = None | |
452 abstract = True | |
453 | |
454 def as_const(self, eval_ctx=None): | |
455 eval_ctx = get_eval_context(self, eval_ctx) | |
456 # intercepted operators cannot be folded at compile time | |
457 if ( | |
458 self.environment.sandboxed | |
459 and self.operator in self.environment.intercepted_unops | |
460 ): | |
461 raise Impossible() | |
462 f = _uaop_to_func[self.operator] | |
463 try: | |
464 return f(self.node.as_const(eval_ctx)) | |
465 except Exception: | |
466 raise Impossible() | |
467 | |
468 | |
469 class Name(Expr): | |
470 """Looks up a name or stores a value in a name. | |
471 The `ctx` of the node can be one of the following values: | |
472 | |
473 - `store`: store a value in the name | |
474 - `load`: load that name | |
475 - `param`: like `store` but if the name was defined as function parameter. | |
476 """ | |
477 | |
478 fields = ("name", "ctx") | |
479 | |
480 def can_assign(self): | |
481 return self.name not in ("true", "false", "none", "True", "False", "None") | |
482 | |
483 | |
484 class NSRef(Expr): | |
485 """Reference to a namespace value assignment""" | |
486 | |
487 fields = ("name", "attr") | |
488 | |
489 def can_assign(self): | |
490 # We don't need any special checks here; NSRef assignments have a | |
491 # runtime check to ensure the target is a namespace object which will | |
492 # have been checked already as it is created using a normal assignment | |
493 # which goes through a `Name` node. | |
494 return True | |
495 | |
496 | |
497 class Literal(Expr): | |
498 """Baseclass for literals.""" | |
499 | |
500 abstract = True | |
501 | |
502 | |
503 class Const(Literal): | |
504 """All constant values. The parser will return this node for simple | |
505 constants such as ``42`` or ``"foo"`` but it can be used to store more | |
506 complex values such as lists too. Only constants with a safe | |
507 representation (objects where ``eval(repr(x)) == x`` is true). | |
508 """ | |
509 | |
510 fields = ("value",) | |
511 | |
512 def as_const(self, eval_ctx=None): | |
513 rv = self.value | |
514 if ( | |
515 PY2 | |
516 and type(rv) is text_type | |
517 and self.environment.policies["compiler.ascii_str"] | |
518 ): | |
519 try: | |
520 rv = rv.encode("ascii") | |
521 except UnicodeError: | |
522 pass | |
523 return rv | |
524 | |
525 @classmethod | |
526 def from_untrusted(cls, value, lineno=None, environment=None): | |
527 """Return a const object if the value is representable as | |
528 constant value in the generated code, otherwise it will raise | |
529 an `Impossible` exception. | |
530 """ | |
531 from .compiler import has_safe_repr | |
532 | |
533 if not has_safe_repr(value): | |
534 raise Impossible() | |
535 return cls(value, lineno=lineno, environment=environment) | |
536 | |
537 | |
538 class TemplateData(Literal): | |
539 """A constant template string.""" | |
540 | |
541 fields = ("data",) | |
542 | |
543 def as_const(self, eval_ctx=None): | |
544 eval_ctx = get_eval_context(self, eval_ctx) | |
545 if eval_ctx.volatile: | |
546 raise Impossible() | |
547 if eval_ctx.autoescape: | |
548 return Markup(self.data) | |
549 return self.data | |
550 | |
551 | |
552 class Tuple(Literal): | |
553 """For loop unpacking and some other things like multiple arguments | |
554 for subscripts. Like for :class:`Name` `ctx` specifies if the tuple | |
555 is used for loading the names or storing. | |
556 """ | |
557 | |
558 fields = ("items", "ctx") | |
559 | |
560 def as_const(self, eval_ctx=None): | |
561 eval_ctx = get_eval_context(self, eval_ctx) | |
562 return tuple(x.as_const(eval_ctx) for x in self.items) | |
563 | |
564 def can_assign(self): | |
565 for item in self.items: | |
566 if not item.can_assign(): | |
567 return False | |
568 return True | |
569 | |
570 | |
571 class List(Literal): | |
572 """Any list literal such as ``[1, 2, 3]``""" | |
573 | |
574 fields = ("items",) | |
575 | |
576 def as_const(self, eval_ctx=None): | |
577 eval_ctx = get_eval_context(self, eval_ctx) | |
578 return [x.as_const(eval_ctx) for x in self.items] | |
579 | |
580 | |
581 class Dict(Literal): | |
582 """Any dict literal such as ``{1: 2, 3: 4}``. The items must be a list of | |
583 :class:`Pair` nodes. | |
584 """ | |
585 | |
586 fields = ("items",) | |
587 | |
588 def as_const(self, eval_ctx=None): | |
589 eval_ctx = get_eval_context(self, eval_ctx) | |
590 return dict(x.as_const(eval_ctx) for x in self.items) | |
591 | |
592 | |
593 class Pair(Helper): | |
594 """A key, value pair for dicts.""" | |
595 | |
596 fields = ("key", "value") | |
597 | |
598 def as_const(self, eval_ctx=None): | |
599 eval_ctx = get_eval_context(self, eval_ctx) | |
600 return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx) | |
601 | |
602 | |
603 class Keyword(Helper): | |
604 """A key, value pair for keyword arguments where key is a string.""" | |
605 | |
606 fields = ("key", "value") | |
607 | |
608 def as_const(self, eval_ctx=None): | |
609 eval_ctx = get_eval_context(self, eval_ctx) | |
610 return self.key, self.value.as_const(eval_ctx) | |
611 | |
612 | |
613 class CondExpr(Expr): | |
614 """A conditional expression (inline if expression). (``{{ | |
615 foo if bar else baz }}``) | |
616 """ | |
617 | |
618 fields = ("test", "expr1", "expr2") | |
619 | |
620 def as_const(self, eval_ctx=None): | |
621 eval_ctx = get_eval_context(self, eval_ctx) | |
622 if self.test.as_const(eval_ctx): | |
623 return self.expr1.as_const(eval_ctx) | |
624 | |
625 # if we evaluate to an undefined object, we better do that at runtime | |
626 if self.expr2 is None: | |
627 raise Impossible() | |
628 | |
629 return self.expr2.as_const(eval_ctx) | |
630 | |
631 | |
632 def args_as_const(node, eval_ctx): | |
633 args = [x.as_const(eval_ctx) for x in node.args] | |
634 kwargs = dict(x.as_const(eval_ctx) for x in node.kwargs) | |
635 | |
636 if node.dyn_args is not None: | |
637 try: | |
638 args.extend(node.dyn_args.as_const(eval_ctx)) | |
639 except Exception: | |
640 raise Impossible() | |
641 | |
642 if node.dyn_kwargs is not None: | |
643 try: | |
644 kwargs.update(node.dyn_kwargs.as_const(eval_ctx)) | |
645 except Exception: | |
646 raise Impossible() | |
647 | |
648 return args, kwargs | |
649 | |
650 | |
651 class Filter(Expr): | |
652 """This node applies a filter on an expression. `name` is the name of | |
653 the filter, the rest of the fields are the same as for :class:`Call`. | |
654 | |
655 If the `node` of a filter is `None` the contents of the last buffer are | |
656 filtered. Buffers are created by macros and filter blocks. | |
657 """ | |
658 | |
659 fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") | |
660 | |
661 def as_const(self, eval_ctx=None): | |
662 eval_ctx = get_eval_context(self, eval_ctx) | |
663 | |
664 if eval_ctx.volatile or self.node is None: | |
665 raise Impossible() | |
666 | |
667 # we have to be careful here because we call filter_ below. | |
668 # if this variable would be called filter, 2to3 would wrap the | |
669 # call in a list because it is assuming we are talking about the | |
670 # builtin filter function here which no longer returns a list in | |
671 # python 3. because of that, do not rename filter_ to filter! | |
672 filter_ = self.environment.filters.get(self.name) | |
673 | |
674 if filter_ is None or getattr(filter_, "contextfilter", False) is True: | |
675 raise Impossible() | |
676 | |
677 # We cannot constant handle async filters, so we need to make sure | |
678 # to not go down this path. | |
679 if eval_ctx.environment.is_async and getattr( | |
680 filter_, "asyncfiltervariant", False | |
681 ): | |
682 raise Impossible() | |
683 | |
684 args, kwargs = args_as_const(self, eval_ctx) | |
685 args.insert(0, self.node.as_const(eval_ctx)) | |
686 | |
687 if getattr(filter_, "evalcontextfilter", False) is True: | |
688 args.insert(0, eval_ctx) | |
689 elif getattr(filter_, "environmentfilter", False) is True: | |
690 args.insert(0, self.environment) | |
691 | |
692 try: | |
693 return filter_(*args, **kwargs) | |
694 except Exception: | |
695 raise Impossible() | |
696 | |
697 | |
698 class Test(Expr): | |
699 """Applies a test on an expression. `name` is the name of the test, the | |
700 rest of the fields are the same as for :class:`Call`. | |
701 """ | |
702 | |
703 fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") | |
704 | |
705 def as_const(self, eval_ctx=None): | |
706 test = self.environment.tests.get(self.name) | |
707 | |
708 if test is None: | |
709 raise Impossible() | |
710 | |
711 eval_ctx = get_eval_context(self, eval_ctx) | |
712 args, kwargs = args_as_const(self, eval_ctx) | |
713 args.insert(0, self.node.as_const(eval_ctx)) | |
714 | |
715 try: | |
716 return test(*args, **kwargs) | |
717 except Exception: | |
718 raise Impossible() | |
719 | |
720 | |
721 class Call(Expr): | |
722 """Calls an expression. `args` is a list of arguments, `kwargs` a list | |
723 of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args` | |
724 and `dyn_kwargs` has to be either `None` or a node that is used as | |
725 node for dynamic positional (``*args``) or keyword (``**kwargs``) | |
726 arguments. | |
727 """ | |
728 | |
729 fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs") | |
730 | |
731 | |
732 class Getitem(Expr): | |
733 """Get an attribute or item from an expression and prefer the item.""" | |
734 | |
735 fields = ("node", "arg", "ctx") | |
736 | |
737 def as_const(self, eval_ctx=None): | |
738 eval_ctx = get_eval_context(self, eval_ctx) | |
739 if self.ctx != "load": | |
740 raise Impossible() | |
741 try: | |
742 return self.environment.getitem( | |
743 self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx) | |
744 ) | |
745 except Exception: | |
746 raise Impossible() | |
747 | |
748 def can_assign(self): | |
749 return False | |
750 | |
751 | |
752 class Getattr(Expr): | |
753 """Get an attribute or item from an expression that is a ascii-only | |
754 bytestring and prefer the attribute. | |
755 """ | |
756 | |
757 fields = ("node", "attr", "ctx") | |
758 | |
759 def as_const(self, eval_ctx=None): | |
760 if self.ctx != "load": | |
761 raise Impossible() | |
762 try: | |
763 eval_ctx = get_eval_context(self, eval_ctx) | |
764 return self.environment.getattr(self.node.as_const(eval_ctx), self.attr) | |
765 except Exception: | |
766 raise Impossible() | |
767 | |
768 def can_assign(self): | |
769 return False | |
770 | |
771 | |
772 class Slice(Expr): | |
773 """Represents a slice object. This must only be used as argument for | |
774 :class:`Subscript`. | |
775 """ | |
776 | |
777 fields = ("start", "stop", "step") | |
778 | |
779 def as_const(self, eval_ctx=None): | |
780 eval_ctx = get_eval_context(self, eval_ctx) | |
781 | |
782 def const(obj): | |
783 if obj is None: | |
784 return None | |
785 return obj.as_const(eval_ctx) | |
786 | |
787 return slice(const(self.start), const(self.stop), const(self.step)) | |
788 | |
789 | |
790 class Concat(Expr): | |
791 """Concatenates the list of expressions provided after converting them to | |
792 unicode. | |
793 """ | |
794 | |
795 fields = ("nodes",) | |
796 | |
797 def as_const(self, eval_ctx=None): | |
798 eval_ctx = get_eval_context(self, eval_ctx) | |
799 return "".join(text_type(x.as_const(eval_ctx)) for x in self.nodes) | |
800 | |
801 | |
802 class Compare(Expr): | |
803 """Compares an expression with some other expressions. `ops` must be a | |
804 list of :class:`Operand`\\s. | |
805 """ | |
806 | |
807 fields = ("expr", "ops") | |
808 | |
809 def as_const(self, eval_ctx=None): | |
810 eval_ctx = get_eval_context(self, eval_ctx) | |
811 result = value = self.expr.as_const(eval_ctx) | |
812 | |
813 try: | |
814 for op in self.ops: | |
815 new_value = op.expr.as_const(eval_ctx) | |
816 result = _cmpop_to_func[op.op](value, new_value) | |
817 | |
818 if not result: | |
819 return False | |
820 | |
821 value = new_value | |
822 except Exception: | |
823 raise Impossible() | |
824 | |
825 return result | |
826 | |
827 | |
828 class Operand(Helper): | |
829 """Holds an operator and an expression.""" | |
830 | |
831 fields = ("op", "expr") | |
832 | |
833 | |
834 if __debug__: | |
835 Operand.__doc__ += "\nThe following operators are available: " + ", ".join( | |
836 sorted( | |
837 "``%s``" % x | |
838 for x in set(_binop_to_func) | set(_uaop_to_func) | set(_cmpop_to_func) | |
839 ) | |
840 ) | |
841 | |
842 | |
843 class Mul(BinExpr): | |
844 """Multiplies the left with the right node.""" | |
845 | |
846 operator = "*" | |
847 | |
848 | |
849 class Div(BinExpr): | |
850 """Divides the left by the right node.""" | |
851 | |
852 operator = "/" | |
853 | |
854 | |
855 class FloorDiv(BinExpr): | |
856 """Divides the left by the right node and truncates conver the | |
857 result into an integer by truncating. | |
858 """ | |
859 | |
860 operator = "//" | |
861 | |
862 | |
863 class Add(BinExpr): | |
864 """Add the left to the right node.""" | |
865 | |
866 operator = "+" | |
867 | |
868 | |
869 class Sub(BinExpr): | |
870 """Subtract the right from the left node.""" | |
871 | |
872 operator = "-" | |
873 | |
874 | |
875 class Mod(BinExpr): | |
876 """Left modulo right.""" | |
877 | |
878 operator = "%" | |
879 | |
880 | |
881 class Pow(BinExpr): | |
882 """Left to the power of right.""" | |
883 | |
884 operator = "**" | |
885 | |
886 | |
887 class And(BinExpr): | |
888 """Short circuited AND.""" | |
889 | |
890 operator = "and" | |
891 | |
892 def as_const(self, eval_ctx=None): | |
893 eval_ctx = get_eval_context(self, eval_ctx) | |
894 return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx) | |
895 | |
896 | |
897 class Or(BinExpr): | |
898 """Short circuited OR.""" | |
899 | |
900 operator = "or" | |
901 | |
902 def as_const(self, eval_ctx=None): | |
903 eval_ctx = get_eval_context(self, eval_ctx) | |
904 return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx) | |
905 | |
906 | |
907 class Not(UnaryExpr): | |
908 """Negate the expression.""" | |
909 | |
910 operator = "not" | |
911 | |
912 | |
913 class Neg(UnaryExpr): | |
914 """Make the expression negative.""" | |
915 | |
916 operator = "-" | |
917 | |
918 | |
919 class Pos(UnaryExpr): | |
920 """Make the expression positive (noop for most expressions)""" | |
921 | |
922 operator = "+" | |
923 | |
924 | |
925 # Helpers for extensions | |
926 | |
927 | |
928 class EnvironmentAttribute(Expr): | |
929 """Loads an attribute from the environment object. This is useful for | |
930 extensions that want to call a callback stored on the environment. | |
931 """ | |
932 | |
933 fields = ("name",) | |
934 | |
935 | |
936 class ExtensionAttribute(Expr): | |
937 """Returns the attribute of an extension bound to the environment. | |
938 The identifier is the identifier of the :class:`Extension`. | |
939 | |
940 This node is usually constructed by calling the | |
941 :meth:`~jinja2.ext.Extension.attr` method on an extension. | |
942 """ | |
943 | |
944 fields = ("identifier", "name") | |
945 | |
946 | |
947 class ImportedName(Expr): | |
948 """If created with an import name the import name is returned on node | |
949 access. For example ``ImportedName('cgi.escape')`` returns the `escape` | |
950 function from the cgi module on evaluation. Imports are optimized by the | |
951 compiler so there is no need to assign them to local variables. | |
952 """ | |
953 | |
954 fields = ("importname",) | |
955 | |
956 | |
957 class InternalName(Expr): | |
958 """An internal name in the compiler. You cannot create these nodes | |
959 yourself but the parser provides a | |
960 :meth:`~jinja2.parser.Parser.free_identifier` method that creates | |
961 a new identifier for you. This identifier is not available from the | |
962 template and is not threated specially by the compiler. | |
963 """ | |
964 | |
965 fields = ("name",) | |
966 | |
967 def __init__(self): | |
968 raise TypeError( | |
969 "Can't create internal names. Use the " | |
970 "`free_identifier` method on a parser." | |
971 ) | |
972 | |
973 | |
974 class MarkSafe(Expr): | |
975 """Mark the wrapped expression as safe (wrap it as `Markup`).""" | |
976 | |
977 fields = ("expr",) | |
978 | |
979 def as_const(self, eval_ctx=None): | |
980 eval_ctx = get_eval_context(self, eval_ctx) | |
981 return Markup(self.expr.as_const(eval_ctx)) | |
982 | |
983 | |
984 class MarkSafeIfAutoescape(Expr): | |
985 """Mark the wrapped expression as safe (wrap it as `Markup`) but | |
986 only if autoescaping is active. | |
987 | |
988 .. versionadded:: 2.5 | |
989 """ | |
990 | |
991 fields = ("expr",) | |
992 | |
993 def as_const(self, eval_ctx=None): | |
994 eval_ctx = get_eval_context(self, eval_ctx) | |
995 if eval_ctx.volatile: | |
996 raise Impossible() | |
997 expr = self.expr.as_const(eval_ctx) | |
998 if eval_ctx.autoescape: | |
999 return Markup(expr) | |
1000 return expr | |
1001 | |
1002 | |
1003 class ContextReference(Expr): | |
1004 """Returns the current template context. It can be used like a | |
1005 :class:`Name` node, with a ``'load'`` ctx and will return the | |
1006 current :class:`~jinja2.runtime.Context` object. | |
1007 | |
1008 Here an example that assigns the current template name to a | |
1009 variable named `foo`:: | |
1010 | |
1011 Assign(Name('foo', ctx='store'), | |
1012 Getattr(ContextReference(), 'name')) | |
1013 | |
1014 This is basically equivalent to using the | |
1015 :func:`~jinja2.contextfunction` decorator when using the | |
1016 high-level API, which causes a reference to the context to be passed | |
1017 as the first argument to a function. | |
1018 """ | |
1019 | |
1020 | |
1021 class DerivedContextReference(Expr): | |
1022 """Return the current template context including locals. Behaves | |
1023 exactly like :class:`ContextReference`, but includes local | |
1024 variables, such as from a ``for`` loop. | |
1025 | |
1026 .. versionadded:: 2.11 | |
1027 """ | |
1028 | |
1029 | |
1030 class Continue(Stmt): | |
1031 """Continue a loop.""" | |
1032 | |
1033 | |
1034 class Break(Stmt): | |
1035 """Break a loop.""" | |
1036 | |
1037 | |
1038 class Scope(Stmt): | |
1039 """An artificial scope.""" | |
1040 | |
1041 fields = ("body",) | |
1042 | |
1043 | |
1044 class OverlayScope(Stmt): | |
1045 """An overlay scope for extensions. This is a largely unoptimized scope | |
1046 that however can be used to introduce completely arbitrary variables into | |
1047 a sub scope from a dictionary or dictionary like object. The `context` | |
1048 field has to evaluate to a dictionary object. | |
1049 | |
1050 Example usage:: | |
1051 | |
1052 OverlayScope(context=self.call_method('get_context'), | |
1053 body=[...]) | |
1054 | |
1055 .. versionadded:: 2.10 | |
1056 """ | |
1057 | |
1058 fields = ("context", "body") | |
1059 | |
1060 | |
1061 class EvalContextModifier(Stmt): | |
1062 """Modifies the eval context. For each option that should be modified, | |
1063 a :class:`Keyword` has to be added to the :attr:`options` list. | |
1064 | |
1065 Example to change the `autoescape` setting:: | |
1066 | |
1067 EvalContextModifier(options=[Keyword('autoescape', Const(True))]) | |
1068 """ | |
1069 | |
1070 fields = ("options",) | |
1071 | |
1072 | |
1073 class ScopedEvalContextModifier(EvalContextModifier): | |
1074 """Modifies the eval context and reverts it later. Works exactly like | |
1075 :class:`EvalContextModifier` but will only modify the | |
1076 :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`. | |
1077 """ | |
1078 | |
1079 fields = ("body",) | |
1080 | |
1081 | |
1082 # make sure nobody creates custom nodes | |
1083 def _failing_new(*args, **kwargs): | |
1084 raise TypeError("can't create custom node types") | |
1085 | |
1086 | |
1087 NodeType.__new__ = staticmethod(_failing_new) | |
1088 del _failing_new |