1e31aef6aSopenharmony_ci"""Classes for managing templates and their runtime and compile time
2e31aef6aSopenharmony_cioptions.
3e31aef6aSopenharmony_ci"""
4e31aef6aSopenharmony_ciimport os
5e31aef6aSopenharmony_ciimport typing
6e31aef6aSopenharmony_ciimport typing as t
7e31aef6aSopenharmony_ciimport weakref
8e31aef6aSopenharmony_cifrom collections import ChainMap
9e31aef6aSopenharmony_cifrom functools import lru_cache
10e31aef6aSopenharmony_cifrom functools import partial
11e31aef6aSopenharmony_cifrom functools import reduce
12e31aef6aSopenharmony_cifrom types import CodeType
13e31aef6aSopenharmony_ci
14e31aef6aSopenharmony_cifrom markupsafe import Markup
15e31aef6aSopenharmony_ci
16e31aef6aSopenharmony_cifrom . import nodes
17e31aef6aSopenharmony_cifrom .compiler import CodeGenerator
18e31aef6aSopenharmony_cifrom .compiler import generate
19e31aef6aSopenharmony_cifrom .defaults import BLOCK_END_STRING
20e31aef6aSopenharmony_cifrom .defaults import BLOCK_START_STRING
21e31aef6aSopenharmony_cifrom .defaults import COMMENT_END_STRING
22e31aef6aSopenharmony_cifrom .defaults import COMMENT_START_STRING
23e31aef6aSopenharmony_cifrom .defaults import DEFAULT_FILTERS
24e31aef6aSopenharmony_cifrom .defaults import DEFAULT_NAMESPACE
25e31aef6aSopenharmony_cifrom .defaults import DEFAULT_POLICIES
26e31aef6aSopenharmony_cifrom .defaults import DEFAULT_TESTS
27e31aef6aSopenharmony_cifrom .defaults import KEEP_TRAILING_NEWLINE
28e31aef6aSopenharmony_cifrom .defaults import LINE_COMMENT_PREFIX
29e31aef6aSopenharmony_cifrom .defaults import LINE_STATEMENT_PREFIX
30e31aef6aSopenharmony_cifrom .defaults import LSTRIP_BLOCKS
31e31aef6aSopenharmony_cifrom .defaults import NEWLINE_SEQUENCE
32e31aef6aSopenharmony_cifrom .defaults import TRIM_BLOCKS
33e31aef6aSopenharmony_cifrom .defaults import VARIABLE_END_STRING
34e31aef6aSopenharmony_cifrom .defaults import VARIABLE_START_STRING
35e31aef6aSopenharmony_cifrom .exceptions import TemplateNotFound
36e31aef6aSopenharmony_cifrom .exceptions import TemplateRuntimeError
37e31aef6aSopenharmony_cifrom .exceptions import TemplatesNotFound
38e31aef6aSopenharmony_cifrom .exceptions import TemplateSyntaxError
39e31aef6aSopenharmony_cifrom .exceptions import UndefinedError
40e31aef6aSopenharmony_cifrom .lexer import get_lexer
41e31aef6aSopenharmony_cifrom .lexer import Lexer
42e31aef6aSopenharmony_cifrom .lexer import TokenStream
43e31aef6aSopenharmony_cifrom .nodes import EvalContext
44e31aef6aSopenharmony_cifrom .parser import Parser
45e31aef6aSopenharmony_cifrom .runtime import Context
46e31aef6aSopenharmony_cifrom .runtime import new_context
47e31aef6aSopenharmony_cifrom .runtime import Undefined
48e31aef6aSopenharmony_cifrom .utils import _PassArg
49e31aef6aSopenharmony_cifrom .utils import concat
50e31aef6aSopenharmony_cifrom .utils import consume
51e31aef6aSopenharmony_cifrom .utils import import_string
52e31aef6aSopenharmony_cifrom .utils import internalcode
53e31aef6aSopenharmony_cifrom .utils import LRUCache
54e31aef6aSopenharmony_cifrom .utils import missing
55e31aef6aSopenharmony_ci
56e31aef6aSopenharmony_ciif t.TYPE_CHECKING:
57e31aef6aSopenharmony_ci    import typing_extensions as te
58e31aef6aSopenharmony_ci    from .bccache import BytecodeCache
59e31aef6aSopenharmony_ci    from .ext import Extension
60e31aef6aSopenharmony_ci    from .loaders import BaseLoader
61e31aef6aSopenharmony_ci
62e31aef6aSopenharmony_ci_env_bound = t.TypeVar("_env_bound", bound="Environment")
63e31aef6aSopenharmony_ci
64e31aef6aSopenharmony_ci
65e31aef6aSopenharmony_ci# for direct template usage we have up to ten living environments
66e31aef6aSopenharmony_ci@lru_cache(maxsize=10)
67e31aef6aSopenharmony_cidef get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound:
68e31aef6aSopenharmony_ci    """Return a new spontaneous environment. A spontaneous environment
69e31aef6aSopenharmony_ci    is used for templates created directly rather than through an
70e31aef6aSopenharmony_ci    existing environment.
71e31aef6aSopenharmony_ci
72e31aef6aSopenharmony_ci    :param cls: Environment class to create.
73e31aef6aSopenharmony_ci    :param args: Positional arguments passed to environment.
74e31aef6aSopenharmony_ci    """
75e31aef6aSopenharmony_ci    env = cls(*args)
76e31aef6aSopenharmony_ci    env.shared = True
77e31aef6aSopenharmony_ci    return env
78e31aef6aSopenharmony_ci
79e31aef6aSopenharmony_ci
80e31aef6aSopenharmony_cidef create_cache(
81e31aef6aSopenharmony_ci    size: int,
82e31aef6aSopenharmony_ci) -> t.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]:
83e31aef6aSopenharmony_ci    """Return the cache class for the given size."""
84e31aef6aSopenharmony_ci    if size == 0:
85e31aef6aSopenharmony_ci        return None
86e31aef6aSopenharmony_ci
87e31aef6aSopenharmony_ci    if size < 0:
88e31aef6aSopenharmony_ci        return {}
89e31aef6aSopenharmony_ci
90e31aef6aSopenharmony_ci    return LRUCache(size)  # type: ignore
91e31aef6aSopenharmony_ci
92e31aef6aSopenharmony_ci
93e31aef6aSopenharmony_cidef copy_cache(
94e31aef6aSopenharmony_ci    cache: t.Optional[t.MutableMapping],
95e31aef6aSopenharmony_ci) -> t.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]:
96e31aef6aSopenharmony_ci    """Create an empty copy of the given cache."""
97e31aef6aSopenharmony_ci    if cache is None:
98e31aef6aSopenharmony_ci        return None
99e31aef6aSopenharmony_ci
100e31aef6aSopenharmony_ci    if type(cache) is dict:
101e31aef6aSopenharmony_ci        return {}
102e31aef6aSopenharmony_ci
103e31aef6aSopenharmony_ci    return LRUCache(cache.capacity)  # type: ignore
104e31aef6aSopenharmony_ci
105e31aef6aSopenharmony_ci
106e31aef6aSopenharmony_cidef load_extensions(
107e31aef6aSopenharmony_ci    environment: "Environment",
108e31aef6aSopenharmony_ci    extensions: t.Sequence[t.Union[str, t.Type["Extension"]]],
109e31aef6aSopenharmony_ci) -> t.Dict[str, "Extension"]:
110e31aef6aSopenharmony_ci    """Load the extensions from the list and bind it to the environment.
111e31aef6aSopenharmony_ci    Returns a dict of instantiated extensions.
112e31aef6aSopenharmony_ci    """
113e31aef6aSopenharmony_ci    result = {}
114e31aef6aSopenharmony_ci
115e31aef6aSopenharmony_ci    for extension in extensions:
116e31aef6aSopenharmony_ci        if isinstance(extension, str):
117e31aef6aSopenharmony_ci            extension = t.cast(t.Type["Extension"], import_string(extension))
118e31aef6aSopenharmony_ci
119e31aef6aSopenharmony_ci        result[extension.identifier] = extension(environment)
120e31aef6aSopenharmony_ci
121e31aef6aSopenharmony_ci    return result
122e31aef6aSopenharmony_ci
123e31aef6aSopenharmony_ci
124e31aef6aSopenharmony_cidef _environment_config_check(environment: "Environment") -> "Environment":
125e31aef6aSopenharmony_ci    """Perform a sanity check on the environment."""
126e31aef6aSopenharmony_ci    assert issubclass(
127e31aef6aSopenharmony_ci        environment.undefined, Undefined
128e31aef6aSopenharmony_ci    ), "'undefined' must be a subclass of 'jinja2.Undefined'."
129e31aef6aSopenharmony_ci    assert (
130e31aef6aSopenharmony_ci        environment.block_start_string
131e31aef6aSopenharmony_ci        != environment.variable_start_string
132e31aef6aSopenharmony_ci        != environment.comment_start_string
133e31aef6aSopenharmony_ci    ), "block, variable and comment start strings must be different."
134e31aef6aSopenharmony_ci    assert environment.newline_sequence in {
135e31aef6aSopenharmony_ci        "\r",
136e31aef6aSopenharmony_ci        "\r\n",
137e31aef6aSopenharmony_ci        "\n",
138e31aef6aSopenharmony_ci    }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'."
139e31aef6aSopenharmony_ci    return environment
140e31aef6aSopenharmony_ci
141e31aef6aSopenharmony_ci
142e31aef6aSopenharmony_ciclass Environment:
143e31aef6aSopenharmony_ci    r"""The core component of Jinja is the `Environment`.  It contains
144e31aef6aSopenharmony_ci    important shared variables like configuration, filters, tests,
145e31aef6aSopenharmony_ci    globals and others.  Instances of this class may be modified if
146e31aef6aSopenharmony_ci    they are not shared and if no template was loaded so far.
147e31aef6aSopenharmony_ci    Modifications on environments after the first template was loaded
148e31aef6aSopenharmony_ci    will lead to surprising effects and undefined behavior.
149e31aef6aSopenharmony_ci
150e31aef6aSopenharmony_ci    Here are the possible initialization parameters:
151e31aef6aSopenharmony_ci
152e31aef6aSopenharmony_ci        `block_start_string`
153e31aef6aSopenharmony_ci            The string marking the beginning of a block.  Defaults to ``'{%'``.
154e31aef6aSopenharmony_ci
155e31aef6aSopenharmony_ci        `block_end_string`
156e31aef6aSopenharmony_ci            The string marking the end of a block.  Defaults to ``'%}'``.
157e31aef6aSopenharmony_ci
158e31aef6aSopenharmony_ci        `variable_start_string`
159e31aef6aSopenharmony_ci            The string marking the beginning of a print statement.
160e31aef6aSopenharmony_ci            Defaults to ``'{{'``.
161e31aef6aSopenharmony_ci
162e31aef6aSopenharmony_ci        `variable_end_string`
163e31aef6aSopenharmony_ci            The string marking the end of a print statement.  Defaults to
164e31aef6aSopenharmony_ci            ``'}}'``.
165e31aef6aSopenharmony_ci
166e31aef6aSopenharmony_ci        `comment_start_string`
167e31aef6aSopenharmony_ci            The string marking the beginning of a comment.  Defaults to ``'{#'``.
168e31aef6aSopenharmony_ci
169e31aef6aSopenharmony_ci        `comment_end_string`
170e31aef6aSopenharmony_ci            The string marking the end of a comment.  Defaults to ``'#}'``.
171e31aef6aSopenharmony_ci
172e31aef6aSopenharmony_ci        `line_statement_prefix`
173e31aef6aSopenharmony_ci            If given and a string, this will be used as prefix for line based
174e31aef6aSopenharmony_ci            statements.  See also :ref:`line-statements`.
175e31aef6aSopenharmony_ci
176e31aef6aSopenharmony_ci        `line_comment_prefix`
177e31aef6aSopenharmony_ci            If given and a string, this will be used as prefix for line based
178e31aef6aSopenharmony_ci            comments.  See also :ref:`line-statements`.
179e31aef6aSopenharmony_ci
180e31aef6aSopenharmony_ci            .. versionadded:: 2.2
181e31aef6aSopenharmony_ci
182e31aef6aSopenharmony_ci        `trim_blocks`
183e31aef6aSopenharmony_ci            If this is set to ``True`` the first newline after a block is
184e31aef6aSopenharmony_ci            removed (block, not variable tag!).  Defaults to `False`.
185e31aef6aSopenharmony_ci
186e31aef6aSopenharmony_ci        `lstrip_blocks`
187e31aef6aSopenharmony_ci            If this is set to ``True`` leading spaces and tabs are stripped
188e31aef6aSopenharmony_ci            from the start of a line to a block.  Defaults to `False`.
189e31aef6aSopenharmony_ci
190e31aef6aSopenharmony_ci        `newline_sequence`
191e31aef6aSopenharmony_ci            The sequence that starts a newline.  Must be one of ``'\r'``,
192e31aef6aSopenharmony_ci            ``'\n'`` or ``'\r\n'``.  The default is ``'\n'`` which is a
193e31aef6aSopenharmony_ci            useful default for Linux and OS X systems as well as web
194e31aef6aSopenharmony_ci            applications.
195e31aef6aSopenharmony_ci
196e31aef6aSopenharmony_ci        `keep_trailing_newline`
197e31aef6aSopenharmony_ci            Preserve the trailing newline when rendering templates.
198e31aef6aSopenharmony_ci            The default is ``False``, which causes a single newline,
199e31aef6aSopenharmony_ci            if present, to be stripped from the end of the template.
200e31aef6aSopenharmony_ci
201e31aef6aSopenharmony_ci            .. versionadded:: 2.7
202e31aef6aSopenharmony_ci
203e31aef6aSopenharmony_ci        `extensions`
204e31aef6aSopenharmony_ci            List of Jinja extensions to use.  This can either be import paths
205e31aef6aSopenharmony_ci            as strings or extension classes.  For more information have a
206e31aef6aSopenharmony_ci            look at :ref:`the extensions documentation <jinja-extensions>`.
207e31aef6aSopenharmony_ci
208e31aef6aSopenharmony_ci        `optimized`
209e31aef6aSopenharmony_ci            should the optimizer be enabled?  Default is ``True``.
210e31aef6aSopenharmony_ci
211e31aef6aSopenharmony_ci        `undefined`
212e31aef6aSopenharmony_ci            :class:`Undefined` or a subclass of it that is used to represent
213e31aef6aSopenharmony_ci            undefined values in the template.
214e31aef6aSopenharmony_ci
215e31aef6aSopenharmony_ci        `finalize`
216e31aef6aSopenharmony_ci            A callable that can be used to process the result of a variable
217e31aef6aSopenharmony_ci            expression before it is output.  For example one can convert
218e31aef6aSopenharmony_ci            ``None`` implicitly into an empty string here.
219e31aef6aSopenharmony_ci
220e31aef6aSopenharmony_ci        `autoescape`
221e31aef6aSopenharmony_ci            If set to ``True`` the XML/HTML autoescaping feature is enabled by
222e31aef6aSopenharmony_ci            default.  For more details about autoescaping see
223e31aef6aSopenharmony_ci            :class:`~markupsafe.Markup`.  As of Jinja 2.4 this can also
224e31aef6aSopenharmony_ci            be a callable that is passed the template name and has to
225e31aef6aSopenharmony_ci            return ``True`` or ``False`` depending on autoescape should be
226e31aef6aSopenharmony_ci            enabled by default.
227e31aef6aSopenharmony_ci
228e31aef6aSopenharmony_ci            .. versionchanged:: 2.4
229e31aef6aSopenharmony_ci               `autoescape` can now be a function
230e31aef6aSopenharmony_ci
231e31aef6aSopenharmony_ci        `loader`
232e31aef6aSopenharmony_ci            The template loader for this environment.
233e31aef6aSopenharmony_ci
234e31aef6aSopenharmony_ci        `cache_size`
235e31aef6aSopenharmony_ci            The size of the cache.  Per default this is ``400`` which means
236e31aef6aSopenharmony_ci            that if more than 400 templates are loaded the loader will clean
237e31aef6aSopenharmony_ci            out the least recently used template.  If the cache size is set to
238e31aef6aSopenharmony_ci            ``0`` templates are recompiled all the time, if the cache size is
239e31aef6aSopenharmony_ci            ``-1`` the cache will not be cleaned.
240e31aef6aSopenharmony_ci
241e31aef6aSopenharmony_ci            .. versionchanged:: 2.8
242e31aef6aSopenharmony_ci               The cache size was increased to 400 from a low 50.
243e31aef6aSopenharmony_ci
244e31aef6aSopenharmony_ci        `auto_reload`
245e31aef6aSopenharmony_ci            Some loaders load templates from locations where the template
246e31aef6aSopenharmony_ci            sources may change (ie: file system or database).  If
247e31aef6aSopenharmony_ci            ``auto_reload`` is set to ``True`` (default) every time a template is
248e31aef6aSopenharmony_ci            requested the loader checks if the source changed and if yes, it
249e31aef6aSopenharmony_ci            will reload the template.  For higher performance it's possible to
250e31aef6aSopenharmony_ci            disable that.
251e31aef6aSopenharmony_ci
252e31aef6aSopenharmony_ci        `bytecode_cache`
253e31aef6aSopenharmony_ci            If set to a bytecode cache object, this object will provide a
254e31aef6aSopenharmony_ci            cache for the internal Jinja bytecode so that templates don't
255e31aef6aSopenharmony_ci            have to be parsed if they were not changed.
256e31aef6aSopenharmony_ci
257e31aef6aSopenharmony_ci            See :ref:`bytecode-cache` for more information.
258e31aef6aSopenharmony_ci
259e31aef6aSopenharmony_ci        `enable_async`
260e31aef6aSopenharmony_ci            If set to true this enables async template execution which
261e31aef6aSopenharmony_ci            allows using async functions and generators.
262e31aef6aSopenharmony_ci    """
263e31aef6aSopenharmony_ci
264e31aef6aSopenharmony_ci    #: if this environment is sandboxed.  Modifying this variable won't make
265e31aef6aSopenharmony_ci    #: the environment sandboxed though.  For a real sandboxed environment
266e31aef6aSopenharmony_ci    #: have a look at jinja2.sandbox.  This flag alone controls the code
267e31aef6aSopenharmony_ci    #: generation by the compiler.
268e31aef6aSopenharmony_ci    sandboxed = False
269e31aef6aSopenharmony_ci
270e31aef6aSopenharmony_ci    #: True if the environment is just an overlay
271e31aef6aSopenharmony_ci    overlayed = False
272e31aef6aSopenharmony_ci
273e31aef6aSopenharmony_ci    #: the environment this environment is linked to if it is an overlay
274e31aef6aSopenharmony_ci    linked_to: t.Optional["Environment"] = None
275e31aef6aSopenharmony_ci
276e31aef6aSopenharmony_ci    #: shared environments have this set to `True`.  A shared environment
277e31aef6aSopenharmony_ci    #: must not be modified
278e31aef6aSopenharmony_ci    shared = False
279e31aef6aSopenharmony_ci
280e31aef6aSopenharmony_ci    #: the class that is used for code generation.  See
281e31aef6aSopenharmony_ci    #: :class:`~jinja2.compiler.CodeGenerator` for more information.
282e31aef6aSopenharmony_ci    code_generator_class: t.Type["CodeGenerator"] = CodeGenerator
283e31aef6aSopenharmony_ci
284e31aef6aSopenharmony_ci    concat = "".join
285e31aef6aSopenharmony_ci
286e31aef6aSopenharmony_ci    #: the context class that is used for templates.  See
287e31aef6aSopenharmony_ci    #: :class:`~jinja2.runtime.Context` for more information.
288e31aef6aSopenharmony_ci    context_class: t.Type[Context] = Context
289e31aef6aSopenharmony_ci
290e31aef6aSopenharmony_ci    template_class: t.Type["Template"]
291e31aef6aSopenharmony_ci
292e31aef6aSopenharmony_ci    def __init__(
293e31aef6aSopenharmony_ci        self,
294e31aef6aSopenharmony_ci        block_start_string: str = BLOCK_START_STRING,
295e31aef6aSopenharmony_ci        block_end_string: str = BLOCK_END_STRING,
296e31aef6aSopenharmony_ci        variable_start_string: str = VARIABLE_START_STRING,
297e31aef6aSopenharmony_ci        variable_end_string: str = VARIABLE_END_STRING,
298e31aef6aSopenharmony_ci        comment_start_string: str = COMMENT_START_STRING,
299e31aef6aSopenharmony_ci        comment_end_string: str = COMMENT_END_STRING,
300e31aef6aSopenharmony_ci        line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX,
301e31aef6aSopenharmony_ci        line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX,
302e31aef6aSopenharmony_ci        trim_blocks: bool = TRIM_BLOCKS,
303e31aef6aSopenharmony_ci        lstrip_blocks: bool = LSTRIP_BLOCKS,
304e31aef6aSopenharmony_ci        newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE,
305e31aef6aSopenharmony_ci        keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE,
306e31aef6aSopenharmony_ci        extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (),
307e31aef6aSopenharmony_ci        optimized: bool = True,
308e31aef6aSopenharmony_ci        undefined: t.Type[Undefined] = Undefined,
309e31aef6aSopenharmony_ci        finalize: t.Optional[t.Callable[..., t.Any]] = None,
310e31aef6aSopenharmony_ci        autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False,
311e31aef6aSopenharmony_ci        loader: t.Optional["BaseLoader"] = None,
312e31aef6aSopenharmony_ci        cache_size: int = 400,
313e31aef6aSopenharmony_ci        auto_reload: bool = True,
314e31aef6aSopenharmony_ci        bytecode_cache: t.Optional["BytecodeCache"] = None,
315e31aef6aSopenharmony_ci        enable_async: bool = False,
316e31aef6aSopenharmony_ci    ):
317e31aef6aSopenharmony_ci        # !!Important notice!!
318e31aef6aSopenharmony_ci        #   The constructor accepts quite a few arguments that should be
319e31aef6aSopenharmony_ci        #   passed by keyword rather than position.  However it's important to
320e31aef6aSopenharmony_ci        #   not change the order of arguments because it's used at least
321e31aef6aSopenharmony_ci        #   internally in those cases:
322e31aef6aSopenharmony_ci        #       -   spontaneous environments (i18n extension and Template)
323e31aef6aSopenharmony_ci        #       -   unittests
324e31aef6aSopenharmony_ci        #   If parameter changes are required only add parameters at the end
325e31aef6aSopenharmony_ci        #   and don't change the arguments (or the defaults!) of the arguments
326e31aef6aSopenharmony_ci        #   existing already.
327e31aef6aSopenharmony_ci
328e31aef6aSopenharmony_ci        # lexer / parser information
329e31aef6aSopenharmony_ci        self.block_start_string = block_start_string
330e31aef6aSopenharmony_ci        self.block_end_string = block_end_string
331e31aef6aSopenharmony_ci        self.variable_start_string = variable_start_string
332e31aef6aSopenharmony_ci        self.variable_end_string = variable_end_string
333e31aef6aSopenharmony_ci        self.comment_start_string = comment_start_string
334e31aef6aSopenharmony_ci        self.comment_end_string = comment_end_string
335e31aef6aSopenharmony_ci        self.line_statement_prefix = line_statement_prefix
336e31aef6aSopenharmony_ci        self.line_comment_prefix = line_comment_prefix
337e31aef6aSopenharmony_ci        self.trim_blocks = trim_blocks
338e31aef6aSopenharmony_ci        self.lstrip_blocks = lstrip_blocks
339e31aef6aSopenharmony_ci        self.newline_sequence = newline_sequence
340e31aef6aSopenharmony_ci        self.keep_trailing_newline = keep_trailing_newline
341e31aef6aSopenharmony_ci
342e31aef6aSopenharmony_ci        # runtime information
343e31aef6aSopenharmony_ci        self.undefined: t.Type[Undefined] = undefined
344e31aef6aSopenharmony_ci        self.optimized = optimized
345e31aef6aSopenharmony_ci        self.finalize = finalize
346e31aef6aSopenharmony_ci        self.autoescape = autoescape
347e31aef6aSopenharmony_ci
348e31aef6aSopenharmony_ci        # defaults
349e31aef6aSopenharmony_ci        self.filters = DEFAULT_FILTERS.copy()
350e31aef6aSopenharmony_ci        self.tests = DEFAULT_TESTS.copy()
351e31aef6aSopenharmony_ci        self.globals = DEFAULT_NAMESPACE.copy()
352e31aef6aSopenharmony_ci
353e31aef6aSopenharmony_ci        # set the loader provided
354e31aef6aSopenharmony_ci        self.loader = loader
355e31aef6aSopenharmony_ci        self.cache = create_cache(cache_size)
356e31aef6aSopenharmony_ci        self.bytecode_cache = bytecode_cache
357e31aef6aSopenharmony_ci        self.auto_reload = auto_reload
358e31aef6aSopenharmony_ci
359e31aef6aSopenharmony_ci        # configurable policies
360e31aef6aSopenharmony_ci        self.policies = DEFAULT_POLICIES.copy()
361e31aef6aSopenharmony_ci
362e31aef6aSopenharmony_ci        # load extensions
363e31aef6aSopenharmony_ci        self.extensions = load_extensions(self, extensions)
364e31aef6aSopenharmony_ci
365e31aef6aSopenharmony_ci        self.is_async = enable_async
366e31aef6aSopenharmony_ci        _environment_config_check(self)
367e31aef6aSopenharmony_ci
368e31aef6aSopenharmony_ci    def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None:
369e31aef6aSopenharmony_ci        """Adds an extension after the environment was created.
370e31aef6aSopenharmony_ci
371e31aef6aSopenharmony_ci        .. versionadded:: 2.5
372e31aef6aSopenharmony_ci        """
373e31aef6aSopenharmony_ci        self.extensions.update(load_extensions(self, [extension]))
374e31aef6aSopenharmony_ci
375e31aef6aSopenharmony_ci    def extend(self, **attributes: t.Any) -> None:
376e31aef6aSopenharmony_ci        """Add the items to the instance of the environment if they do not exist
377e31aef6aSopenharmony_ci        yet.  This is used by :ref:`extensions <writing-extensions>` to register
378e31aef6aSopenharmony_ci        callbacks and configuration values without breaking inheritance.
379e31aef6aSopenharmony_ci        """
380e31aef6aSopenharmony_ci        for key, value in attributes.items():
381e31aef6aSopenharmony_ci            if not hasattr(self, key):
382e31aef6aSopenharmony_ci                setattr(self, key, value)
383e31aef6aSopenharmony_ci
384e31aef6aSopenharmony_ci    def overlay(
385e31aef6aSopenharmony_ci        self,
386e31aef6aSopenharmony_ci        block_start_string: str = missing,
387e31aef6aSopenharmony_ci        block_end_string: str = missing,
388e31aef6aSopenharmony_ci        variable_start_string: str = missing,
389e31aef6aSopenharmony_ci        variable_end_string: str = missing,
390e31aef6aSopenharmony_ci        comment_start_string: str = missing,
391e31aef6aSopenharmony_ci        comment_end_string: str = missing,
392e31aef6aSopenharmony_ci        line_statement_prefix: t.Optional[str] = missing,
393e31aef6aSopenharmony_ci        line_comment_prefix: t.Optional[str] = missing,
394e31aef6aSopenharmony_ci        trim_blocks: bool = missing,
395e31aef6aSopenharmony_ci        lstrip_blocks: bool = missing,
396e31aef6aSopenharmony_ci        newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing,
397e31aef6aSopenharmony_ci        keep_trailing_newline: bool = missing,
398e31aef6aSopenharmony_ci        extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing,
399e31aef6aSopenharmony_ci        optimized: bool = missing,
400e31aef6aSopenharmony_ci        undefined: t.Type[Undefined] = missing,
401e31aef6aSopenharmony_ci        finalize: t.Optional[t.Callable[..., t.Any]] = missing,
402e31aef6aSopenharmony_ci        autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing,
403e31aef6aSopenharmony_ci        loader: t.Optional["BaseLoader"] = missing,
404e31aef6aSopenharmony_ci        cache_size: int = missing,
405e31aef6aSopenharmony_ci        auto_reload: bool = missing,
406e31aef6aSopenharmony_ci        bytecode_cache: t.Optional["BytecodeCache"] = missing,
407e31aef6aSopenharmony_ci        enable_async: bool = False,
408e31aef6aSopenharmony_ci    ) -> "Environment":
409e31aef6aSopenharmony_ci        """Create a new overlay environment that shares all the data with the
410e31aef6aSopenharmony_ci        current environment except for cache and the overridden attributes.
411e31aef6aSopenharmony_ci        Extensions cannot be removed for an overlayed environment.  An overlayed
412e31aef6aSopenharmony_ci        environment automatically gets all the extensions of the environment it
413e31aef6aSopenharmony_ci        is linked to plus optional extra extensions.
414e31aef6aSopenharmony_ci
415e31aef6aSopenharmony_ci        Creating overlays should happen after the initial environment was set
416e31aef6aSopenharmony_ci        up completely.  Not all attributes are truly linked, some are just
417e31aef6aSopenharmony_ci        copied over so modifications on the original environment may not shine
418e31aef6aSopenharmony_ci        through.
419e31aef6aSopenharmony_ci
420e31aef6aSopenharmony_ci        .. versionchanged:: 3.1.2
421e31aef6aSopenharmony_ci            Added the ``newline_sequence``,, ``keep_trailing_newline``,
422e31aef6aSopenharmony_ci            and ``enable_async`` parameters to match ``__init__``.
423e31aef6aSopenharmony_ci        """
424e31aef6aSopenharmony_ci        args = dict(locals())
425e31aef6aSopenharmony_ci        del args["self"], args["cache_size"], args["extensions"], args["enable_async"]
426e31aef6aSopenharmony_ci
427e31aef6aSopenharmony_ci        rv = object.__new__(self.__class__)
428e31aef6aSopenharmony_ci        rv.__dict__.update(self.__dict__)
429e31aef6aSopenharmony_ci        rv.overlayed = True
430e31aef6aSopenharmony_ci        rv.linked_to = self
431e31aef6aSopenharmony_ci
432e31aef6aSopenharmony_ci        for key, value in args.items():
433e31aef6aSopenharmony_ci            if value is not missing:
434e31aef6aSopenharmony_ci                setattr(rv, key, value)
435e31aef6aSopenharmony_ci
436e31aef6aSopenharmony_ci        if cache_size is not missing:
437e31aef6aSopenharmony_ci            rv.cache = create_cache(cache_size)
438e31aef6aSopenharmony_ci        else:
439e31aef6aSopenharmony_ci            rv.cache = copy_cache(self.cache)
440e31aef6aSopenharmony_ci
441e31aef6aSopenharmony_ci        rv.extensions = {}
442e31aef6aSopenharmony_ci        for key, value in self.extensions.items():
443e31aef6aSopenharmony_ci            rv.extensions[key] = value.bind(rv)
444e31aef6aSopenharmony_ci        if extensions is not missing:
445e31aef6aSopenharmony_ci            rv.extensions.update(load_extensions(rv, extensions))
446e31aef6aSopenharmony_ci
447e31aef6aSopenharmony_ci        if enable_async is not missing:
448e31aef6aSopenharmony_ci            rv.is_async = enable_async
449e31aef6aSopenharmony_ci
450e31aef6aSopenharmony_ci        return _environment_config_check(rv)
451e31aef6aSopenharmony_ci
452e31aef6aSopenharmony_ci    @property
453e31aef6aSopenharmony_ci    def lexer(self) -> Lexer:
454e31aef6aSopenharmony_ci        """The lexer for this environment."""
455e31aef6aSopenharmony_ci        return get_lexer(self)
456e31aef6aSopenharmony_ci
457e31aef6aSopenharmony_ci    def iter_extensions(self) -> t.Iterator["Extension"]:
458e31aef6aSopenharmony_ci        """Iterates over the extensions by priority."""
459e31aef6aSopenharmony_ci        return iter(sorted(self.extensions.values(), key=lambda x: x.priority))
460e31aef6aSopenharmony_ci
461e31aef6aSopenharmony_ci    def getitem(
462e31aef6aSopenharmony_ci        self, obj: t.Any, argument: t.Union[str, t.Any]
463e31aef6aSopenharmony_ci    ) -> t.Union[t.Any, Undefined]:
464e31aef6aSopenharmony_ci        """Get an item or attribute of an object but prefer the item."""
465e31aef6aSopenharmony_ci        try:
466e31aef6aSopenharmony_ci            return obj[argument]
467e31aef6aSopenharmony_ci        except (AttributeError, TypeError, LookupError):
468e31aef6aSopenharmony_ci            if isinstance(argument, str):
469e31aef6aSopenharmony_ci                try:
470e31aef6aSopenharmony_ci                    attr = str(argument)
471e31aef6aSopenharmony_ci                except Exception:
472e31aef6aSopenharmony_ci                    pass
473e31aef6aSopenharmony_ci                else:
474e31aef6aSopenharmony_ci                    try:
475e31aef6aSopenharmony_ci                        return getattr(obj, attr)
476e31aef6aSopenharmony_ci                    except AttributeError:
477e31aef6aSopenharmony_ci                        pass
478e31aef6aSopenharmony_ci            return self.undefined(obj=obj, name=argument)
479e31aef6aSopenharmony_ci
480e31aef6aSopenharmony_ci    def getattr(self, obj: t.Any, attribute: str) -> t.Any:
481e31aef6aSopenharmony_ci        """Get an item or attribute of an object but prefer the attribute.
482e31aef6aSopenharmony_ci        Unlike :meth:`getitem` the attribute *must* be a string.
483e31aef6aSopenharmony_ci        """
484e31aef6aSopenharmony_ci        try:
485e31aef6aSopenharmony_ci            return getattr(obj, attribute)
486e31aef6aSopenharmony_ci        except AttributeError:
487e31aef6aSopenharmony_ci            pass
488e31aef6aSopenharmony_ci        try:
489e31aef6aSopenharmony_ci            return obj[attribute]
490e31aef6aSopenharmony_ci        except (TypeError, LookupError, AttributeError):
491e31aef6aSopenharmony_ci            return self.undefined(obj=obj, name=attribute)
492e31aef6aSopenharmony_ci
493e31aef6aSopenharmony_ci    def _filter_test_common(
494e31aef6aSopenharmony_ci        self,
495e31aef6aSopenharmony_ci        name: t.Union[str, Undefined],
496e31aef6aSopenharmony_ci        value: t.Any,
497e31aef6aSopenharmony_ci        args: t.Optional[t.Sequence[t.Any]],
498e31aef6aSopenharmony_ci        kwargs: t.Optional[t.Mapping[str, t.Any]],
499e31aef6aSopenharmony_ci        context: t.Optional[Context],
500e31aef6aSopenharmony_ci        eval_ctx: t.Optional[EvalContext],
501e31aef6aSopenharmony_ci        is_filter: bool,
502e31aef6aSopenharmony_ci    ) -> t.Any:
503e31aef6aSopenharmony_ci        if is_filter:
504e31aef6aSopenharmony_ci            env_map = self.filters
505e31aef6aSopenharmony_ci            type_name = "filter"
506e31aef6aSopenharmony_ci        else:
507e31aef6aSopenharmony_ci            env_map = self.tests
508e31aef6aSopenharmony_ci            type_name = "test"
509e31aef6aSopenharmony_ci
510e31aef6aSopenharmony_ci        func = env_map.get(name)  # type: ignore
511e31aef6aSopenharmony_ci
512e31aef6aSopenharmony_ci        if func is None:
513e31aef6aSopenharmony_ci            msg = f"No {type_name} named {name!r}."
514e31aef6aSopenharmony_ci
515e31aef6aSopenharmony_ci            if isinstance(name, Undefined):
516e31aef6aSopenharmony_ci                try:
517e31aef6aSopenharmony_ci                    name._fail_with_undefined_error()
518e31aef6aSopenharmony_ci                except Exception as e:
519e31aef6aSopenharmony_ci                    msg = f"{msg} ({e}; did you forget to quote the callable name?)"
520e31aef6aSopenharmony_ci
521e31aef6aSopenharmony_ci            raise TemplateRuntimeError(msg)
522e31aef6aSopenharmony_ci
523e31aef6aSopenharmony_ci        args = [value, *(args if args is not None else ())]
524e31aef6aSopenharmony_ci        kwargs = kwargs if kwargs is not None else {}
525e31aef6aSopenharmony_ci        pass_arg = _PassArg.from_obj(func)
526e31aef6aSopenharmony_ci
527e31aef6aSopenharmony_ci        if pass_arg is _PassArg.context:
528e31aef6aSopenharmony_ci            if context is None:
529e31aef6aSopenharmony_ci                raise TemplateRuntimeError(
530e31aef6aSopenharmony_ci                    f"Attempted to invoke a context {type_name} without context."
531e31aef6aSopenharmony_ci                )
532e31aef6aSopenharmony_ci
533e31aef6aSopenharmony_ci            args.insert(0, context)
534e31aef6aSopenharmony_ci        elif pass_arg is _PassArg.eval_context:
535e31aef6aSopenharmony_ci            if eval_ctx is None:
536e31aef6aSopenharmony_ci                if context is not None:
537e31aef6aSopenharmony_ci                    eval_ctx = context.eval_ctx
538e31aef6aSopenharmony_ci                else:
539e31aef6aSopenharmony_ci                    eval_ctx = EvalContext(self)
540e31aef6aSopenharmony_ci
541e31aef6aSopenharmony_ci            args.insert(0, eval_ctx)
542e31aef6aSopenharmony_ci        elif pass_arg is _PassArg.environment:
543e31aef6aSopenharmony_ci            args.insert(0, self)
544e31aef6aSopenharmony_ci
545e31aef6aSopenharmony_ci        return func(*args, **kwargs)
546e31aef6aSopenharmony_ci
547e31aef6aSopenharmony_ci    def call_filter(
548e31aef6aSopenharmony_ci        self,
549e31aef6aSopenharmony_ci        name: str,
550e31aef6aSopenharmony_ci        value: t.Any,
551e31aef6aSopenharmony_ci        args: t.Optional[t.Sequence[t.Any]] = None,
552e31aef6aSopenharmony_ci        kwargs: t.Optional[t.Mapping[str, t.Any]] = None,
553e31aef6aSopenharmony_ci        context: t.Optional[Context] = None,
554e31aef6aSopenharmony_ci        eval_ctx: t.Optional[EvalContext] = None,
555e31aef6aSopenharmony_ci    ) -> t.Any:
556e31aef6aSopenharmony_ci        """Invoke a filter on a value the same way the compiler does.
557e31aef6aSopenharmony_ci
558e31aef6aSopenharmony_ci        This might return a coroutine if the filter is running from an
559e31aef6aSopenharmony_ci        environment in async mode and the filter supports async
560e31aef6aSopenharmony_ci        execution. It's your responsibility to await this if needed.
561e31aef6aSopenharmony_ci
562e31aef6aSopenharmony_ci        .. versionadded:: 2.7
563e31aef6aSopenharmony_ci        """
564e31aef6aSopenharmony_ci        return self._filter_test_common(
565e31aef6aSopenharmony_ci            name, value, args, kwargs, context, eval_ctx, True
566e31aef6aSopenharmony_ci        )
567e31aef6aSopenharmony_ci
568e31aef6aSopenharmony_ci    def call_test(
569e31aef6aSopenharmony_ci        self,
570e31aef6aSopenharmony_ci        name: str,
571e31aef6aSopenharmony_ci        value: t.Any,
572e31aef6aSopenharmony_ci        args: t.Optional[t.Sequence[t.Any]] = None,
573e31aef6aSopenharmony_ci        kwargs: t.Optional[t.Mapping[str, t.Any]] = None,
574e31aef6aSopenharmony_ci        context: t.Optional[Context] = None,
575e31aef6aSopenharmony_ci        eval_ctx: t.Optional[EvalContext] = None,
576e31aef6aSopenharmony_ci    ) -> t.Any:
577e31aef6aSopenharmony_ci        """Invoke a test on a value the same way the compiler does.
578e31aef6aSopenharmony_ci
579e31aef6aSopenharmony_ci        This might return a coroutine if the test is running from an
580e31aef6aSopenharmony_ci        environment in async mode and the test supports async execution.
581e31aef6aSopenharmony_ci        It's your responsibility to await this if needed.
582e31aef6aSopenharmony_ci
583e31aef6aSopenharmony_ci        .. versionchanged:: 3.0
584e31aef6aSopenharmony_ci            Tests support ``@pass_context``, etc. decorators. Added
585e31aef6aSopenharmony_ci            the ``context`` and ``eval_ctx`` parameters.
586e31aef6aSopenharmony_ci
587e31aef6aSopenharmony_ci        .. versionadded:: 2.7
588e31aef6aSopenharmony_ci        """
589e31aef6aSopenharmony_ci        return self._filter_test_common(
590e31aef6aSopenharmony_ci            name, value, args, kwargs, context, eval_ctx, False
591e31aef6aSopenharmony_ci        )
592e31aef6aSopenharmony_ci
593e31aef6aSopenharmony_ci    @internalcode
594e31aef6aSopenharmony_ci    def parse(
595e31aef6aSopenharmony_ci        self,
596e31aef6aSopenharmony_ci        source: str,
597e31aef6aSopenharmony_ci        name: t.Optional[str] = None,
598e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
599e31aef6aSopenharmony_ci    ) -> nodes.Template:
600e31aef6aSopenharmony_ci        """Parse the sourcecode and return the abstract syntax tree.  This
601e31aef6aSopenharmony_ci        tree of nodes is used by the compiler to convert the template into
602e31aef6aSopenharmony_ci        executable source- or bytecode.  This is useful for debugging or to
603e31aef6aSopenharmony_ci        extract information from templates.
604e31aef6aSopenharmony_ci
605e31aef6aSopenharmony_ci        If you are :ref:`developing Jinja extensions <writing-extensions>`
606e31aef6aSopenharmony_ci        this gives you a good overview of the node tree generated.
607e31aef6aSopenharmony_ci        """
608e31aef6aSopenharmony_ci        try:
609e31aef6aSopenharmony_ci            return self._parse(source, name, filename)
610e31aef6aSopenharmony_ci        except TemplateSyntaxError:
611e31aef6aSopenharmony_ci            self.handle_exception(source=source)
612e31aef6aSopenharmony_ci
613e31aef6aSopenharmony_ci    def _parse(
614e31aef6aSopenharmony_ci        self, source: str, name: t.Optional[str], filename: t.Optional[str]
615e31aef6aSopenharmony_ci    ) -> nodes.Template:
616e31aef6aSopenharmony_ci        """Internal parsing function used by `parse` and `compile`."""
617e31aef6aSopenharmony_ci        return Parser(self, source, name, filename).parse()
618e31aef6aSopenharmony_ci
619e31aef6aSopenharmony_ci    def lex(
620e31aef6aSopenharmony_ci        self,
621e31aef6aSopenharmony_ci        source: str,
622e31aef6aSopenharmony_ci        name: t.Optional[str] = None,
623e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
624e31aef6aSopenharmony_ci    ) -> t.Iterator[t.Tuple[int, str, str]]:
625e31aef6aSopenharmony_ci        """Lex the given sourcecode and return a generator that yields
626e31aef6aSopenharmony_ci        tokens as tuples in the form ``(lineno, token_type, value)``.
627e31aef6aSopenharmony_ci        This can be useful for :ref:`extension development <writing-extensions>`
628e31aef6aSopenharmony_ci        and debugging templates.
629e31aef6aSopenharmony_ci
630e31aef6aSopenharmony_ci        This does not perform preprocessing.  If you want the preprocessing
631e31aef6aSopenharmony_ci        of the extensions to be applied you have to filter source through
632e31aef6aSopenharmony_ci        the :meth:`preprocess` method.
633e31aef6aSopenharmony_ci        """
634e31aef6aSopenharmony_ci        source = str(source)
635e31aef6aSopenharmony_ci        try:
636e31aef6aSopenharmony_ci            return self.lexer.tokeniter(source, name, filename)
637e31aef6aSopenharmony_ci        except TemplateSyntaxError:
638e31aef6aSopenharmony_ci            self.handle_exception(source=source)
639e31aef6aSopenharmony_ci
640e31aef6aSopenharmony_ci    def preprocess(
641e31aef6aSopenharmony_ci        self,
642e31aef6aSopenharmony_ci        source: str,
643e31aef6aSopenharmony_ci        name: t.Optional[str] = None,
644e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
645e31aef6aSopenharmony_ci    ) -> str:
646e31aef6aSopenharmony_ci        """Preprocesses the source with all extensions.  This is automatically
647e31aef6aSopenharmony_ci        called for all parsing and compiling methods but *not* for :meth:`lex`
648e31aef6aSopenharmony_ci        because there you usually only want the actual source tokenized.
649e31aef6aSopenharmony_ci        """
650e31aef6aSopenharmony_ci        return reduce(
651e31aef6aSopenharmony_ci            lambda s, e: e.preprocess(s, name, filename),
652e31aef6aSopenharmony_ci            self.iter_extensions(),
653e31aef6aSopenharmony_ci            str(source),
654e31aef6aSopenharmony_ci        )
655e31aef6aSopenharmony_ci
656e31aef6aSopenharmony_ci    def _tokenize(
657e31aef6aSopenharmony_ci        self,
658e31aef6aSopenharmony_ci        source: str,
659e31aef6aSopenharmony_ci        name: t.Optional[str],
660e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
661e31aef6aSopenharmony_ci        state: t.Optional[str] = None,
662e31aef6aSopenharmony_ci    ) -> TokenStream:
663e31aef6aSopenharmony_ci        """Called by the parser to do the preprocessing and filtering
664e31aef6aSopenharmony_ci        for all the extensions.  Returns a :class:`~jinja2.lexer.TokenStream`.
665e31aef6aSopenharmony_ci        """
666e31aef6aSopenharmony_ci        source = self.preprocess(source, name, filename)
667e31aef6aSopenharmony_ci        stream = self.lexer.tokenize(source, name, filename, state)
668e31aef6aSopenharmony_ci
669e31aef6aSopenharmony_ci        for ext in self.iter_extensions():
670e31aef6aSopenharmony_ci            stream = ext.filter_stream(stream)  # type: ignore
671e31aef6aSopenharmony_ci
672e31aef6aSopenharmony_ci            if not isinstance(stream, TokenStream):
673e31aef6aSopenharmony_ci                stream = TokenStream(stream, name, filename)  # type: ignore
674e31aef6aSopenharmony_ci
675e31aef6aSopenharmony_ci        return stream
676e31aef6aSopenharmony_ci
677e31aef6aSopenharmony_ci    def _generate(
678e31aef6aSopenharmony_ci        self,
679e31aef6aSopenharmony_ci        source: nodes.Template,
680e31aef6aSopenharmony_ci        name: t.Optional[str],
681e31aef6aSopenharmony_ci        filename: t.Optional[str],
682e31aef6aSopenharmony_ci        defer_init: bool = False,
683e31aef6aSopenharmony_ci    ) -> str:
684e31aef6aSopenharmony_ci        """Internal hook that can be overridden to hook a different generate
685e31aef6aSopenharmony_ci        method in.
686e31aef6aSopenharmony_ci
687e31aef6aSopenharmony_ci        .. versionadded:: 2.5
688e31aef6aSopenharmony_ci        """
689e31aef6aSopenharmony_ci        return generate(  # type: ignore
690e31aef6aSopenharmony_ci            source,
691e31aef6aSopenharmony_ci            self,
692e31aef6aSopenharmony_ci            name,
693e31aef6aSopenharmony_ci            filename,
694e31aef6aSopenharmony_ci            defer_init=defer_init,
695e31aef6aSopenharmony_ci            optimized=self.optimized,
696e31aef6aSopenharmony_ci        )
697e31aef6aSopenharmony_ci
698e31aef6aSopenharmony_ci    def _compile(self, source: str, filename: str) -> CodeType:
699e31aef6aSopenharmony_ci        """Internal hook that can be overridden to hook a different compile
700e31aef6aSopenharmony_ci        method in.
701e31aef6aSopenharmony_ci
702e31aef6aSopenharmony_ci        .. versionadded:: 2.5
703e31aef6aSopenharmony_ci        """
704e31aef6aSopenharmony_ci        return compile(source, filename, "exec")
705e31aef6aSopenharmony_ci
706e31aef6aSopenharmony_ci    @typing.overload
707e31aef6aSopenharmony_ci    def compile(  # type: ignore
708e31aef6aSopenharmony_ci        self,
709e31aef6aSopenharmony_ci        source: t.Union[str, nodes.Template],
710e31aef6aSopenharmony_ci        name: t.Optional[str] = None,
711e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
712e31aef6aSopenharmony_ci        raw: "te.Literal[False]" = False,
713e31aef6aSopenharmony_ci        defer_init: bool = False,
714e31aef6aSopenharmony_ci    ) -> CodeType:
715e31aef6aSopenharmony_ci        ...
716e31aef6aSopenharmony_ci
717e31aef6aSopenharmony_ci    @typing.overload
718e31aef6aSopenharmony_ci    def compile(
719e31aef6aSopenharmony_ci        self,
720e31aef6aSopenharmony_ci        source: t.Union[str, nodes.Template],
721e31aef6aSopenharmony_ci        name: t.Optional[str] = None,
722e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
723e31aef6aSopenharmony_ci        raw: "te.Literal[True]" = ...,
724e31aef6aSopenharmony_ci        defer_init: bool = False,
725e31aef6aSopenharmony_ci    ) -> str:
726e31aef6aSopenharmony_ci        ...
727e31aef6aSopenharmony_ci
728e31aef6aSopenharmony_ci    @internalcode
729e31aef6aSopenharmony_ci    def compile(
730e31aef6aSopenharmony_ci        self,
731e31aef6aSopenharmony_ci        source: t.Union[str, nodes.Template],
732e31aef6aSopenharmony_ci        name: t.Optional[str] = None,
733e31aef6aSopenharmony_ci        filename: t.Optional[str] = None,
734e31aef6aSopenharmony_ci        raw: bool = False,
735e31aef6aSopenharmony_ci        defer_init: bool = False,
736e31aef6aSopenharmony_ci    ) -> t.Union[str, CodeType]:
737e31aef6aSopenharmony_ci        """Compile a node or template source code.  The `name` parameter is
738e31aef6aSopenharmony_ci        the load name of the template after it was joined using
739e31aef6aSopenharmony_ci        :meth:`join_path` if necessary, not the filename on the file system.
740e31aef6aSopenharmony_ci        the `filename` parameter is the estimated filename of the template on
741e31aef6aSopenharmony_ci        the file system.  If the template came from a database or memory this
742e31aef6aSopenharmony_ci        can be omitted.
743e31aef6aSopenharmony_ci
744e31aef6aSopenharmony_ci        The return value of this method is a python code object.  If the `raw`
745e31aef6aSopenharmony_ci        parameter is `True` the return value will be a string with python
746e31aef6aSopenharmony_ci        code equivalent to the bytecode returned otherwise.  This method is
747e31aef6aSopenharmony_ci        mainly used internally.
748e31aef6aSopenharmony_ci
749e31aef6aSopenharmony_ci        `defer_init` is use internally to aid the module code generator.  This
750e31aef6aSopenharmony_ci        causes the generated code to be able to import without the global
751e31aef6aSopenharmony_ci        environment variable to be set.
752e31aef6aSopenharmony_ci
753e31aef6aSopenharmony_ci        .. versionadded:: 2.4
754e31aef6aSopenharmony_ci           `defer_init` parameter added.
755e31aef6aSopenharmony_ci        """
756e31aef6aSopenharmony_ci        source_hint = None
757e31aef6aSopenharmony_ci        try:
758e31aef6aSopenharmony_ci            if isinstance(source, str):
759e31aef6aSopenharmony_ci                source_hint = source
760e31aef6aSopenharmony_ci                source = self._parse(source, name, filename)
761e31aef6aSopenharmony_ci            source = self._generate(source, name, filename, defer_init=defer_init)
762e31aef6aSopenharmony_ci            if raw:
763e31aef6aSopenharmony_ci                return source
764e31aef6aSopenharmony_ci            if filename is None:
765e31aef6aSopenharmony_ci                filename = "<template>"
766e31aef6aSopenharmony_ci            return self._compile(source, filename)
767e31aef6aSopenharmony_ci        except TemplateSyntaxError:
768e31aef6aSopenharmony_ci            self.handle_exception(source=source_hint)
769e31aef6aSopenharmony_ci
770e31aef6aSopenharmony_ci    def compile_expression(
771e31aef6aSopenharmony_ci        self, source: str, undefined_to_none: bool = True
772e31aef6aSopenharmony_ci    ) -> "TemplateExpression":
773e31aef6aSopenharmony_ci        """A handy helper method that returns a callable that accepts keyword
774e31aef6aSopenharmony_ci        arguments that appear as variables in the expression.  If called it
775e31aef6aSopenharmony_ci        returns the result of the expression.
776e31aef6aSopenharmony_ci
777e31aef6aSopenharmony_ci        This is useful if applications want to use the same rules as Jinja
778e31aef6aSopenharmony_ci        in template "configuration files" or similar situations.
779e31aef6aSopenharmony_ci
780e31aef6aSopenharmony_ci        Example usage:
781e31aef6aSopenharmony_ci
782e31aef6aSopenharmony_ci        >>> env = Environment()
783e31aef6aSopenharmony_ci        >>> expr = env.compile_expression('foo == 42')
784e31aef6aSopenharmony_ci        >>> expr(foo=23)
785e31aef6aSopenharmony_ci        False
786e31aef6aSopenharmony_ci        >>> expr(foo=42)
787e31aef6aSopenharmony_ci        True
788e31aef6aSopenharmony_ci
789e31aef6aSopenharmony_ci        Per default the return value is converted to `None` if the
790e31aef6aSopenharmony_ci        expression returns an undefined value.  This can be changed
791e31aef6aSopenharmony_ci        by setting `undefined_to_none` to `False`.
792e31aef6aSopenharmony_ci
793e31aef6aSopenharmony_ci        >>> env.compile_expression('var')() is None
794e31aef6aSopenharmony_ci        True
795e31aef6aSopenharmony_ci        >>> env.compile_expression('var', undefined_to_none=False)()
796e31aef6aSopenharmony_ci        Undefined
797e31aef6aSopenharmony_ci
798e31aef6aSopenharmony_ci        .. versionadded:: 2.1
799e31aef6aSopenharmony_ci        """
800e31aef6aSopenharmony_ci        parser = Parser(self, source, state="variable")
801e31aef6aSopenharmony_ci        try:
802e31aef6aSopenharmony_ci            expr = parser.parse_expression()
803e31aef6aSopenharmony_ci            if not parser.stream.eos:
804e31aef6aSopenharmony_ci                raise TemplateSyntaxError(
805e31aef6aSopenharmony_ci                    "chunk after expression", parser.stream.current.lineno, None, None
806e31aef6aSopenharmony_ci                )
807e31aef6aSopenharmony_ci            expr.set_environment(self)
808e31aef6aSopenharmony_ci        except TemplateSyntaxError:
809e31aef6aSopenharmony_ci            self.handle_exception(source=source)
810e31aef6aSopenharmony_ci
811e31aef6aSopenharmony_ci        body = [nodes.Assign(nodes.Name("result", "store"), expr, lineno=1)]
812e31aef6aSopenharmony_ci        template = self.from_string(nodes.Template(body, lineno=1))
813e31aef6aSopenharmony_ci        return TemplateExpression(template, undefined_to_none)
814e31aef6aSopenharmony_ci
815e31aef6aSopenharmony_ci    def compile_templates(
816e31aef6aSopenharmony_ci        self,
817e31aef6aSopenharmony_ci        target: t.Union[str, os.PathLike],
818e31aef6aSopenharmony_ci        extensions: t.Optional[t.Collection[str]] = None,
819e31aef6aSopenharmony_ci        filter_func: t.Optional[t.Callable[[str], bool]] = None,
820e31aef6aSopenharmony_ci        zip: t.Optional[str] = "deflated",
821e31aef6aSopenharmony_ci        log_function: t.Optional[t.Callable[[str], None]] = None,
822e31aef6aSopenharmony_ci        ignore_errors: bool = True,
823e31aef6aSopenharmony_ci    ) -> None:
824e31aef6aSopenharmony_ci        """Finds all the templates the loader can find, compiles them
825e31aef6aSopenharmony_ci        and stores them in `target`.  If `zip` is `None`, instead of in a
826e31aef6aSopenharmony_ci        zipfile, the templates will be stored in a directory.
827e31aef6aSopenharmony_ci        By default a deflate zip algorithm is used. To switch to
828e31aef6aSopenharmony_ci        the stored algorithm, `zip` can be set to ``'stored'``.
829e31aef6aSopenharmony_ci
830e31aef6aSopenharmony_ci        `extensions` and `filter_func` are passed to :meth:`list_templates`.
831e31aef6aSopenharmony_ci        Each template returned will be compiled to the target folder or
832e31aef6aSopenharmony_ci        zipfile.
833e31aef6aSopenharmony_ci
834e31aef6aSopenharmony_ci        By default template compilation errors are ignored.  In case a
835e31aef6aSopenharmony_ci        log function is provided, errors are logged.  If you want template
836e31aef6aSopenharmony_ci        syntax errors to abort the compilation you can set `ignore_errors`
837e31aef6aSopenharmony_ci        to `False` and you will get an exception on syntax errors.
838e31aef6aSopenharmony_ci
839e31aef6aSopenharmony_ci        .. versionadded:: 2.4
840e31aef6aSopenharmony_ci        """
841e31aef6aSopenharmony_ci        from .loaders import ModuleLoader
842e31aef6aSopenharmony_ci
843e31aef6aSopenharmony_ci        if log_function is None:
844e31aef6aSopenharmony_ci
845e31aef6aSopenharmony_ci            def log_function(x: str) -> None:
846e31aef6aSopenharmony_ci                pass
847e31aef6aSopenharmony_ci
848e31aef6aSopenharmony_ci        assert log_function is not None
849e31aef6aSopenharmony_ci        assert self.loader is not None, "No loader configured."
850e31aef6aSopenharmony_ci
851e31aef6aSopenharmony_ci        def write_file(filename: str, data: str) -> None:
852e31aef6aSopenharmony_ci            if zip:
853e31aef6aSopenharmony_ci                info = ZipInfo(filename)
854e31aef6aSopenharmony_ci                info.external_attr = 0o755 << 16
855e31aef6aSopenharmony_ci                zip_file.writestr(info, data)
856e31aef6aSopenharmony_ci            else:
857e31aef6aSopenharmony_ci                with open(os.path.join(target, filename), "wb") as f:
858e31aef6aSopenharmony_ci                    f.write(data.encode("utf8"))
859e31aef6aSopenharmony_ci
860e31aef6aSopenharmony_ci        if zip is not None:
861e31aef6aSopenharmony_ci            from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
862e31aef6aSopenharmony_ci
863e31aef6aSopenharmony_ci            zip_file = ZipFile(
864e31aef6aSopenharmony_ci                target, "w", dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip]
865e31aef6aSopenharmony_ci            )
866e31aef6aSopenharmony_ci            log_function(f"Compiling into Zip archive {target!r}")
867e31aef6aSopenharmony_ci        else:
868e31aef6aSopenharmony_ci            if not os.path.isdir(target):
869e31aef6aSopenharmony_ci                os.makedirs(target)
870e31aef6aSopenharmony_ci            log_function(f"Compiling into folder {target!r}")
871e31aef6aSopenharmony_ci
872e31aef6aSopenharmony_ci        try:
873e31aef6aSopenharmony_ci            for name in self.list_templates(extensions, filter_func):
874e31aef6aSopenharmony_ci                source, filename, _ = self.loader.get_source(self, name)
875e31aef6aSopenharmony_ci                try:
876e31aef6aSopenharmony_ci                    code = self.compile(source, name, filename, True, True)
877e31aef6aSopenharmony_ci                except TemplateSyntaxError as e:
878e31aef6aSopenharmony_ci                    if not ignore_errors:
879e31aef6aSopenharmony_ci                        raise
880e31aef6aSopenharmony_ci                    log_function(f'Could not compile "{name}": {e}')
881e31aef6aSopenharmony_ci                    continue
882e31aef6aSopenharmony_ci
883e31aef6aSopenharmony_ci                filename = ModuleLoader.get_module_filename(name)
884e31aef6aSopenharmony_ci
885e31aef6aSopenharmony_ci                write_file(filename, code)
886e31aef6aSopenharmony_ci                log_function(f'Compiled "{name}" as {filename}')
887e31aef6aSopenharmony_ci        finally:
888e31aef6aSopenharmony_ci            if zip:
889e31aef6aSopenharmony_ci                zip_file.close()
890e31aef6aSopenharmony_ci
891e31aef6aSopenharmony_ci        log_function("Finished compiling templates")
892e31aef6aSopenharmony_ci
893e31aef6aSopenharmony_ci    def list_templates(
894e31aef6aSopenharmony_ci        self,
895e31aef6aSopenharmony_ci        extensions: t.Optional[t.Collection[str]] = None,
896e31aef6aSopenharmony_ci        filter_func: t.Optional[t.Callable[[str], bool]] = None,
897e31aef6aSopenharmony_ci    ) -> t.List[str]:
898e31aef6aSopenharmony_ci        """Returns a list of templates for this environment.  This requires
899e31aef6aSopenharmony_ci        that the loader supports the loader's
900e31aef6aSopenharmony_ci        :meth:`~BaseLoader.list_templates` method.
901e31aef6aSopenharmony_ci
902e31aef6aSopenharmony_ci        If there are other files in the template folder besides the
903e31aef6aSopenharmony_ci        actual templates, the returned list can be filtered.  There are two
904e31aef6aSopenharmony_ci        ways: either `extensions` is set to a list of file extensions for
905e31aef6aSopenharmony_ci        templates, or a `filter_func` can be provided which is a callable that
906e31aef6aSopenharmony_ci        is passed a template name and should return `True` if it should end up
907e31aef6aSopenharmony_ci        in the result list.
908e31aef6aSopenharmony_ci
909e31aef6aSopenharmony_ci        If the loader does not support that, a :exc:`TypeError` is raised.
910e31aef6aSopenharmony_ci
911e31aef6aSopenharmony_ci        .. versionadded:: 2.4
912e31aef6aSopenharmony_ci        """
913e31aef6aSopenharmony_ci        assert self.loader is not None, "No loader configured."
914e31aef6aSopenharmony_ci        names = self.loader.list_templates()
915e31aef6aSopenharmony_ci
916e31aef6aSopenharmony_ci        if extensions is not None:
917e31aef6aSopenharmony_ci            if filter_func is not None:
918e31aef6aSopenharmony_ci                raise TypeError(
919e31aef6aSopenharmony_ci                    "either extensions or filter_func can be passed, but not both"
920e31aef6aSopenharmony_ci                )
921e31aef6aSopenharmony_ci
922e31aef6aSopenharmony_ci            def filter_func(x: str) -> bool:
923e31aef6aSopenharmony_ci                return "." in x and x.rsplit(".", 1)[1] in extensions
924e31aef6aSopenharmony_ci
925e31aef6aSopenharmony_ci        if filter_func is not None:
926e31aef6aSopenharmony_ci            names = [name for name in names if filter_func(name)]
927e31aef6aSopenharmony_ci
928e31aef6aSopenharmony_ci        return names
929e31aef6aSopenharmony_ci
930e31aef6aSopenharmony_ci    def handle_exception(self, source: t.Optional[str] = None) -> "te.NoReturn":
931e31aef6aSopenharmony_ci        """Exception handling helper.  This is used internally to either raise
932e31aef6aSopenharmony_ci        rewritten exceptions or return a rendered traceback for the template.
933e31aef6aSopenharmony_ci        """
934e31aef6aSopenharmony_ci        from .debug import rewrite_traceback_stack
935e31aef6aSopenharmony_ci
936e31aef6aSopenharmony_ci        raise rewrite_traceback_stack(source=source)
937e31aef6aSopenharmony_ci
938e31aef6aSopenharmony_ci    def join_path(self, template: str, parent: str) -> str:
939e31aef6aSopenharmony_ci        """Join a template with the parent.  By default all the lookups are
940e31aef6aSopenharmony_ci        relative to the loader root so this method returns the `template`
941e31aef6aSopenharmony_ci        parameter unchanged, but if the paths should be relative to the
942e31aef6aSopenharmony_ci        parent template, this function can be used to calculate the real
943e31aef6aSopenharmony_ci        template name.
944e31aef6aSopenharmony_ci
945e31aef6aSopenharmony_ci        Subclasses may override this method and implement template path
946e31aef6aSopenharmony_ci        joining here.
947e31aef6aSopenharmony_ci        """
948e31aef6aSopenharmony_ci        return template
949e31aef6aSopenharmony_ci
950e31aef6aSopenharmony_ci    @internalcode
951e31aef6aSopenharmony_ci    def _load_template(
952e31aef6aSopenharmony_ci        self, name: str, globals: t.Optional[t.MutableMapping[str, t.Any]]
953e31aef6aSopenharmony_ci    ) -> "Template":
954e31aef6aSopenharmony_ci        if self.loader is None:
955e31aef6aSopenharmony_ci            raise TypeError("no loader for this environment specified")
956e31aef6aSopenharmony_ci        cache_key = (weakref.ref(self.loader), name)
957e31aef6aSopenharmony_ci        if self.cache is not None:
958e31aef6aSopenharmony_ci            template = self.cache.get(cache_key)
959e31aef6aSopenharmony_ci            if template is not None and (
960e31aef6aSopenharmony_ci                not self.auto_reload or template.is_up_to_date
961e31aef6aSopenharmony_ci            ):
962e31aef6aSopenharmony_ci                # template.globals is a ChainMap, modifying it will only
963e31aef6aSopenharmony_ci                # affect the template, not the environment globals.
964e31aef6aSopenharmony_ci                if globals:
965e31aef6aSopenharmony_ci                    template.globals.update(globals)
966e31aef6aSopenharmony_ci
967e31aef6aSopenharmony_ci                return template
968e31aef6aSopenharmony_ci
969e31aef6aSopenharmony_ci        template = self.loader.load(self, name, self.make_globals(globals))
970e31aef6aSopenharmony_ci
971e31aef6aSopenharmony_ci        if self.cache is not None:
972e31aef6aSopenharmony_ci            self.cache[cache_key] = template
973e31aef6aSopenharmony_ci        return template
974e31aef6aSopenharmony_ci
975e31aef6aSopenharmony_ci    @internalcode
976e31aef6aSopenharmony_ci    def get_template(
977e31aef6aSopenharmony_ci        self,
978e31aef6aSopenharmony_ci        name: t.Union[str, "Template"],
979e31aef6aSopenharmony_ci        parent: t.Optional[str] = None,
980e31aef6aSopenharmony_ci        globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
981e31aef6aSopenharmony_ci    ) -> "Template":
982e31aef6aSopenharmony_ci        """Load a template by name with :attr:`loader` and return a
983e31aef6aSopenharmony_ci        :class:`Template`. If the template does not exist a
984e31aef6aSopenharmony_ci        :exc:`TemplateNotFound` exception is raised.
985e31aef6aSopenharmony_ci
986e31aef6aSopenharmony_ci        :param name: Name of the template to load. When loading
987e31aef6aSopenharmony_ci            templates from the filesystem, "/" is used as the path
988e31aef6aSopenharmony_ci            separator, even on Windows.
989e31aef6aSopenharmony_ci        :param parent: The name of the parent template importing this
990e31aef6aSopenharmony_ci            template. :meth:`join_path` can be used to implement name
991e31aef6aSopenharmony_ci            transformations with this.
992e31aef6aSopenharmony_ci        :param globals: Extend the environment :attr:`globals` with
993e31aef6aSopenharmony_ci            these extra variables available for all renders of this
994e31aef6aSopenharmony_ci            template. If the template has already been loaded and
995e31aef6aSopenharmony_ci            cached, its globals are updated with any new items.
996e31aef6aSopenharmony_ci
997e31aef6aSopenharmony_ci        .. versionchanged:: 3.0
998e31aef6aSopenharmony_ci            If a template is loaded from cache, ``globals`` will update
999e31aef6aSopenharmony_ci            the template's globals instead of ignoring the new values.
1000e31aef6aSopenharmony_ci
1001e31aef6aSopenharmony_ci        .. versionchanged:: 2.4
1002e31aef6aSopenharmony_ci            If ``name`` is a :class:`Template` object it is returned
1003e31aef6aSopenharmony_ci            unchanged.
1004e31aef6aSopenharmony_ci        """
1005e31aef6aSopenharmony_ci        if isinstance(name, Template):
1006e31aef6aSopenharmony_ci            return name
1007e31aef6aSopenharmony_ci        if parent is not None:
1008e31aef6aSopenharmony_ci            name = self.join_path(name, parent)
1009e31aef6aSopenharmony_ci
1010e31aef6aSopenharmony_ci        return self._load_template(name, globals)
1011e31aef6aSopenharmony_ci
1012e31aef6aSopenharmony_ci    @internalcode
1013e31aef6aSopenharmony_ci    def select_template(
1014e31aef6aSopenharmony_ci        self,
1015e31aef6aSopenharmony_ci        names: t.Iterable[t.Union[str, "Template"]],
1016e31aef6aSopenharmony_ci        parent: t.Optional[str] = None,
1017e31aef6aSopenharmony_ci        globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
1018e31aef6aSopenharmony_ci    ) -> "Template":
1019e31aef6aSopenharmony_ci        """Like :meth:`get_template`, but tries loading multiple names.
1020e31aef6aSopenharmony_ci        If none of the names can be loaded a :exc:`TemplatesNotFound`
1021e31aef6aSopenharmony_ci        exception is raised.
1022e31aef6aSopenharmony_ci
1023e31aef6aSopenharmony_ci        :param names: List of template names to try loading in order.
1024e31aef6aSopenharmony_ci        :param parent: The name of the parent template importing this
1025e31aef6aSopenharmony_ci            template. :meth:`join_path` can be used to implement name
1026e31aef6aSopenharmony_ci            transformations with this.
1027e31aef6aSopenharmony_ci        :param globals: Extend the environment :attr:`globals` with
1028e31aef6aSopenharmony_ci            these extra variables available for all renders of this
1029e31aef6aSopenharmony_ci            template. If the template has already been loaded and
1030e31aef6aSopenharmony_ci            cached, its globals are updated with any new items.
1031e31aef6aSopenharmony_ci
1032e31aef6aSopenharmony_ci        .. versionchanged:: 3.0
1033e31aef6aSopenharmony_ci            If a template is loaded from cache, ``globals`` will update
1034e31aef6aSopenharmony_ci            the template's globals instead of ignoring the new values.
1035e31aef6aSopenharmony_ci
1036e31aef6aSopenharmony_ci        .. versionchanged:: 2.11
1037e31aef6aSopenharmony_ci            If ``names`` is :class:`Undefined`, an :exc:`UndefinedError`
1038e31aef6aSopenharmony_ci            is raised instead. If no templates were found and ``names``
1039e31aef6aSopenharmony_ci            contains :class:`Undefined`, the message is more helpful.
1040e31aef6aSopenharmony_ci
1041e31aef6aSopenharmony_ci        .. versionchanged:: 2.4
1042e31aef6aSopenharmony_ci            If ``names`` contains a :class:`Template` object it is
1043e31aef6aSopenharmony_ci            returned unchanged.
1044e31aef6aSopenharmony_ci
1045e31aef6aSopenharmony_ci        .. versionadded:: 2.3
1046e31aef6aSopenharmony_ci        """
1047e31aef6aSopenharmony_ci        if isinstance(names, Undefined):
1048e31aef6aSopenharmony_ci            names._fail_with_undefined_error()
1049e31aef6aSopenharmony_ci
1050e31aef6aSopenharmony_ci        if not names:
1051e31aef6aSopenharmony_ci            raise TemplatesNotFound(
1052e31aef6aSopenharmony_ci                message="Tried to select from an empty list of templates."
1053e31aef6aSopenharmony_ci            )
1054e31aef6aSopenharmony_ci
1055e31aef6aSopenharmony_ci        for name in names:
1056e31aef6aSopenharmony_ci            if isinstance(name, Template):
1057e31aef6aSopenharmony_ci                return name
1058e31aef6aSopenharmony_ci            if parent is not None:
1059e31aef6aSopenharmony_ci                name = self.join_path(name, parent)
1060e31aef6aSopenharmony_ci            try:
1061e31aef6aSopenharmony_ci                return self._load_template(name, globals)
1062e31aef6aSopenharmony_ci            except (TemplateNotFound, UndefinedError):
1063e31aef6aSopenharmony_ci                pass
1064e31aef6aSopenharmony_ci        raise TemplatesNotFound(names)  # type: ignore
1065e31aef6aSopenharmony_ci
1066e31aef6aSopenharmony_ci    @internalcode
1067e31aef6aSopenharmony_ci    def get_or_select_template(
1068e31aef6aSopenharmony_ci        self,
1069e31aef6aSopenharmony_ci        template_name_or_list: t.Union[
1070e31aef6aSopenharmony_ci            str, "Template", t.List[t.Union[str, "Template"]]
1071e31aef6aSopenharmony_ci        ],
1072e31aef6aSopenharmony_ci        parent: t.Optional[str] = None,
1073e31aef6aSopenharmony_ci        globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
1074e31aef6aSopenharmony_ci    ) -> "Template":
1075e31aef6aSopenharmony_ci        """Use :meth:`select_template` if an iterable of template names
1076e31aef6aSopenharmony_ci        is given, or :meth:`get_template` if one name is given.
1077e31aef6aSopenharmony_ci
1078e31aef6aSopenharmony_ci        .. versionadded:: 2.3
1079e31aef6aSopenharmony_ci        """
1080e31aef6aSopenharmony_ci        if isinstance(template_name_or_list, (str, Undefined)):
1081e31aef6aSopenharmony_ci            return self.get_template(template_name_or_list, parent, globals)
1082e31aef6aSopenharmony_ci        elif isinstance(template_name_or_list, Template):
1083e31aef6aSopenharmony_ci            return template_name_or_list
1084e31aef6aSopenharmony_ci        return self.select_template(template_name_or_list, parent, globals)
1085e31aef6aSopenharmony_ci
1086e31aef6aSopenharmony_ci    def from_string(
1087e31aef6aSopenharmony_ci        self,
1088e31aef6aSopenharmony_ci        source: t.Union[str, nodes.Template],
1089e31aef6aSopenharmony_ci        globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
1090e31aef6aSopenharmony_ci        template_class: t.Optional[t.Type["Template"]] = None,
1091e31aef6aSopenharmony_ci    ) -> "Template":
1092e31aef6aSopenharmony_ci        """Load a template from a source string without using
1093e31aef6aSopenharmony_ci        :attr:`loader`.
1094e31aef6aSopenharmony_ci
1095e31aef6aSopenharmony_ci        :param source: Jinja source to compile into a template.
1096e31aef6aSopenharmony_ci        :param globals: Extend the environment :attr:`globals` with
1097e31aef6aSopenharmony_ci            these extra variables available for all renders of this
1098e31aef6aSopenharmony_ci            template. If the template has already been loaded and
1099e31aef6aSopenharmony_ci            cached, its globals are updated with any new items.
1100e31aef6aSopenharmony_ci        :param template_class: Return an instance of this
1101e31aef6aSopenharmony_ci            :class:`Template` class.
1102e31aef6aSopenharmony_ci        """
1103e31aef6aSopenharmony_ci        gs = self.make_globals(globals)
1104e31aef6aSopenharmony_ci        cls = template_class or self.template_class
1105e31aef6aSopenharmony_ci        return cls.from_code(self, self.compile(source), gs, None)
1106e31aef6aSopenharmony_ci
1107e31aef6aSopenharmony_ci    def make_globals(
1108e31aef6aSopenharmony_ci        self, d: t.Optional[t.MutableMapping[str, t.Any]]
1109e31aef6aSopenharmony_ci    ) -> t.MutableMapping[str, t.Any]:
1110e31aef6aSopenharmony_ci        """Make the globals map for a template. Any given template
1111e31aef6aSopenharmony_ci        globals overlay the environment :attr:`globals`.
1112e31aef6aSopenharmony_ci
1113e31aef6aSopenharmony_ci        Returns a :class:`collections.ChainMap`. This allows any changes
1114e31aef6aSopenharmony_ci        to a template's globals to only affect that template, while
1115e31aef6aSopenharmony_ci        changes to the environment's globals are still reflected.
1116e31aef6aSopenharmony_ci        However, avoid modifying any globals after a template is loaded.
1117e31aef6aSopenharmony_ci
1118e31aef6aSopenharmony_ci        :param d: Dict of template-specific globals.
1119e31aef6aSopenharmony_ci
1120e31aef6aSopenharmony_ci        .. versionchanged:: 3.0
1121e31aef6aSopenharmony_ci            Use :class:`collections.ChainMap` to always prevent mutating
1122e31aef6aSopenharmony_ci            environment globals.
1123e31aef6aSopenharmony_ci        """
1124e31aef6aSopenharmony_ci        if d is None:
1125e31aef6aSopenharmony_ci            d = {}
1126e31aef6aSopenharmony_ci
1127e31aef6aSopenharmony_ci        return ChainMap(d, self.globals)
1128e31aef6aSopenharmony_ci
1129e31aef6aSopenharmony_ci
1130e31aef6aSopenharmony_ciclass Template:
1131e31aef6aSopenharmony_ci    """A compiled template that can be rendered.
1132e31aef6aSopenharmony_ci
1133e31aef6aSopenharmony_ci    Use the methods on :class:`Environment` to create or load templates.
1134e31aef6aSopenharmony_ci    The environment is used to configure how templates are compiled and
1135e31aef6aSopenharmony_ci    behave.
1136e31aef6aSopenharmony_ci
1137e31aef6aSopenharmony_ci    It is also possible to create a template object directly. This is
1138e31aef6aSopenharmony_ci    not usually recommended. The constructor takes most of the same
1139e31aef6aSopenharmony_ci    arguments as :class:`Environment`. All templates created with the
1140e31aef6aSopenharmony_ci    same environment arguments share the same ephemeral ``Environment``
1141e31aef6aSopenharmony_ci    instance behind the scenes.
1142e31aef6aSopenharmony_ci
1143e31aef6aSopenharmony_ci    A template object should be considered immutable. Modifications on
1144e31aef6aSopenharmony_ci    the object are not supported.
1145e31aef6aSopenharmony_ci    """
1146e31aef6aSopenharmony_ci
1147e31aef6aSopenharmony_ci    #: Type of environment to create when creating a template directly
1148e31aef6aSopenharmony_ci    #: rather than through an existing environment.
1149e31aef6aSopenharmony_ci    environment_class: t.Type[Environment] = Environment
1150e31aef6aSopenharmony_ci
1151e31aef6aSopenharmony_ci    environment: Environment
1152e31aef6aSopenharmony_ci    globals: t.MutableMapping[str, t.Any]
1153e31aef6aSopenharmony_ci    name: t.Optional[str]
1154e31aef6aSopenharmony_ci    filename: t.Optional[str]
1155e31aef6aSopenharmony_ci    blocks: t.Dict[str, t.Callable[[Context], t.Iterator[str]]]
1156e31aef6aSopenharmony_ci    root_render_func: t.Callable[[Context], t.Iterator[str]]
1157e31aef6aSopenharmony_ci    _module: t.Optional["TemplateModule"]
1158e31aef6aSopenharmony_ci    _debug_info: str
1159e31aef6aSopenharmony_ci    _uptodate: t.Optional[t.Callable[[], bool]]
1160e31aef6aSopenharmony_ci
1161e31aef6aSopenharmony_ci    def __new__(
1162e31aef6aSopenharmony_ci        cls,
1163e31aef6aSopenharmony_ci        source: t.Union[str, nodes.Template],
1164e31aef6aSopenharmony_ci        block_start_string: str = BLOCK_START_STRING,
1165e31aef6aSopenharmony_ci        block_end_string: str = BLOCK_END_STRING,
1166e31aef6aSopenharmony_ci        variable_start_string: str = VARIABLE_START_STRING,
1167e31aef6aSopenharmony_ci        variable_end_string: str = VARIABLE_END_STRING,
1168e31aef6aSopenharmony_ci        comment_start_string: str = COMMENT_START_STRING,
1169e31aef6aSopenharmony_ci        comment_end_string: str = COMMENT_END_STRING,
1170e31aef6aSopenharmony_ci        line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX,
1171e31aef6aSopenharmony_ci        line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX,
1172e31aef6aSopenharmony_ci        trim_blocks: bool = TRIM_BLOCKS,
1173e31aef6aSopenharmony_ci        lstrip_blocks: bool = LSTRIP_BLOCKS,
1174e31aef6aSopenharmony_ci        newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE,
1175e31aef6aSopenharmony_ci        keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE,
1176e31aef6aSopenharmony_ci        extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (),
1177e31aef6aSopenharmony_ci        optimized: bool = True,
1178e31aef6aSopenharmony_ci        undefined: t.Type[Undefined] = Undefined,
1179e31aef6aSopenharmony_ci        finalize: t.Optional[t.Callable[..., t.Any]] = None,
1180e31aef6aSopenharmony_ci        autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False,
1181e31aef6aSopenharmony_ci        enable_async: bool = False,
1182e31aef6aSopenharmony_ci    ) -> t.Any:  # it returns a `Template`, but this breaks the sphinx build...
1183e31aef6aSopenharmony_ci        env = get_spontaneous_environment(
1184e31aef6aSopenharmony_ci            cls.environment_class,  # type: ignore
1185e31aef6aSopenharmony_ci            block_start_string,
1186e31aef6aSopenharmony_ci            block_end_string,
1187e31aef6aSopenharmony_ci            variable_start_string,
1188e31aef6aSopenharmony_ci            variable_end_string,
1189e31aef6aSopenharmony_ci            comment_start_string,
1190e31aef6aSopenharmony_ci            comment_end_string,
1191e31aef6aSopenharmony_ci            line_statement_prefix,
1192e31aef6aSopenharmony_ci            line_comment_prefix,
1193e31aef6aSopenharmony_ci            trim_blocks,
1194e31aef6aSopenharmony_ci            lstrip_blocks,
1195e31aef6aSopenharmony_ci            newline_sequence,
1196e31aef6aSopenharmony_ci            keep_trailing_newline,
1197e31aef6aSopenharmony_ci            frozenset(extensions),
1198e31aef6aSopenharmony_ci            optimized,
1199e31aef6aSopenharmony_ci            undefined,  # type: ignore
1200e31aef6aSopenharmony_ci            finalize,
1201e31aef6aSopenharmony_ci            autoescape,
1202e31aef6aSopenharmony_ci            None,
1203e31aef6aSopenharmony_ci            0,
1204e31aef6aSopenharmony_ci            False,
1205e31aef6aSopenharmony_ci            None,
1206e31aef6aSopenharmony_ci            enable_async,
1207e31aef6aSopenharmony_ci        )
1208e31aef6aSopenharmony_ci        return env.from_string(source, template_class=cls)
1209e31aef6aSopenharmony_ci
1210e31aef6aSopenharmony_ci    @classmethod
1211e31aef6aSopenharmony_ci    def from_code(
1212e31aef6aSopenharmony_ci        cls,
1213e31aef6aSopenharmony_ci        environment: Environment,
1214e31aef6aSopenharmony_ci        code: CodeType,
1215e31aef6aSopenharmony_ci        globals: t.MutableMapping[str, t.Any],
1216e31aef6aSopenharmony_ci        uptodate: t.Optional[t.Callable[[], bool]] = None,
1217e31aef6aSopenharmony_ci    ) -> "Template":
1218e31aef6aSopenharmony_ci        """Creates a template object from compiled code and the globals.  This
1219e31aef6aSopenharmony_ci        is used by the loaders and environment to create a template object.
1220e31aef6aSopenharmony_ci        """
1221e31aef6aSopenharmony_ci        namespace = {"environment": environment, "__file__": code.co_filename}
1222e31aef6aSopenharmony_ci        exec(code, namespace)
1223e31aef6aSopenharmony_ci        rv = cls._from_namespace(environment, namespace, globals)
1224e31aef6aSopenharmony_ci        rv._uptodate = uptodate
1225e31aef6aSopenharmony_ci        return rv
1226e31aef6aSopenharmony_ci
1227e31aef6aSopenharmony_ci    @classmethod
1228e31aef6aSopenharmony_ci    def from_module_dict(
1229e31aef6aSopenharmony_ci        cls,
1230e31aef6aSopenharmony_ci        environment: Environment,
1231e31aef6aSopenharmony_ci        module_dict: t.MutableMapping[str, t.Any],
1232e31aef6aSopenharmony_ci        globals: t.MutableMapping[str, t.Any],
1233e31aef6aSopenharmony_ci    ) -> "Template":
1234e31aef6aSopenharmony_ci        """Creates a template object from a module.  This is used by the
1235e31aef6aSopenharmony_ci        module loader to create a template object.
1236e31aef6aSopenharmony_ci
1237e31aef6aSopenharmony_ci        .. versionadded:: 2.4
1238e31aef6aSopenharmony_ci        """
1239e31aef6aSopenharmony_ci        return cls._from_namespace(environment, module_dict, globals)
1240e31aef6aSopenharmony_ci
1241e31aef6aSopenharmony_ci    @classmethod
1242e31aef6aSopenharmony_ci    def _from_namespace(
1243e31aef6aSopenharmony_ci        cls,
1244e31aef6aSopenharmony_ci        environment: Environment,
1245e31aef6aSopenharmony_ci        namespace: t.MutableMapping[str, t.Any],
1246e31aef6aSopenharmony_ci        globals: t.MutableMapping[str, t.Any],
1247e31aef6aSopenharmony_ci    ) -> "Template":
1248e31aef6aSopenharmony_ci        t: "Template" = object.__new__(cls)
1249e31aef6aSopenharmony_ci        t.environment = environment
1250e31aef6aSopenharmony_ci        t.globals = globals
1251e31aef6aSopenharmony_ci        t.name = namespace["name"]
1252e31aef6aSopenharmony_ci        t.filename = namespace["__file__"]
1253e31aef6aSopenharmony_ci        t.blocks = namespace["blocks"]
1254e31aef6aSopenharmony_ci
1255e31aef6aSopenharmony_ci        # render function and module
1256e31aef6aSopenharmony_ci        t.root_render_func = namespace["root"]
1257e31aef6aSopenharmony_ci        t._module = None
1258e31aef6aSopenharmony_ci
1259e31aef6aSopenharmony_ci        # debug and loader helpers
1260e31aef6aSopenharmony_ci        t._debug_info = namespace["debug_info"]
1261e31aef6aSopenharmony_ci        t._uptodate = None
1262e31aef6aSopenharmony_ci
1263e31aef6aSopenharmony_ci        # store the reference
1264e31aef6aSopenharmony_ci        namespace["environment"] = environment
1265e31aef6aSopenharmony_ci        namespace["__jinja_template__"] = t
1266e31aef6aSopenharmony_ci
1267e31aef6aSopenharmony_ci        return t
1268e31aef6aSopenharmony_ci
1269e31aef6aSopenharmony_ci    def render(self, *args: t.Any, **kwargs: t.Any) -> str:
1270e31aef6aSopenharmony_ci        """This method accepts the same arguments as the `dict` constructor:
1271e31aef6aSopenharmony_ci        A dict, a dict subclass or some keyword arguments.  If no arguments
1272e31aef6aSopenharmony_ci        are given the context will be empty.  These two calls do the same::
1273e31aef6aSopenharmony_ci
1274e31aef6aSopenharmony_ci            template.render(knights='that say nih')
1275e31aef6aSopenharmony_ci            template.render({'knights': 'that say nih'})
1276e31aef6aSopenharmony_ci
1277e31aef6aSopenharmony_ci        This will return the rendered template as a string.
1278e31aef6aSopenharmony_ci        """
1279e31aef6aSopenharmony_ci        if self.environment.is_async:
1280e31aef6aSopenharmony_ci            import asyncio
1281e31aef6aSopenharmony_ci
1282e31aef6aSopenharmony_ci            close = False
1283e31aef6aSopenharmony_ci
1284e31aef6aSopenharmony_ci            try:
1285e31aef6aSopenharmony_ci                loop = asyncio.get_running_loop()
1286e31aef6aSopenharmony_ci            except RuntimeError:
1287e31aef6aSopenharmony_ci                loop = asyncio.new_event_loop()
1288e31aef6aSopenharmony_ci                close = True
1289e31aef6aSopenharmony_ci
1290e31aef6aSopenharmony_ci            try:
1291e31aef6aSopenharmony_ci                return loop.run_until_complete(self.render_async(*args, **kwargs))
1292e31aef6aSopenharmony_ci            finally:
1293e31aef6aSopenharmony_ci                if close:
1294e31aef6aSopenharmony_ci                    loop.close()
1295e31aef6aSopenharmony_ci
1296e31aef6aSopenharmony_ci        ctx = self.new_context(dict(*args, **kwargs))
1297e31aef6aSopenharmony_ci
1298e31aef6aSopenharmony_ci        try:
1299e31aef6aSopenharmony_ci            return self.environment.concat(self.root_render_func(ctx))  # type: ignore
1300e31aef6aSopenharmony_ci        except Exception:
1301e31aef6aSopenharmony_ci            self.environment.handle_exception()
1302e31aef6aSopenharmony_ci
1303e31aef6aSopenharmony_ci    async def render_async(self, *args: t.Any, **kwargs: t.Any) -> str:
1304e31aef6aSopenharmony_ci        """This works similar to :meth:`render` but returns a coroutine
1305e31aef6aSopenharmony_ci        that when awaited returns the entire rendered template string.  This
1306e31aef6aSopenharmony_ci        requires the async feature to be enabled.
1307e31aef6aSopenharmony_ci
1308e31aef6aSopenharmony_ci        Example usage::
1309e31aef6aSopenharmony_ci
1310e31aef6aSopenharmony_ci            await template.render_async(knights='that say nih; asynchronously')
1311e31aef6aSopenharmony_ci        """
1312e31aef6aSopenharmony_ci        if not self.environment.is_async:
1313e31aef6aSopenharmony_ci            raise RuntimeError(
1314e31aef6aSopenharmony_ci                "The environment was not created with async mode enabled."
1315e31aef6aSopenharmony_ci            )
1316e31aef6aSopenharmony_ci
1317e31aef6aSopenharmony_ci        ctx = self.new_context(dict(*args, **kwargs))
1318e31aef6aSopenharmony_ci
1319e31aef6aSopenharmony_ci        try:
1320e31aef6aSopenharmony_ci            return self.environment.concat(  # type: ignore
1321e31aef6aSopenharmony_ci                [n async for n in self.root_render_func(ctx)]  # type: ignore
1322e31aef6aSopenharmony_ci            )
1323e31aef6aSopenharmony_ci        except Exception:
1324e31aef6aSopenharmony_ci            return self.environment.handle_exception()
1325e31aef6aSopenharmony_ci
1326e31aef6aSopenharmony_ci    def stream(self, *args: t.Any, **kwargs: t.Any) -> "TemplateStream":
1327e31aef6aSopenharmony_ci        """Works exactly like :meth:`generate` but returns a
1328e31aef6aSopenharmony_ci        :class:`TemplateStream`.
1329e31aef6aSopenharmony_ci        """
1330e31aef6aSopenharmony_ci        return TemplateStream(self.generate(*args, **kwargs))
1331e31aef6aSopenharmony_ci
1332e31aef6aSopenharmony_ci    def generate(self, *args: t.Any, **kwargs: t.Any) -> t.Iterator[str]:
1333e31aef6aSopenharmony_ci        """For very large templates it can be useful to not render the whole
1334e31aef6aSopenharmony_ci        template at once but evaluate each statement after another and yield
1335e31aef6aSopenharmony_ci        piece for piece.  This method basically does exactly that and returns
1336e31aef6aSopenharmony_ci        a generator that yields one item after another as strings.
1337e31aef6aSopenharmony_ci
1338e31aef6aSopenharmony_ci        It accepts the same arguments as :meth:`render`.
1339e31aef6aSopenharmony_ci        """
1340e31aef6aSopenharmony_ci        if self.environment.is_async:
1341e31aef6aSopenharmony_ci            import asyncio
1342e31aef6aSopenharmony_ci
1343e31aef6aSopenharmony_ci            async def to_list() -> t.List[str]:
1344e31aef6aSopenharmony_ci                return [x async for x in self.generate_async(*args, **kwargs)]
1345e31aef6aSopenharmony_ci
1346e31aef6aSopenharmony_ci            yield from asyncio.run(to_list())
1347e31aef6aSopenharmony_ci            return
1348e31aef6aSopenharmony_ci
1349e31aef6aSopenharmony_ci        ctx = self.new_context(dict(*args, **kwargs))
1350e31aef6aSopenharmony_ci
1351e31aef6aSopenharmony_ci        try:
1352e31aef6aSopenharmony_ci            yield from self.root_render_func(ctx)
1353e31aef6aSopenharmony_ci        except Exception:
1354e31aef6aSopenharmony_ci            yield self.environment.handle_exception()
1355e31aef6aSopenharmony_ci
1356e31aef6aSopenharmony_ci    async def generate_async(
1357e31aef6aSopenharmony_ci        self, *args: t.Any, **kwargs: t.Any
1358e31aef6aSopenharmony_ci    ) -> t.AsyncIterator[str]:
1359e31aef6aSopenharmony_ci        """An async version of :meth:`generate`.  Works very similarly but
1360e31aef6aSopenharmony_ci        returns an async iterator instead.
1361e31aef6aSopenharmony_ci        """
1362e31aef6aSopenharmony_ci        if not self.environment.is_async:
1363e31aef6aSopenharmony_ci            raise RuntimeError(
1364e31aef6aSopenharmony_ci                "The environment was not created with async mode enabled."
1365e31aef6aSopenharmony_ci            )
1366e31aef6aSopenharmony_ci
1367e31aef6aSopenharmony_ci        ctx = self.new_context(dict(*args, **kwargs))
1368e31aef6aSopenharmony_ci
1369e31aef6aSopenharmony_ci        try:
1370e31aef6aSopenharmony_ci            async for event in self.root_render_func(ctx):  # type: ignore
1371e31aef6aSopenharmony_ci                yield event
1372e31aef6aSopenharmony_ci        except Exception:
1373e31aef6aSopenharmony_ci            yield self.environment.handle_exception()
1374e31aef6aSopenharmony_ci
1375e31aef6aSopenharmony_ci    def new_context(
1376e31aef6aSopenharmony_ci        self,
1377e31aef6aSopenharmony_ci        vars: t.Optional[t.Dict[str, t.Any]] = None,
1378e31aef6aSopenharmony_ci        shared: bool = False,
1379e31aef6aSopenharmony_ci        locals: t.Optional[t.Mapping[str, t.Any]] = None,
1380e31aef6aSopenharmony_ci    ) -> Context:
1381e31aef6aSopenharmony_ci        """Create a new :class:`Context` for this template.  The vars
1382e31aef6aSopenharmony_ci        provided will be passed to the template.  Per default the globals
1383e31aef6aSopenharmony_ci        are added to the context.  If shared is set to `True` the data
1384e31aef6aSopenharmony_ci        is passed as is to the context without adding the globals.
1385e31aef6aSopenharmony_ci
1386e31aef6aSopenharmony_ci        `locals` can be a dict of local variables for internal usage.
1387e31aef6aSopenharmony_ci        """
1388e31aef6aSopenharmony_ci        return new_context(
1389e31aef6aSopenharmony_ci            self.environment, self.name, self.blocks, vars, shared, self.globals, locals
1390e31aef6aSopenharmony_ci        )
1391e31aef6aSopenharmony_ci
1392e31aef6aSopenharmony_ci    def make_module(
1393e31aef6aSopenharmony_ci        self,
1394e31aef6aSopenharmony_ci        vars: t.Optional[t.Dict[str, t.Any]] = None,
1395e31aef6aSopenharmony_ci        shared: bool = False,
1396e31aef6aSopenharmony_ci        locals: t.Optional[t.Mapping[str, t.Any]] = None,
1397e31aef6aSopenharmony_ci    ) -> "TemplateModule":
1398e31aef6aSopenharmony_ci        """This method works like the :attr:`module` attribute when called
1399e31aef6aSopenharmony_ci        without arguments but it will evaluate the template on every call
1400e31aef6aSopenharmony_ci        rather than caching it.  It's also possible to provide
1401e31aef6aSopenharmony_ci        a dict which is then used as context.  The arguments are the same
1402e31aef6aSopenharmony_ci        as for the :meth:`new_context` method.
1403e31aef6aSopenharmony_ci        """
1404e31aef6aSopenharmony_ci        ctx = self.new_context(vars, shared, locals)
1405e31aef6aSopenharmony_ci        return TemplateModule(self, ctx)
1406e31aef6aSopenharmony_ci
1407e31aef6aSopenharmony_ci    async def make_module_async(
1408e31aef6aSopenharmony_ci        self,
1409e31aef6aSopenharmony_ci        vars: t.Optional[t.Dict[str, t.Any]] = None,
1410e31aef6aSopenharmony_ci        shared: bool = False,
1411e31aef6aSopenharmony_ci        locals: t.Optional[t.Mapping[str, t.Any]] = None,
1412e31aef6aSopenharmony_ci    ) -> "TemplateModule":
1413e31aef6aSopenharmony_ci        """As template module creation can invoke template code for
1414e31aef6aSopenharmony_ci        asynchronous executions this method must be used instead of the
1415e31aef6aSopenharmony_ci        normal :meth:`make_module` one.  Likewise the module attribute
1416e31aef6aSopenharmony_ci        becomes unavailable in async mode.
1417e31aef6aSopenharmony_ci        """
1418e31aef6aSopenharmony_ci        ctx = self.new_context(vars, shared, locals)
1419e31aef6aSopenharmony_ci        return TemplateModule(
1420e31aef6aSopenharmony_ci            self, ctx, [x async for x in self.root_render_func(ctx)]  # type: ignore
1421e31aef6aSopenharmony_ci        )
1422e31aef6aSopenharmony_ci
1423e31aef6aSopenharmony_ci    @internalcode
1424e31aef6aSopenharmony_ci    def _get_default_module(self, ctx: t.Optional[Context] = None) -> "TemplateModule":
1425e31aef6aSopenharmony_ci        """If a context is passed in, this means that the template was
1426e31aef6aSopenharmony_ci        imported. Imported templates have access to the current
1427e31aef6aSopenharmony_ci        template's globals by default, but they can only be accessed via
1428e31aef6aSopenharmony_ci        the context during runtime.
1429e31aef6aSopenharmony_ci
1430e31aef6aSopenharmony_ci        If there are new globals, we need to create a new module because
1431e31aef6aSopenharmony_ci        the cached module is already rendered and will not have access
1432e31aef6aSopenharmony_ci        to globals from the current context. This new module is not
1433e31aef6aSopenharmony_ci        cached because the template can be imported elsewhere, and it
1434e31aef6aSopenharmony_ci        should have access to only the current template's globals.
1435e31aef6aSopenharmony_ci        """
1436e31aef6aSopenharmony_ci        if self.environment.is_async:
1437e31aef6aSopenharmony_ci            raise RuntimeError("Module is not available in async mode.")
1438e31aef6aSopenharmony_ci
1439e31aef6aSopenharmony_ci        if ctx is not None:
1440e31aef6aSopenharmony_ci            keys = ctx.globals_keys - self.globals.keys()
1441e31aef6aSopenharmony_ci
1442e31aef6aSopenharmony_ci            if keys:
1443e31aef6aSopenharmony_ci                return self.make_module({k: ctx.parent[k] for k in keys})
1444e31aef6aSopenharmony_ci
1445e31aef6aSopenharmony_ci        if self._module is None:
1446e31aef6aSopenharmony_ci            self._module = self.make_module()
1447e31aef6aSopenharmony_ci
1448e31aef6aSopenharmony_ci        return self._module
1449e31aef6aSopenharmony_ci
1450e31aef6aSopenharmony_ci    async def _get_default_module_async(
1451e31aef6aSopenharmony_ci        self, ctx: t.Optional[Context] = None
1452e31aef6aSopenharmony_ci    ) -> "TemplateModule":
1453e31aef6aSopenharmony_ci        if ctx is not None:
1454e31aef6aSopenharmony_ci            keys = ctx.globals_keys - self.globals.keys()
1455e31aef6aSopenharmony_ci
1456e31aef6aSopenharmony_ci            if keys:
1457e31aef6aSopenharmony_ci                return await self.make_module_async({k: ctx.parent[k] for k in keys})
1458e31aef6aSopenharmony_ci
1459e31aef6aSopenharmony_ci        if self._module is None:
1460e31aef6aSopenharmony_ci            self._module = await self.make_module_async()
1461e31aef6aSopenharmony_ci
1462e31aef6aSopenharmony_ci        return self._module
1463e31aef6aSopenharmony_ci
1464e31aef6aSopenharmony_ci    @property
1465e31aef6aSopenharmony_ci    def module(self) -> "TemplateModule":
1466e31aef6aSopenharmony_ci        """The template as module.  This is used for imports in the
1467e31aef6aSopenharmony_ci        template runtime but is also useful if one wants to access
1468e31aef6aSopenharmony_ci        exported template variables from the Python layer:
1469e31aef6aSopenharmony_ci
1470e31aef6aSopenharmony_ci        >>> t = Template('{% macro foo() %}42{% endmacro %}23')
1471e31aef6aSopenharmony_ci        >>> str(t.module)
1472e31aef6aSopenharmony_ci        '23'
1473e31aef6aSopenharmony_ci        >>> t.module.foo() == u'42'
1474e31aef6aSopenharmony_ci        True
1475e31aef6aSopenharmony_ci
1476e31aef6aSopenharmony_ci        This attribute is not available if async mode is enabled.
1477e31aef6aSopenharmony_ci        """
1478e31aef6aSopenharmony_ci        return self._get_default_module()
1479e31aef6aSopenharmony_ci
1480e31aef6aSopenharmony_ci    def get_corresponding_lineno(self, lineno: int) -> int:
1481e31aef6aSopenharmony_ci        """Return the source line number of a line number in the
1482e31aef6aSopenharmony_ci        generated bytecode as they are not in sync.
1483e31aef6aSopenharmony_ci        """
1484e31aef6aSopenharmony_ci        for template_line, code_line in reversed(self.debug_info):
1485e31aef6aSopenharmony_ci            if code_line <= lineno:
1486e31aef6aSopenharmony_ci                return template_line
1487e31aef6aSopenharmony_ci        return 1
1488e31aef6aSopenharmony_ci
1489e31aef6aSopenharmony_ci    @property
1490e31aef6aSopenharmony_ci    def is_up_to_date(self) -> bool:
1491e31aef6aSopenharmony_ci        """If this variable is `False` there is a newer version available."""
1492e31aef6aSopenharmony_ci        if self._uptodate is None:
1493e31aef6aSopenharmony_ci            return True
1494e31aef6aSopenharmony_ci        return self._uptodate()
1495e31aef6aSopenharmony_ci
1496e31aef6aSopenharmony_ci    @property
1497e31aef6aSopenharmony_ci    def debug_info(self) -> t.List[t.Tuple[int, int]]:
1498e31aef6aSopenharmony_ci        """The debug info mapping."""
1499e31aef6aSopenharmony_ci        if self._debug_info:
1500e31aef6aSopenharmony_ci            return [
1501e31aef6aSopenharmony_ci                tuple(map(int, x.split("=")))  # type: ignore
1502e31aef6aSopenharmony_ci                for x in self._debug_info.split("&")
1503e31aef6aSopenharmony_ci            ]
1504e31aef6aSopenharmony_ci
1505e31aef6aSopenharmony_ci        return []
1506e31aef6aSopenharmony_ci
1507e31aef6aSopenharmony_ci    def __repr__(self) -> str:
1508e31aef6aSopenharmony_ci        if self.name is None:
1509e31aef6aSopenharmony_ci            name = f"memory:{id(self):x}"
1510e31aef6aSopenharmony_ci        else:
1511e31aef6aSopenharmony_ci            name = repr(self.name)
1512e31aef6aSopenharmony_ci        return f"<{type(self).__name__} {name}>"
1513e31aef6aSopenharmony_ci
1514e31aef6aSopenharmony_ci
1515e31aef6aSopenharmony_ciclass TemplateModule:
1516e31aef6aSopenharmony_ci    """Represents an imported template.  All the exported names of the
1517e31aef6aSopenharmony_ci    template are available as attributes on this object.  Additionally
1518e31aef6aSopenharmony_ci    converting it into a string renders the contents.
1519e31aef6aSopenharmony_ci    """
1520e31aef6aSopenharmony_ci
1521e31aef6aSopenharmony_ci    def __init__(
1522e31aef6aSopenharmony_ci        self,
1523e31aef6aSopenharmony_ci        template: Template,
1524e31aef6aSopenharmony_ci        context: Context,
1525e31aef6aSopenharmony_ci        body_stream: t.Optional[t.Iterable[str]] = None,
1526e31aef6aSopenharmony_ci    ) -> None:
1527e31aef6aSopenharmony_ci        if body_stream is None:
1528e31aef6aSopenharmony_ci            if context.environment.is_async:
1529e31aef6aSopenharmony_ci                raise RuntimeError(
1530e31aef6aSopenharmony_ci                    "Async mode requires a body stream to be passed to"
1531e31aef6aSopenharmony_ci                    " a template module. Use the async methods of the"
1532e31aef6aSopenharmony_ci                    " API you are using."
1533e31aef6aSopenharmony_ci                )
1534e31aef6aSopenharmony_ci
1535e31aef6aSopenharmony_ci            body_stream = list(template.root_render_func(context))
1536e31aef6aSopenharmony_ci
1537e31aef6aSopenharmony_ci        self._body_stream = body_stream
1538e31aef6aSopenharmony_ci        self.__dict__.update(context.get_exported())
1539e31aef6aSopenharmony_ci        self.__name__ = template.name
1540e31aef6aSopenharmony_ci
1541e31aef6aSopenharmony_ci    def __html__(self) -> Markup:
1542e31aef6aSopenharmony_ci        return Markup(concat(self._body_stream))
1543e31aef6aSopenharmony_ci
1544e31aef6aSopenharmony_ci    def __str__(self) -> str:
1545e31aef6aSopenharmony_ci        return concat(self._body_stream)
1546e31aef6aSopenharmony_ci
1547e31aef6aSopenharmony_ci    def __repr__(self) -> str:
1548e31aef6aSopenharmony_ci        if self.__name__ is None:
1549e31aef6aSopenharmony_ci            name = f"memory:{id(self):x}"
1550e31aef6aSopenharmony_ci        else:
1551e31aef6aSopenharmony_ci            name = repr(self.__name__)
1552e31aef6aSopenharmony_ci        return f"<{type(self).__name__} {name}>"
1553e31aef6aSopenharmony_ci
1554e31aef6aSopenharmony_ci
1555e31aef6aSopenharmony_ciclass TemplateExpression:
1556e31aef6aSopenharmony_ci    """The :meth:`jinja2.Environment.compile_expression` method returns an
1557e31aef6aSopenharmony_ci    instance of this object.  It encapsulates the expression-like access
1558e31aef6aSopenharmony_ci    to the template with an expression it wraps.
1559e31aef6aSopenharmony_ci    """
1560e31aef6aSopenharmony_ci
1561e31aef6aSopenharmony_ci    def __init__(self, template: Template, undefined_to_none: bool) -> None:
1562e31aef6aSopenharmony_ci        self._template = template
1563e31aef6aSopenharmony_ci        self._undefined_to_none = undefined_to_none
1564e31aef6aSopenharmony_ci
1565e31aef6aSopenharmony_ci    def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Optional[t.Any]:
1566e31aef6aSopenharmony_ci        context = self._template.new_context(dict(*args, **kwargs))
1567e31aef6aSopenharmony_ci        consume(self._template.root_render_func(context))
1568e31aef6aSopenharmony_ci        rv = context.vars["result"]
1569e31aef6aSopenharmony_ci        if self._undefined_to_none and isinstance(rv, Undefined):
1570e31aef6aSopenharmony_ci            rv = None
1571e31aef6aSopenharmony_ci        return rv
1572e31aef6aSopenharmony_ci
1573e31aef6aSopenharmony_ci
1574e31aef6aSopenharmony_ciclass TemplateStream:
1575e31aef6aSopenharmony_ci    """A template stream works pretty much like an ordinary python generator
1576e31aef6aSopenharmony_ci    but it can buffer multiple items to reduce the number of total iterations.
1577e31aef6aSopenharmony_ci    Per default the output is unbuffered which means that for every unbuffered
1578e31aef6aSopenharmony_ci    instruction in the template one string is yielded.
1579e31aef6aSopenharmony_ci
1580e31aef6aSopenharmony_ci    If buffering is enabled with a buffer size of 5, five items are combined
1581e31aef6aSopenharmony_ci    into a new string.  This is mainly useful if you are streaming
1582e31aef6aSopenharmony_ci    big templates to a client via WSGI which flushes after each iteration.
1583e31aef6aSopenharmony_ci    """
1584e31aef6aSopenharmony_ci
1585e31aef6aSopenharmony_ci    def __init__(self, gen: t.Iterator[str]) -> None:
1586e31aef6aSopenharmony_ci        self._gen = gen
1587e31aef6aSopenharmony_ci        self.disable_buffering()
1588e31aef6aSopenharmony_ci
1589e31aef6aSopenharmony_ci    def dump(
1590e31aef6aSopenharmony_ci        self,
1591e31aef6aSopenharmony_ci        fp: t.Union[str, t.IO],
1592e31aef6aSopenharmony_ci        encoding: t.Optional[str] = None,
1593e31aef6aSopenharmony_ci        errors: t.Optional[str] = "strict",
1594e31aef6aSopenharmony_ci    ) -> None:
1595e31aef6aSopenharmony_ci        """Dump the complete stream into a file or file-like object.
1596e31aef6aSopenharmony_ci        Per default strings are written, if you want to encode
1597e31aef6aSopenharmony_ci        before writing specify an `encoding`.
1598e31aef6aSopenharmony_ci
1599e31aef6aSopenharmony_ci        Example usage::
1600e31aef6aSopenharmony_ci
1601e31aef6aSopenharmony_ci            Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
1602e31aef6aSopenharmony_ci        """
1603e31aef6aSopenharmony_ci        close = False
1604e31aef6aSopenharmony_ci
1605e31aef6aSopenharmony_ci        if isinstance(fp, str):
1606e31aef6aSopenharmony_ci            if encoding is None:
1607e31aef6aSopenharmony_ci                encoding = "utf-8"
1608e31aef6aSopenharmony_ci
1609e31aef6aSopenharmony_ci            fp = open(fp, "wb")
1610e31aef6aSopenharmony_ci            close = True
1611e31aef6aSopenharmony_ci        try:
1612e31aef6aSopenharmony_ci            if encoding is not None:
1613e31aef6aSopenharmony_ci                iterable = (x.encode(encoding, errors) for x in self)  # type: ignore
1614e31aef6aSopenharmony_ci            else:
1615e31aef6aSopenharmony_ci                iterable = self  # type: ignore
1616e31aef6aSopenharmony_ci
1617e31aef6aSopenharmony_ci            if hasattr(fp, "writelines"):
1618e31aef6aSopenharmony_ci                fp.writelines(iterable)
1619e31aef6aSopenharmony_ci            else:
1620e31aef6aSopenharmony_ci                for item in iterable:
1621e31aef6aSopenharmony_ci                    fp.write(item)
1622e31aef6aSopenharmony_ci        finally:
1623e31aef6aSopenharmony_ci            if close:
1624e31aef6aSopenharmony_ci                fp.close()
1625e31aef6aSopenharmony_ci
1626e31aef6aSopenharmony_ci    def disable_buffering(self) -> None:
1627e31aef6aSopenharmony_ci        """Disable the output buffering."""
1628e31aef6aSopenharmony_ci        self._next = partial(next, self._gen)
1629e31aef6aSopenharmony_ci        self.buffered = False
1630e31aef6aSopenharmony_ci
1631e31aef6aSopenharmony_ci    def _buffered_generator(self, size: int) -> t.Iterator[str]:
1632e31aef6aSopenharmony_ci        buf: t.List[str] = []
1633e31aef6aSopenharmony_ci        c_size = 0
1634e31aef6aSopenharmony_ci        push = buf.append
1635e31aef6aSopenharmony_ci
1636e31aef6aSopenharmony_ci        while True:
1637e31aef6aSopenharmony_ci            try:
1638e31aef6aSopenharmony_ci                while c_size < size:
1639e31aef6aSopenharmony_ci                    c = next(self._gen)
1640e31aef6aSopenharmony_ci                    push(c)
1641e31aef6aSopenharmony_ci                    if c:
1642e31aef6aSopenharmony_ci                        c_size += 1
1643e31aef6aSopenharmony_ci            except StopIteration:
1644e31aef6aSopenharmony_ci                if not c_size:
1645e31aef6aSopenharmony_ci                    return
1646e31aef6aSopenharmony_ci            yield concat(buf)
1647e31aef6aSopenharmony_ci            del buf[:]
1648e31aef6aSopenharmony_ci            c_size = 0
1649e31aef6aSopenharmony_ci
1650e31aef6aSopenharmony_ci    def enable_buffering(self, size: int = 5) -> None:
1651e31aef6aSopenharmony_ci        """Enable buffering.  Buffer `size` items before yielding them."""
1652e31aef6aSopenharmony_ci        if size <= 1:
1653e31aef6aSopenharmony_ci            raise ValueError("buffer size too small")
1654e31aef6aSopenharmony_ci
1655e31aef6aSopenharmony_ci        self.buffered = True
1656e31aef6aSopenharmony_ci        self._next = partial(next, self._buffered_generator(size))
1657e31aef6aSopenharmony_ci
1658e31aef6aSopenharmony_ci    def __iter__(self) -> "TemplateStream":
1659e31aef6aSopenharmony_ci        return self
1660e31aef6aSopenharmony_ci
1661e31aef6aSopenharmony_ci    def __next__(self) -> str:
1662e31aef6aSopenharmony_ci        return self._next()  # type: ignore
1663e31aef6aSopenharmony_ci
1664e31aef6aSopenharmony_ci
1665e31aef6aSopenharmony_ci# hook in default template class.  if anyone reads this comment: ignore that
1666e31aef6aSopenharmony_ci# it's possible to use custom templates ;-)
1667e31aef6aSopenharmony_ciEnvironment.template_class = Template
1668