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