|  | """AST nodes generated by the parser for the compiler. Also provides | 
					
						
						|  | some node tree helper functions used by the parser and compiler in order | 
					
						
						|  | to normalize nodes. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | import inspect | 
					
						
						|  | import operator | 
					
						
						|  | import typing as t | 
					
						
						|  | from collections import deque | 
					
						
						|  |  | 
					
						
						|  | from markupsafe import Markup | 
					
						
						|  |  | 
					
						
						|  | from .utils import _PassArg | 
					
						
						|  |  | 
					
						
						|  | if t.TYPE_CHECKING: | 
					
						
						|  | import typing_extensions as te | 
					
						
						|  |  | 
					
						
						|  | from .environment import Environment | 
					
						
						|  |  | 
					
						
						|  | _NodeBound = t.TypeVar("_NodeBound", bound="Node") | 
					
						
						|  |  | 
					
						
						|  | _binop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { | 
					
						
						|  | "*": operator.mul, | 
					
						
						|  | "/": operator.truediv, | 
					
						
						|  | "//": operator.floordiv, | 
					
						
						|  | "**": operator.pow, | 
					
						
						|  | "%": operator.mod, | 
					
						
						|  | "+": operator.add, | 
					
						
						|  | "-": operator.sub, | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | _uaop_to_func: t.Dict[str, t.Callable[[t.Any], t.Any]] = { | 
					
						
						|  | "not": operator.not_, | 
					
						
						|  | "+": operator.pos, | 
					
						
						|  | "-": operator.neg, | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | _cmpop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { | 
					
						
						|  | "eq": operator.eq, | 
					
						
						|  | "ne": operator.ne, | 
					
						
						|  | "gt": operator.gt, | 
					
						
						|  | "gteq": operator.ge, | 
					
						
						|  | "lt": operator.lt, | 
					
						
						|  | "lteq": operator.le, | 
					
						
						|  | "in": lambda a, b: a in b, | 
					
						
						|  | "notin": lambda a, b: a not in b, | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Impossible(Exception): | 
					
						
						|  | """Raised if the node could not perform a requested action.""" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class NodeType(type): | 
					
						
						|  | """A metaclass for nodes that handles the field and attribute | 
					
						
						|  | inheritance.  fields and attributes from the parent class are | 
					
						
						|  | automatically forwarded to the child.""" | 
					
						
						|  |  | 
					
						
						|  | def __new__(mcs, name, bases, d): | 
					
						
						|  | for attr in "fields", "attributes": | 
					
						
						|  | storage: t.List[t.Tuple[str, ...]] = [] | 
					
						
						|  | storage.extend(getattr(bases[0] if bases else object, attr, ())) | 
					
						
						|  | storage.extend(d.get(attr, ())) | 
					
						
						|  | assert len(bases) <= 1, "multiple inheritance not allowed" | 
					
						
						|  | assert len(storage) == len(set(storage)), "layout conflict" | 
					
						
						|  | d[attr] = tuple(storage) | 
					
						
						|  | d.setdefault("abstract", False) | 
					
						
						|  | return type.__new__(mcs, name, bases, d) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class EvalContext: | 
					
						
						|  | """Holds evaluation time information.  Custom attributes can be attached | 
					
						
						|  | to it in extensions. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | def __init__( | 
					
						
						|  | self, environment: "Environment", template_name: t.Optional[str] = None | 
					
						
						|  | ) -> None: | 
					
						
						|  | self.environment = environment | 
					
						
						|  | if callable(environment.autoescape): | 
					
						
						|  | self.autoescape = environment.autoescape(template_name) | 
					
						
						|  | else: | 
					
						
						|  | self.autoescape = environment.autoescape | 
					
						
						|  | self.volatile = False | 
					
						
						|  |  | 
					
						
						|  | def save(self) -> t.Mapping[str, t.Any]: | 
					
						
						|  | return self.__dict__.copy() | 
					
						
						|  |  | 
					
						
						|  | def revert(self, old: t.Mapping[str, t.Any]) -> None: | 
					
						
						|  | self.__dict__.clear() | 
					
						
						|  | self.__dict__.update(old) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | def get_eval_context(node: "Node", ctx: t.Optional[EvalContext]) -> EvalContext: | 
					
						
						|  | if ctx is None: | 
					
						
						|  | if node.environment is None: | 
					
						
						|  | raise RuntimeError( | 
					
						
						|  | "if no eval context is passed, the node must have an" | 
					
						
						|  | " attached environment." | 
					
						
						|  | ) | 
					
						
						|  | return EvalContext(node.environment) | 
					
						
						|  | return ctx | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Node(metaclass=NodeType): | 
					
						
						|  | """Baseclass for all Jinja nodes.  There are a number of nodes available | 
					
						
						|  | of different types.  There are four major types: | 
					
						
						|  |  | 
					
						
						|  | -   :class:`Stmt`: statements | 
					
						
						|  | -   :class:`Expr`: expressions | 
					
						
						|  | -   :class:`Helper`: helper nodes | 
					
						
						|  | -   :class:`Template`: the outermost wrapper node | 
					
						
						|  |  | 
					
						
						|  | All nodes have fields and attributes.  Fields may be other nodes, lists, | 
					
						
						|  | or arbitrary values.  Fields are passed to the constructor as regular | 
					
						
						|  | positional arguments, attributes as keyword arguments.  Each node has | 
					
						
						|  | two attributes: `lineno` (the line number of the node) and `environment`. | 
					
						
						|  | The `environment` attribute is set at the end of the parsing process for | 
					
						
						|  | all nodes automatically. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields: t.Tuple[str, ...] = () | 
					
						
						|  | attributes: t.Tuple[str, ...] = ("lineno", "environment") | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  | lineno: int | 
					
						
						|  | environment: t.Optional["Environment"] | 
					
						
						|  |  | 
					
						
						|  | def __init__(self, *fields: t.Any, **attributes: t.Any) -> None: | 
					
						
						|  | if self.abstract: | 
					
						
						|  | raise TypeError("abstract nodes are not instantiable") | 
					
						
						|  | if fields: | 
					
						
						|  | if len(fields) != len(self.fields): | 
					
						
						|  | if not self.fields: | 
					
						
						|  | raise TypeError(f"{type(self).__name__!r} takes 0 arguments") | 
					
						
						|  | raise TypeError( | 
					
						
						|  | f"{type(self).__name__!r} takes 0 or {len(self.fields)}" | 
					
						
						|  | f" argument{'s' if len(self.fields) != 1 else ''}" | 
					
						
						|  | ) | 
					
						
						|  | for name, arg in zip(self.fields, fields): | 
					
						
						|  | setattr(self, name, arg) | 
					
						
						|  | for attr in self.attributes: | 
					
						
						|  | setattr(self, attr, attributes.pop(attr, None)) | 
					
						
						|  | if attributes: | 
					
						
						|  | raise TypeError(f"unknown attribute {next(iter(attributes))!r}") | 
					
						
						|  |  | 
					
						
						|  | def iter_fields( | 
					
						
						|  | self, | 
					
						
						|  | exclude: t.Optional[t.Container[str]] = None, | 
					
						
						|  | only: t.Optional[t.Container[str]] = None, | 
					
						
						|  | ) -> t.Iterator[t.Tuple[str, t.Any]]: | 
					
						
						|  | """This method iterates over all fields that are defined and yields | 
					
						
						|  | ``(key, value)`` tuples.  Per default all fields are returned, but | 
					
						
						|  | it's possible to limit that to some fields by providing the `only` | 
					
						
						|  | parameter or to exclude some using the `exclude` parameter.  Both | 
					
						
						|  | should be sets or tuples of field names. | 
					
						
						|  | """ | 
					
						
						|  | for name in self.fields: | 
					
						
						|  | if ( | 
					
						
						|  | (exclude is None and only is None) | 
					
						
						|  | or (exclude is not None and name not in exclude) | 
					
						
						|  | or (only is not None and name in only) | 
					
						
						|  | ): | 
					
						
						|  | try: | 
					
						
						|  | yield name, getattr(self, name) | 
					
						
						|  | except AttributeError: | 
					
						
						|  | pass | 
					
						
						|  |  | 
					
						
						|  | def iter_child_nodes( | 
					
						
						|  | self, | 
					
						
						|  | exclude: t.Optional[t.Container[str]] = None, | 
					
						
						|  | only: t.Optional[t.Container[str]] = None, | 
					
						
						|  | ) -> t.Iterator["Node"]: | 
					
						
						|  | """Iterates over all direct child nodes of the node.  This iterates | 
					
						
						|  | over all fields and yields the values of they are nodes.  If the value | 
					
						
						|  | of a field is a list all the nodes in that list are returned. | 
					
						
						|  | """ | 
					
						
						|  | for _, item in self.iter_fields(exclude, only): | 
					
						
						|  | if isinstance(item, list): | 
					
						
						|  | for n in item: | 
					
						
						|  | if isinstance(n, Node): | 
					
						
						|  | yield n | 
					
						
						|  | elif isinstance(item, Node): | 
					
						
						|  | yield item | 
					
						
						|  |  | 
					
						
						|  | def find(self, node_type: t.Type[_NodeBound]) -> t.Optional[_NodeBound]: | 
					
						
						|  | """Find the first node of a given type.  If no such node exists the | 
					
						
						|  | return value is `None`. | 
					
						
						|  | """ | 
					
						
						|  | for result in self.find_all(node_type): | 
					
						
						|  | return result | 
					
						
						|  |  | 
					
						
						|  | return None | 
					
						
						|  |  | 
					
						
						|  | def find_all( | 
					
						
						|  | self, node_type: t.Union[t.Type[_NodeBound], t.Tuple[t.Type[_NodeBound], ...]] | 
					
						
						|  | ) -> t.Iterator[_NodeBound]: | 
					
						
						|  | """Find all the nodes of a given type.  If the type is a tuple, | 
					
						
						|  | the check is performed for any of the tuple items. | 
					
						
						|  | """ | 
					
						
						|  | for child in self.iter_child_nodes(): | 
					
						
						|  | if isinstance(child, node_type): | 
					
						
						|  | yield child | 
					
						
						|  | yield from child.find_all(node_type) | 
					
						
						|  |  | 
					
						
						|  | def set_ctx(self, ctx: str) -> "Node": | 
					
						
						|  | """Reset the context of a node and all child nodes.  Per default the | 
					
						
						|  | parser will all generate nodes that have a 'load' context as it's the | 
					
						
						|  | most common one.  This method is used in the parser to set assignment | 
					
						
						|  | targets and other nodes to a store context. | 
					
						
						|  | """ | 
					
						
						|  | todo = deque([self]) | 
					
						
						|  | while todo: | 
					
						
						|  | node = todo.popleft() | 
					
						
						|  | if "ctx" in node.fields: | 
					
						
						|  | node.ctx = ctx | 
					
						
						|  | todo.extend(node.iter_child_nodes()) | 
					
						
						|  | return self | 
					
						
						|  |  | 
					
						
						|  | def set_lineno(self, lineno: int, override: bool = False) -> "Node": | 
					
						
						|  | """Set the line numbers of the node and children.""" | 
					
						
						|  | todo = deque([self]) | 
					
						
						|  | while todo: | 
					
						
						|  | node = todo.popleft() | 
					
						
						|  | if "lineno" in node.attributes: | 
					
						
						|  | if node.lineno is None or override: | 
					
						
						|  | node.lineno = lineno | 
					
						
						|  | todo.extend(node.iter_child_nodes()) | 
					
						
						|  | return self | 
					
						
						|  |  | 
					
						
						|  | def set_environment(self, environment: "Environment") -> "Node": | 
					
						
						|  | """Set the environment for all nodes.""" | 
					
						
						|  | todo = deque([self]) | 
					
						
						|  | while todo: | 
					
						
						|  | node = todo.popleft() | 
					
						
						|  | node.environment = environment | 
					
						
						|  | todo.extend(node.iter_child_nodes()) | 
					
						
						|  | return self | 
					
						
						|  |  | 
					
						
						|  | def __eq__(self, other: t.Any) -> bool: | 
					
						
						|  | if type(self) is not type(other): | 
					
						
						|  | return NotImplemented | 
					
						
						|  |  | 
					
						
						|  | return tuple(self.iter_fields()) == tuple(other.iter_fields()) | 
					
						
						|  |  | 
					
						
						|  | __hash__ = object.__hash__ | 
					
						
						|  |  | 
					
						
						|  | def __repr__(self) -> str: | 
					
						
						|  | args_str = ", ".join(f"{a}={getattr(self, a, None)!r}" for a in self.fields) | 
					
						
						|  | return f"{type(self).__name__}({args_str})" | 
					
						
						|  |  | 
					
						
						|  | def dump(self) -> str: | 
					
						
						|  | def _dump(node: t.Union[Node, t.Any]) -> None: | 
					
						
						|  | if not isinstance(node, Node): | 
					
						
						|  | buf.append(repr(node)) | 
					
						
						|  | return | 
					
						
						|  |  | 
					
						
						|  | buf.append(f"nodes.{type(node).__name__}(") | 
					
						
						|  | if not node.fields: | 
					
						
						|  | buf.append(")") | 
					
						
						|  | return | 
					
						
						|  | for idx, field in enumerate(node.fields): | 
					
						
						|  | if idx: | 
					
						
						|  | buf.append(", ") | 
					
						
						|  | value = getattr(node, field) | 
					
						
						|  | if isinstance(value, list): | 
					
						
						|  | buf.append("[") | 
					
						
						|  | for idx, item in enumerate(value): | 
					
						
						|  | if idx: | 
					
						
						|  | buf.append(", ") | 
					
						
						|  | _dump(item) | 
					
						
						|  | buf.append("]") | 
					
						
						|  | else: | 
					
						
						|  | _dump(value) | 
					
						
						|  | buf.append(")") | 
					
						
						|  |  | 
					
						
						|  | buf: t.List[str] = [] | 
					
						
						|  | _dump(self) | 
					
						
						|  | return "".join(buf) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Stmt(Node): | 
					
						
						|  | """Base node for all statements.""" | 
					
						
						|  |  | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Helper(Node): | 
					
						
						|  | """Nodes that exist in a specific context only.""" | 
					
						
						|  |  | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Template(Node): | 
					
						
						|  | """Node that represents a template.  This must be the outermost node that | 
					
						
						|  | is passed to the compiler. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("body",) | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Output(Stmt): | 
					
						
						|  | """A node that holds multiple expressions which are then printed out. | 
					
						
						|  | This is used both for the `print` statement and the regular template data. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("nodes",) | 
					
						
						|  | nodes: t.List["Expr"] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Extends(Stmt): | 
					
						
						|  | """Represents an extends statement.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("template",) | 
					
						
						|  | template: "Expr" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class For(Stmt): | 
					
						
						|  | """The for loop.  `target` is the target for the iteration (usually a | 
					
						
						|  | :class:`Name` or :class:`Tuple`), `iter` the iterable.  `body` is a list | 
					
						
						|  | of nodes that are used as loop-body, and `else_` a list of nodes for the | 
					
						
						|  | `else` block.  If no else node exists it has to be an empty list. | 
					
						
						|  |  | 
					
						
						|  | For filtered nodes an expression can be stored as `test`, otherwise `None`. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("target", "iter", "body", "else_", "test", "recursive") | 
					
						
						|  | target: Node | 
					
						
						|  | iter: Node | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  | else_: t.List[Node] | 
					
						
						|  | test: t.Optional[Node] | 
					
						
						|  | recursive: bool | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class If(Stmt): | 
					
						
						|  | """If `test` is true, `body` is rendered, else `else_`.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("test", "body", "elif_", "else_") | 
					
						
						|  | test: Node | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  | elif_: t.List["If"] | 
					
						
						|  | else_: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Macro(Stmt): | 
					
						
						|  | """A macro definition.  `name` is the name of the macro, `args` a list of | 
					
						
						|  | arguments and `defaults` a list of defaults if there are any.  `body` is | 
					
						
						|  | a list of nodes for the macro body. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("name", "args", "defaults", "body") | 
					
						
						|  | name: str | 
					
						
						|  | args: t.List["Name"] | 
					
						
						|  | defaults: t.List["Expr"] | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class CallBlock(Stmt): | 
					
						
						|  | """Like a macro without a name but a call instead.  `call` is called with | 
					
						
						|  | the unnamed macro as `caller` argument this node holds. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("call", "args", "defaults", "body") | 
					
						
						|  | call: "Call" | 
					
						
						|  | args: t.List["Name"] | 
					
						
						|  | defaults: t.List["Expr"] | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class FilterBlock(Stmt): | 
					
						
						|  | """Node for filter sections.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("body", "filter") | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  | filter: "Filter" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class With(Stmt): | 
					
						
						|  | """Specific node for with statements.  In older versions of Jinja the | 
					
						
						|  | with statement was implemented on the base of the `Scope` node instead. | 
					
						
						|  |  | 
					
						
						|  | .. versionadded:: 2.9.3 | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("targets", "values", "body") | 
					
						
						|  | targets: t.List["Expr"] | 
					
						
						|  | values: t.List["Expr"] | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Block(Stmt): | 
					
						
						|  | """A node that represents a block. | 
					
						
						|  |  | 
					
						
						|  | .. versionchanged:: 3.0.0 | 
					
						
						|  | the `required` field was added. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("name", "body", "scoped", "required") | 
					
						
						|  | name: str | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  | scoped: bool | 
					
						
						|  | required: bool | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Include(Stmt): | 
					
						
						|  | """A node that represents the include tag.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("template", "with_context", "ignore_missing") | 
					
						
						|  | template: "Expr" | 
					
						
						|  | with_context: bool | 
					
						
						|  | ignore_missing: bool | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Import(Stmt): | 
					
						
						|  | """A node that represents the import tag.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("template", "target", "with_context") | 
					
						
						|  | template: "Expr" | 
					
						
						|  | target: str | 
					
						
						|  | with_context: bool | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class FromImport(Stmt): | 
					
						
						|  | """A node that represents the from import tag.  It's important to not | 
					
						
						|  | pass unsafe names to the name attribute.  The compiler translates the | 
					
						
						|  | attribute lookups directly into getattr calls and does *not* use the | 
					
						
						|  | subscript callback of the interface.  As exported variables may not | 
					
						
						|  | start with double underscores (which the parser asserts) this is not a | 
					
						
						|  | problem for regular Jinja code, but if this node is used in an extension | 
					
						
						|  | extra care must be taken. | 
					
						
						|  |  | 
					
						
						|  | The list of names may contain tuples if aliases are wanted. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("template", "names", "with_context") | 
					
						
						|  | template: "Expr" | 
					
						
						|  | names: t.List[t.Union[str, t.Tuple[str, str]]] | 
					
						
						|  | with_context: bool | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class ExprStmt(Stmt): | 
					
						
						|  | """A statement that evaluates an expression and discards the result.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("node",) | 
					
						
						|  | node: Node | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Assign(Stmt): | 
					
						
						|  | """Assigns an expression to a target.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("target", "node") | 
					
						
						|  | target: "Expr" | 
					
						
						|  | node: Node | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class AssignBlock(Stmt): | 
					
						
						|  | """Assigns a block to a target.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("target", "filter", "body") | 
					
						
						|  | target: "Expr" | 
					
						
						|  | filter: t.Optional["Filter"] | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Expr(Node): | 
					
						
						|  | """Baseclass for all expressions.""" | 
					
						
						|  |  | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | """Return the value of the expression as constant or raise | 
					
						
						|  | :exc:`Impossible` if this was not possible. | 
					
						
						|  |  | 
					
						
						|  | An :class:`EvalContext` can be provided, if none is given | 
					
						
						|  | a default context is created which requires the nodes to have | 
					
						
						|  | an attached environment. | 
					
						
						|  |  | 
					
						
						|  | .. versionchanged:: 2.4 | 
					
						
						|  | the `eval_ctx` parameter was added. | 
					
						
						|  | """ | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | def can_assign(self) -> bool: | 
					
						
						|  | """Check if it's possible to assign something to this node.""" | 
					
						
						|  | return False | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class BinExpr(Expr): | 
					
						
						|  | """Baseclass for all binary expressions.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("left", "right") | 
					
						
						|  | left: Expr | 
					
						
						|  | right: Expr | 
					
						
						|  | operator: str | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | if ( | 
					
						
						|  | eval_ctx.environment.sandboxed | 
					
						
						|  | and self.operator in eval_ctx.environment.intercepted_binops | 
					
						
						|  | ): | 
					
						
						|  | raise Impossible() | 
					
						
						|  | f = _binop_to_func[self.operator] | 
					
						
						|  | try: | 
					
						
						|  | return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class UnaryExpr(Expr): | 
					
						
						|  | """Baseclass for all unary expressions.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("node",) | 
					
						
						|  | node: Expr | 
					
						
						|  | operator: str | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | if ( | 
					
						
						|  | eval_ctx.environment.sandboxed | 
					
						
						|  | and self.operator in eval_ctx.environment.intercepted_unops | 
					
						
						|  | ): | 
					
						
						|  | raise Impossible() | 
					
						
						|  | f = _uaop_to_func[self.operator] | 
					
						
						|  | try: | 
					
						
						|  | return f(self.node.as_const(eval_ctx)) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Name(Expr): | 
					
						
						|  | """Looks up a name or stores a value in a name. | 
					
						
						|  | The `ctx` of the node can be one of the following values: | 
					
						
						|  |  | 
					
						
						|  | -   `store`: store a value in the name | 
					
						
						|  | -   `load`: load that name | 
					
						
						|  | -   `param`: like `store` but if the name was defined as function parameter. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("name", "ctx") | 
					
						
						|  | name: str | 
					
						
						|  | ctx: str | 
					
						
						|  |  | 
					
						
						|  | def can_assign(self) -> bool: | 
					
						
						|  | return self.name not in {"true", "false", "none", "True", "False", "None"} | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class NSRef(Expr): | 
					
						
						|  | """Reference to a namespace value assignment""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("name", "attr") | 
					
						
						|  | name: str | 
					
						
						|  | attr: str | 
					
						
						|  |  | 
					
						
						|  | def can_assign(self) -> bool: | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | return True | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Literal(Expr): | 
					
						
						|  | """Baseclass for literals.""" | 
					
						
						|  |  | 
					
						
						|  | abstract = True | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Const(Literal): | 
					
						
						|  | """All constant values.  The parser will return this node for simple | 
					
						
						|  | constants such as ``42`` or ``"foo"`` but it can be used to store more | 
					
						
						|  | complex values such as lists too.  Only constants with a safe | 
					
						
						|  | representation (objects where ``eval(repr(x)) == x`` is true). | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("value",) | 
					
						
						|  | value: t.Any | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | return self.value | 
					
						
						|  |  | 
					
						
						|  | @classmethod | 
					
						
						|  | def from_untrusted( | 
					
						
						|  | cls, | 
					
						
						|  | value: t.Any, | 
					
						
						|  | lineno: t.Optional[int] = None, | 
					
						
						|  | environment: "t.Optional[Environment]" = None, | 
					
						
						|  | ) -> "Const": | 
					
						
						|  | """Return a const object if the value is representable as | 
					
						
						|  | constant value in the generated code, otherwise it will raise | 
					
						
						|  | an `Impossible` exception. | 
					
						
						|  | """ | 
					
						
						|  | from .compiler import has_safe_repr | 
					
						
						|  |  | 
					
						
						|  | if not has_safe_repr(value): | 
					
						
						|  | raise Impossible() | 
					
						
						|  | return cls(value, lineno=lineno, environment=environment) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class TemplateData(Literal): | 
					
						
						|  | """A constant template string.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("data",) | 
					
						
						|  | data: str | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | if eval_ctx.volatile: | 
					
						
						|  | raise Impossible() | 
					
						
						|  | if eval_ctx.autoescape: | 
					
						
						|  | return Markup(self.data) | 
					
						
						|  | return self.data | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Tuple(Literal): | 
					
						
						|  | """For loop unpacking and some other things like multiple arguments | 
					
						
						|  | for subscripts.  Like for :class:`Name` `ctx` specifies if the tuple | 
					
						
						|  | is used for loading the names or storing. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("items", "ctx") | 
					
						
						|  | items: t.List[Expr] | 
					
						
						|  | ctx: str | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[t.Any, ...]: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return tuple(x.as_const(eval_ctx) for x in self.items) | 
					
						
						|  |  | 
					
						
						|  | def can_assign(self) -> bool: | 
					
						
						|  | for item in self.items: | 
					
						
						|  | if not item.can_assign(): | 
					
						
						|  | return False | 
					
						
						|  | return True | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class List(Literal): | 
					
						
						|  | """Any list literal such as ``[1, 2, 3]``""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("items",) | 
					
						
						|  | items: t.List[Expr] | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.List[t.Any]: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return [x.as_const(eval_ctx) for x in self.items] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Dict(Literal): | 
					
						
						|  | """Any dict literal such as ``{1: 2, 3: 4}``.  The items must be a list of | 
					
						
						|  | :class:`Pair` nodes. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("items",) | 
					
						
						|  | items: t.List["Pair"] | 
					
						
						|  |  | 
					
						
						|  | def as_const( | 
					
						
						|  | self, eval_ctx: t.Optional[EvalContext] = None | 
					
						
						|  | ) -> t.Dict[t.Any, t.Any]: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return dict(x.as_const(eval_ctx) for x in self.items) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Pair(Helper): | 
					
						
						|  | """A key, value pair for dicts.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("key", "value") | 
					
						
						|  | key: Expr | 
					
						
						|  | value: Expr | 
					
						
						|  |  | 
					
						
						|  | def as_const( | 
					
						
						|  | self, eval_ctx: t.Optional[EvalContext] = None | 
					
						
						|  | ) -> t.Tuple[t.Any, t.Any]: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Keyword(Helper): | 
					
						
						|  | """A key, value pair for keyword arguments where key is a string.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("key", "value") | 
					
						
						|  | key: str | 
					
						
						|  | value: Expr | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[str, t.Any]: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return self.key, self.value.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class CondExpr(Expr): | 
					
						
						|  | """A conditional expression (inline if expression).  (``{{ | 
					
						
						|  | foo if bar else baz }}``) | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("test", "expr1", "expr2") | 
					
						
						|  | test: Expr | 
					
						
						|  | expr1: Expr | 
					
						
						|  | expr2: t.Optional[Expr] | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | if self.test.as_const(eval_ctx): | 
					
						
						|  | return self.expr1.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | if self.expr2 is None: | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | return self.expr2.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | def args_as_const( | 
					
						
						|  | node: t.Union["_FilterTestCommon", "Call"], eval_ctx: t.Optional[EvalContext] | 
					
						
						|  | ) -> t.Tuple[t.List[t.Any], t.Dict[t.Any, t.Any]]: | 
					
						
						|  | args = [x.as_const(eval_ctx) for x in node.args] | 
					
						
						|  | kwargs = dict(x.as_const(eval_ctx) for x in node.kwargs) | 
					
						
						|  |  | 
					
						
						|  | if node.dyn_args is not None: | 
					
						
						|  | try: | 
					
						
						|  | args.extend(node.dyn_args.as_const(eval_ctx)) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  | if node.dyn_kwargs is not None: | 
					
						
						|  | try: | 
					
						
						|  | kwargs.update(node.dyn_kwargs.as_const(eval_ctx)) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  | return args, kwargs | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class _FilterTestCommon(Expr): | 
					
						
						|  | fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs") | 
					
						
						|  | node: Expr | 
					
						
						|  | name: str | 
					
						
						|  | args: t.List[Expr] | 
					
						
						|  | kwargs: t.List[Pair] | 
					
						
						|  | dyn_args: t.Optional[Expr] | 
					
						
						|  | dyn_kwargs: t.Optional[Expr] | 
					
						
						|  | abstract = True | 
					
						
						|  | _is_filter = True | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  |  | 
					
						
						|  | if eval_ctx.volatile: | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | if self._is_filter: | 
					
						
						|  | env_map = eval_ctx.environment.filters | 
					
						
						|  | else: | 
					
						
						|  | env_map = eval_ctx.environment.tests | 
					
						
						|  |  | 
					
						
						|  | func = env_map.get(self.name) | 
					
						
						|  | pass_arg = _PassArg.from_obj(func) | 
					
						
						|  |  | 
					
						
						|  | if func is None or pass_arg is _PassArg.context: | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | if eval_ctx.environment.is_async and ( | 
					
						
						|  | getattr(func, "jinja_async_variant", False) is True | 
					
						
						|  | or inspect.iscoroutinefunction(func) | 
					
						
						|  | ): | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | args, kwargs = args_as_const(self, eval_ctx) | 
					
						
						|  | args.insert(0, self.node.as_const(eval_ctx)) | 
					
						
						|  |  | 
					
						
						|  | if pass_arg is _PassArg.eval_context: | 
					
						
						|  | args.insert(0, eval_ctx) | 
					
						
						|  | elif pass_arg is _PassArg.environment: | 
					
						
						|  | args.insert(0, eval_ctx.environment) | 
					
						
						|  |  | 
					
						
						|  | try: | 
					
						
						|  | return func(*args, **kwargs) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Filter(_FilterTestCommon): | 
					
						
						|  | """Apply a filter to an expression. ``name`` is the name of the | 
					
						
						|  | filter, the other fields are the same as :class:`Call`. | 
					
						
						|  |  | 
					
						
						|  | If ``node`` is ``None``, the filter is being used in a filter block | 
					
						
						|  | and is applied to the content of the block. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | node: t.Optional[Expr] | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | if self.node is None: | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | return super().as_const(eval_ctx=eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Test(_FilterTestCommon): | 
					
						
						|  | """Apply a test to an expression. ``name`` is the name of the test, | 
					
						
						|  | the other field are the same as :class:`Call`. | 
					
						
						|  |  | 
					
						
						|  | .. versionchanged:: 3.0 | 
					
						
						|  | ``as_const`` shares the same logic for filters and tests. Tests | 
					
						
						|  | check for volatile, async, and ``@pass_context`` etc. | 
					
						
						|  | decorators. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | _is_filter = False | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Call(Expr): | 
					
						
						|  | """Calls an expression.  `args` is a list of arguments, `kwargs` a list | 
					
						
						|  | of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args` | 
					
						
						|  | and `dyn_kwargs` has to be either `None` or a node that is used as | 
					
						
						|  | node for dynamic positional (``*args``) or keyword (``**kwargs``) | 
					
						
						|  | arguments. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs") | 
					
						
						|  | node: Expr | 
					
						
						|  | args: t.List[Expr] | 
					
						
						|  | kwargs: t.List[Keyword] | 
					
						
						|  | dyn_args: t.Optional[Expr] | 
					
						
						|  | dyn_kwargs: t.Optional[Expr] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Getitem(Expr): | 
					
						
						|  | """Get an attribute or item from an expression and prefer the item.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("node", "arg", "ctx") | 
					
						
						|  | node: Expr | 
					
						
						|  | arg: Expr | 
					
						
						|  | ctx: str | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | if self.ctx != "load": | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  |  | 
					
						
						|  | try: | 
					
						
						|  | return eval_ctx.environment.getitem( | 
					
						
						|  | self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx) | 
					
						
						|  | ) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Getattr(Expr): | 
					
						
						|  | """Get an attribute or item from an expression that is a ascii-only | 
					
						
						|  | bytestring and prefer the attribute. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("node", "attr", "ctx") | 
					
						
						|  | node: Expr | 
					
						
						|  | attr: str | 
					
						
						|  | ctx: str | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | if self.ctx != "load": | 
					
						
						|  | raise Impossible() | 
					
						
						|  |  | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  |  | 
					
						
						|  | try: | 
					
						
						|  | return eval_ctx.environment.getattr(self.node.as_const(eval_ctx), self.attr) | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Slice(Expr): | 
					
						
						|  | """Represents a slice object.  This must only be used as argument for | 
					
						
						|  | :class:`Subscript`. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("start", "stop", "step") | 
					
						
						|  | start: t.Optional[Expr] | 
					
						
						|  | stop: t.Optional[Expr] | 
					
						
						|  | step: t.Optional[Expr] | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> slice: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  |  | 
					
						
						|  | def const(obj: t.Optional[Expr]) -> t.Optional[t.Any]: | 
					
						
						|  | if obj is None: | 
					
						
						|  | return None | 
					
						
						|  | return obj.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  | return slice(const(self.start), const(self.stop), const(self.step)) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Concat(Expr): | 
					
						
						|  | """Concatenates the list of expressions provided after converting | 
					
						
						|  | them to strings. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("nodes",) | 
					
						
						|  | nodes: t.List[Expr] | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return "".join(str(x.as_const(eval_ctx)) for x in self.nodes) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Compare(Expr): | 
					
						
						|  | """Compares an expression with some other expressions.  `ops` must be a | 
					
						
						|  | list of :class:`Operand`\\s. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("expr", "ops") | 
					
						
						|  | expr: Expr | 
					
						
						|  | ops: t.List["Operand"] | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | result = value = self.expr.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  | try: | 
					
						
						|  | for op in self.ops: | 
					
						
						|  | new_value = op.expr.as_const(eval_ctx) | 
					
						
						|  | result = _cmpop_to_func[op.op](value, new_value) | 
					
						
						|  |  | 
					
						
						|  | if not result: | 
					
						
						|  | return False | 
					
						
						|  |  | 
					
						
						|  | value = new_value | 
					
						
						|  | except Exception as e: | 
					
						
						|  | raise Impossible() from e | 
					
						
						|  |  | 
					
						
						|  | return result | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Operand(Helper): | 
					
						
						|  | """Holds an operator and an expression.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("op", "expr") | 
					
						
						|  | op: str | 
					
						
						|  | expr: Expr | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Mul(BinExpr): | 
					
						
						|  | """Multiplies the left with the right node.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "*" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Div(BinExpr): | 
					
						
						|  | """Divides the left by the right node.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "/" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class FloorDiv(BinExpr): | 
					
						
						|  | """Divides the left by the right node and converts the | 
					
						
						|  | result into an integer by truncating. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | operator = "//" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Add(BinExpr): | 
					
						
						|  | """Add the left to the right node.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "+" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Sub(BinExpr): | 
					
						
						|  | """Subtract the right from the left node.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "-" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Mod(BinExpr): | 
					
						
						|  | """Left modulo right.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "%" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Pow(BinExpr): | 
					
						
						|  | """Left to the power of right.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "**" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class And(BinExpr): | 
					
						
						|  | """Short circuited AND.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "and" | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Or(BinExpr): | 
					
						
						|  | """Short circuited OR.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "or" | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Not(UnaryExpr): | 
					
						
						|  | """Negate the expression.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "not" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Neg(UnaryExpr): | 
					
						
						|  | """Make the expression negative.""" | 
					
						
						|  |  | 
					
						
						|  | operator = "-" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Pos(UnaryExpr): | 
					
						
						|  | """Make the expression positive (noop for most expressions)""" | 
					
						
						|  |  | 
					
						
						|  | operator = "+" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class EnvironmentAttribute(Expr): | 
					
						
						|  | """Loads an attribute from the environment object.  This is useful for | 
					
						
						|  | extensions that want to call a callback stored on the environment. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("name",) | 
					
						
						|  | name: str | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class ExtensionAttribute(Expr): | 
					
						
						|  | """Returns the attribute of an extension bound to the environment. | 
					
						
						|  | The identifier is the identifier of the :class:`Extension`. | 
					
						
						|  |  | 
					
						
						|  | This node is usually constructed by calling the | 
					
						
						|  | :meth:`~jinja2.ext.Extension.attr` method on an extension. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("identifier", "name") | 
					
						
						|  | identifier: str | 
					
						
						|  | name: str | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class ImportedName(Expr): | 
					
						
						|  | """If created with an import name the import name is returned on node | 
					
						
						|  | access.  For example ``ImportedName('cgi.escape')`` returns the `escape` | 
					
						
						|  | function from the cgi module on evaluation.  Imports are optimized by the | 
					
						
						|  | compiler so there is no need to assign them to local variables. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("importname",) | 
					
						
						|  | importname: str | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class InternalName(Expr): | 
					
						
						|  | """An internal name in the compiler.  You cannot create these nodes | 
					
						
						|  | yourself but the parser provides a | 
					
						
						|  | :meth:`~jinja2.parser.Parser.free_identifier` method that creates | 
					
						
						|  | a new identifier for you.  This identifier is not available from the | 
					
						
						|  | template and is not treated specially by the compiler. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("name",) | 
					
						
						|  | name: str | 
					
						
						|  |  | 
					
						
						|  | def __init__(self) -> None: | 
					
						
						|  | raise TypeError( | 
					
						
						|  | "Can't create internal names.  Use the " | 
					
						
						|  | "`free_identifier` method on a parser." | 
					
						
						|  | ) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class MarkSafe(Expr): | 
					
						
						|  | """Mark the wrapped expression as safe (wrap it as `Markup`).""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("expr",) | 
					
						
						|  | expr: Expr | 
					
						
						|  |  | 
					
						
						|  | def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> Markup: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | return Markup(self.expr.as_const(eval_ctx)) | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class MarkSafeIfAutoescape(Expr): | 
					
						
						|  | """Mark the wrapped expression as safe (wrap it as `Markup`) but | 
					
						
						|  | only if autoescaping is active. | 
					
						
						|  |  | 
					
						
						|  | .. versionadded:: 2.5 | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("expr",) | 
					
						
						|  | expr: Expr | 
					
						
						|  |  | 
					
						
						|  | def as_const( | 
					
						
						|  | self, eval_ctx: t.Optional[EvalContext] = None | 
					
						
						|  | ) -> t.Union[Markup, t.Any]: | 
					
						
						|  | eval_ctx = get_eval_context(self, eval_ctx) | 
					
						
						|  | if eval_ctx.volatile: | 
					
						
						|  | raise Impossible() | 
					
						
						|  | expr = self.expr.as_const(eval_ctx) | 
					
						
						|  | if eval_ctx.autoescape: | 
					
						
						|  | return Markup(expr) | 
					
						
						|  | return expr | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class ContextReference(Expr): | 
					
						
						|  | """Returns the current template context.  It can be used like a | 
					
						
						|  | :class:`Name` node, with a ``'load'`` ctx and will return the | 
					
						
						|  | current :class:`~jinja2.runtime.Context` object. | 
					
						
						|  |  | 
					
						
						|  | Here an example that assigns the current template name to a | 
					
						
						|  | variable named `foo`:: | 
					
						
						|  |  | 
					
						
						|  | Assign(Name('foo', ctx='store'), | 
					
						
						|  | Getattr(ContextReference(), 'name')) | 
					
						
						|  |  | 
					
						
						|  | This is basically equivalent to using the | 
					
						
						|  | :func:`~jinja2.pass_context` decorator when using the high-level | 
					
						
						|  | API, which causes a reference to the context to be passed as the | 
					
						
						|  | first argument to a function. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class DerivedContextReference(Expr): | 
					
						
						|  | """Return the current template context including locals. Behaves | 
					
						
						|  | exactly like :class:`ContextReference`, but includes local | 
					
						
						|  | variables, such as from a ``for`` loop. | 
					
						
						|  |  | 
					
						
						|  | .. versionadded:: 2.11 | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Continue(Stmt): | 
					
						
						|  | """Continue a loop.""" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Break(Stmt): | 
					
						
						|  | """Break a loop.""" | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class Scope(Stmt): | 
					
						
						|  | """An artificial scope.""" | 
					
						
						|  |  | 
					
						
						|  | fields = ("body",) | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class OverlayScope(Stmt): | 
					
						
						|  | """An overlay scope for extensions.  This is a largely unoptimized scope | 
					
						
						|  | that however can be used to introduce completely arbitrary variables into | 
					
						
						|  | a sub scope from a dictionary or dictionary like object.  The `context` | 
					
						
						|  | field has to evaluate to a dictionary object. | 
					
						
						|  |  | 
					
						
						|  | Example usage:: | 
					
						
						|  |  | 
					
						
						|  | OverlayScope(context=self.call_method('get_context'), | 
					
						
						|  | body=[...]) | 
					
						
						|  |  | 
					
						
						|  | .. versionadded:: 2.10 | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("context", "body") | 
					
						
						|  | context: Expr | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class EvalContextModifier(Stmt): | 
					
						
						|  | """Modifies the eval context.  For each option that should be modified, | 
					
						
						|  | a :class:`Keyword` has to be added to the :attr:`options` list. | 
					
						
						|  |  | 
					
						
						|  | Example to change the `autoescape` setting:: | 
					
						
						|  |  | 
					
						
						|  | EvalContextModifier(options=[Keyword('autoescape', Const(True))]) | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("options",) | 
					
						
						|  | options: t.List[Keyword] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | class ScopedEvalContextModifier(EvalContextModifier): | 
					
						
						|  | """Modifies the eval context and reverts it later.  Works exactly like | 
					
						
						|  | :class:`EvalContextModifier` but will only modify the | 
					
						
						|  | :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`. | 
					
						
						|  | """ | 
					
						
						|  |  | 
					
						
						|  | fields = ("body",) | 
					
						
						|  | body: t.List[Node] | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | def _failing_new(*args: t.Any, **kwargs: t.Any) -> "te.NoReturn": | 
					
						
						|  | raise TypeError("can't create custom node types") | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | NodeType.__new__ = staticmethod(_failing_new) | 
					
						
						|  | del _failing_new | 
					
						
						|  |  |