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