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