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