]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
fix type/lint/format findings 2093/head
authorAdam Englander <adam@voltaire.claims>
Wed, 28 May 2025 17:06:54 +0000 (10:06 -0700)
committerDavid Lord <davidism@gmail.com>
Wed, 28 May 2025 17:08:39 +0000 (10:08 -0700)
23 files changed:
src/jinja2/async_utils.py
src/jinja2/compiler.py
src/jinja2/debug.py
src/jinja2/defaults.py
src/jinja2/environment.py
src/jinja2/ext.py
src/jinja2/filters.py
src/jinja2/idtracking.py
src/jinja2/lexer.py
src/jinja2/loaders.py
src/jinja2/meta.py
src/jinja2/nodes.py
src/jinja2/parser.py
src/jinja2/runtime.py
src/jinja2/sandbox.py
src/jinja2/utils.py
src/jinja2/visitor.py
tests/test_async.py
tests/test_core_tags.py
tests/test_debug.py
tests/test_ext.py
tests/test_filters.py
tests/test_lexnparse.py

index f0c140205c50a3df9863ce1ab610b0c62a483f1b..182ffb0a7ffc658b824c90b2afc45bec2e2c6331 100644 (file)
@@ -95,5 +95,5 @@ def auto_aiter(
 
 async def auto_to_list(
     value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
-) -> t.List["V"]:
+) -> list["V"]:
     return [x async for x in auto_aiter(value)]
index a4ff6a1b11af3e1a868d1a74c48d842390259b43..3931ff0d5f17a20ba6b357aa218640f51cfea7a6 100644 (file)
@@ -139,9 +139,7 @@ def has_safe_repr(value: t.Any) -> bool:
     return False
 
 
-def find_undeclared(
-    nodes: t.Iterable[nodes.Node], names: t.Iterable[str]
-) -> t.Set[str]:
+def find_undeclared(nodes: t.Iterable[nodes.Node], names: t.Iterable[str]) -> set[str]:
     """Check if the names passed are accessed undeclared.  The return value
     is a set of all the undeclared names from the sequence of names found.
     """
@@ -253,8 +251,8 @@ class DependencyFinderVisitor(NodeVisitor):
     """A visitor that collects filter and test calls."""
 
     def __init__(self) -> None:
-        self.filters: t.Set[str] = set()
-        self.tests: t.Set[str] = set()
+        self.filters: set[str] = set()
+        self.tests: set[str] = set()
 
     def visit_Filter(self, node: nodes.Filter) -> None:
         self.generic_visit(node)
@@ -276,7 +274,7 @@ class UndeclaredNameVisitor(NodeVisitor):
 
     def __init__(self, names: t.Iterable[str]) -> None:
         self.names = set(names)
-        self.undeclared: t.Set[str] = set()
+        self.undeclared: set[str] = set()
 
     def visit_Name(self, node: nodes.Name) -> None:
         if node.ctx == "load" and node.name in self.names:
@@ -321,11 +319,11 @@ class CodeGenerator(NodeVisitor):
             self.optimizer = Optimizer(environment)
 
         # aliases for imports
-        self.import_aliases: t.Dict[str, str] = {}
+        self.import_aliases: dict[str, str] = {}
 
         # a registry for all blocks.  Because blocks are moved out
         # into the global python scope they are registered here
-        self.blocks: t.Dict[str, nodes.Block] = {}
+        self.blocks: dict[str, nodes.Block] = {}
 
         # the number of extends statements so far
         self.extends_so_far = 0
@@ -339,11 +337,11 @@ class CodeGenerator(NodeVisitor):
         self.code_lineno = 1
 
         # registry of all filters and tests (global, not block local)
-        self.tests: t.Dict[str, str] = {}
-        self.filters: t.Dict[str, str] = {}
+        self.tests: dict[str, str] = {}
+        self.filters: dict[str, str] = {}
 
         # the debug information
-        self.debug_info: t.List[t.Tuple[int, int]] = []
+        self.debug_info: list[tuple[int, int]] = []
         self._write_debug_info: t.Optional[int] = None
 
         # the number of new lines before the next write()
@@ -363,10 +361,10 @@ class CodeGenerator(NodeVisitor):
         self._indentation = 0
 
         # Tracks toplevel assignments
-        self._assign_stack: t.List[t.Set[str]] = []
+        self._assign_stack: list[set[str]] = []
 
         # Tracks parameter definition blocks
-        self._param_def_block: t.List[t.Set[str]] = []
+        self._param_def_block: list[set[str]] = []
 
         # Tracks the current context.
         self._context_reference_stack = ["context"]
@@ -613,7 +611,7 @@ class CodeGenerator(NodeVisitor):
 
     def macro_body(
         self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame
-    ) -> t.Tuple[Frame, MacroRef]:
+    ) -> tuple[Frame, MacroRef]:
         """Dump the function def of a macro or call block."""
         frame = frame.inner()
         frame.symbols.analyze_node(node)
@@ -1511,7 +1509,7 @@ class CodeGenerator(NodeVisitor):
             self.indent()
 
         finalize = self._make_finalize()
-        body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = []
+        body: list[t.Union[list[t.Any], nodes.Expr]] = []
 
         # Evaluate constants at compile time if possible. Each item in
         # body will be either a list of static data or a node to be
@@ -1586,7 +1584,7 @@ class CodeGenerator(NodeVisitor):
         # it is only valid if it references a Namespace object. Emit a check for
         # that for each ref here, before assignment code is emitted. This can't
         # be done in visit_NSRef as the ref could be in the middle of a tuple.
-        seen_refs: t.Set[str] = set()
+        seen_refs: set[str] = set()
 
         for nsref in node.find_all(nodes.NSRef):
             if nsref.name in seen_refs:
index f85a319eeed3db874d6d9df3f3e23f28d490ae81..41265d4f3a53422b0b5a98e2b3bdbf643a61e5af 100644 (file)
@@ -128,7 +128,7 @@ def fake_traceback(  # type: ignore
         return sys.exc_info()[2].tb_next  # type: ignore
 
 
-def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]:
+def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> dict[str, t.Any]:
     """Based on the runtime locals, get the context that would be
     available at that point in the template.
     """
@@ -136,7 +136,7 @@ def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any
     ctx: t.Optional[Context] = real_locals.get("context")
 
     if ctx is not None:
-        data: t.Dict[str, t.Any] = ctx.get_all().copy()
+        data: dict[str, t.Any] = ctx.get_all().copy()
     else:
         data = {}
 
@@ -144,7 +144,7 @@ def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any
     # rather than pushing a context. Local variables follow the scheme
     # l_depth_name. Find the highest-depth local that has a value for
     # each name.
-    local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {}
+    local_overrides: dict[str, tuple[int, t.Any]] = {}
 
     for name, value in real_locals.items():
         if not name.startswith("l_") or value is missing:
index 638cad3d2d8907330bde56e2b76c9b185c523b45..b698c67ec4deb48838f8178aad78e28dbacb29de 100644 (file)
@@ -36,7 +36,7 @@ DEFAULT_NAMESPACE = {
 }
 
 # default policies
-DEFAULT_POLICIES: t.Dict[str, t.Any] = {
+DEFAULT_POLICIES: dict[str, t.Any] = {
     "compiler.ascii_str": True,
     "urlize.rel": "noopener",
     "urlize.target": None,
index a99cc2d1dda8b3c399cebc2e063670e3c80db7a3..af6420b71df51d2dc2cf00c38a97426f8ec6fedf 100644 (file)
@@ -66,7 +66,7 @@ _env_bound = t.TypeVar("_env_bound", bound="Environment")
 
 # for direct template usage we have up to ten living environments
 @lru_cache(maxsize=10)
-def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound:
+def get_spontaneous_environment(cls: type[_env_bound], *args: t.Any) -> _env_bound:
     """Return a new spontaneous environment. A spontaneous environment
     is used for templates created directly rather than through an
     existing environment.
@@ -81,7 +81,7 @@ def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_b
 
 def create_cache(
     size: int,
-) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[BaseLoader]", str], "Template"]]:
+) -> t.Optional[t.MutableMapping[tuple["weakref.ref[BaseLoader]", str], "Template"]]:
     """Return the cache class for the given size."""
     if size == 0:
         return None
@@ -94,9 +94,9 @@ def create_cache(
 
 def copy_cache(
     cache: t.Optional[
-        t.MutableMapping[t.Tuple["weakref.ref[BaseLoader]", str], "Template"]
+        t.MutableMapping[tuple["weakref.ref[BaseLoader]", str], "Template"]
     ],
-) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[BaseLoader]", str], "Template"]]:
+) -> t.Optional[t.MutableMapping[tuple["weakref.ref[BaseLoader]", str], "Template"]]:
     """Create an empty copy of the given cache."""
     if cache is None:
         return None
@@ -109,8 +109,8 @@ def copy_cache(
 
 def load_extensions(
     environment: "Environment",
-    extensions: t.Sequence[t.Union[str, t.Type["Extension"]]],
-) -> t.Dict[str, "Extension"]:
+    extensions: t.Sequence[t.Union[str, type["Extension"]]],
+) -> dict[str, "Extension"]:
     """Load the extensions from the list and bind it to the environment.
     Returns a dict of instantiated extensions.
     """
@@ -118,7 +118,7 @@ def load_extensions(
 
     for extension in extensions:
         if isinstance(extension, str):
-            extension = t.cast(t.Type["Extension"], import_string(extension))
+            extension = t.cast(type["Extension"], import_string(extension))
 
         result[extension.identifier] = extension(environment)
 
@@ -127,9 +127,9 @@ def load_extensions(
 
 def _environment_config_check(environment: _env_bound) -> _env_bound:
     """Perform a sanity check on the environment."""
-    assert issubclass(
-        environment.undefined, Undefined
-    ), "'undefined' must be a subclass of 'jinja2.Undefined'."
+    assert issubclass(environment.undefined, Undefined), (
+        "'undefined' must be a subclass of 'jinja2.Undefined'."
+    )
     assert (
         environment.block_start_string
         != environment.variable_start_string
@@ -283,15 +283,15 @@ class Environment:
 
     #: the class that is used for code generation.  See
     #: :class:`~jinja2.compiler.CodeGenerator` for more information.
-    code_generator_class: t.Type["CodeGenerator"] = CodeGenerator
+    code_generator_class: type["CodeGenerator"] = CodeGenerator
 
     concat = "".join
 
     #: the context class that is used for templates.  See
     #: :class:`~jinja2.runtime.Context` for more information.
-    context_class: t.Type[Context] = Context
+    context_class: type[Context] = Context
 
-    template_class: t.Type["Template"]
+    template_class: type["Template"]
 
     def __init__(
         self,
@@ -307,9 +307,9 @@ class Environment:
         lstrip_blocks: bool = LSTRIP_BLOCKS,
         newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE,
         keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE,
-        extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (),
+        extensions: t.Sequence[t.Union[str, type["Extension"]]] = (),
         optimized: bool = True,
-        undefined: t.Type[Undefined] = Undefined,
+        undefined: type[Undefined] = Undefined,
         finalize: t.Optional[t.Callable[..., t.Any]] = None,
         autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False,
         loader: t.Optional["BaseLoader"] = None,
@@ -344,7 +344,7 @@ class Environment:
         self.keep_trailing_newline = keep_trailing_newline
 
         # runtime information
-        self.undefined: t.Type[Undefined] = undefined
+        self.undefined: type[Undefined] = undefined
         self.optimized = optimized
         self.finalize = finalize
         self.autoescape = autoescape
@@ -369,7 +369,7 @@ class Environment:
         self.is_async = enable_async
         _environment_config_check(self)
 
-    def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None:
+    def add_extension(self, extension: t.Union[str, type["Extension"]]) -> None:
         """Adds an extension after the environment was created.
 
         .. versionadded:: 2.5
@@ -399,9 +399,9 @@ class Environment:
         lstrip_blocks: bool = missing,
         newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing,
         keep_trailing_newline: bool = missing,
-        extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing,
+        extensions: t.Sequence[t.Union[str, type["Extension"]]] = missing,
         optimized: bool = missing,
-        undefined: t.Type[Undefined] = missing,
+        undefined: type[Undefined] = missing,
         finalize: t.Optional[t.Callable[..., t.Any]] = missing,
         autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing,
         loader: t.Optional["BaseLoader"] = missing,
@@ -628,7 +628,7 @@ class Environment:
         source: str,
         name: t.Optional[str] = None,
         filename: t.Optional[str] = None,
-    ) -> t.Iterator[t.Tuple[int, str, str]]:
+    ) -> t.Iterator[tuple[int, str, str]]:
         """Lex the given sourcecode and return a generator that yields
         tokens as tuples in the form ``(lineno, token_type, value)``.
         This can be useful for :ref:`extension development <writing-extensions>`
@@ -677,7 +677,7 @@ class Environment:
             stream = ext.filter_stream(stream)  # type: ignore
 
             if not isinstance(stream, TokenStream):
-                stream = TokenStream(stream, name, filename)  # type: ignore[unreachable]
+                stream = TokenStream(stream, name, filename)
 
         return stream
 
@@ -902,7 +902,7 @@ class Environment:
         self,
         extensions: t.Optional[t.Collection[str]] = None,
         filter_func: t.Optional[t.Callable[[str], bool]] = None,
-    ) -> t.List[str]:
+    ) -> list[str]:
         """Returns a list of templates for this environment.  This requires
         that the loader supports the loader's
         :meth:`~BaseLoader.list_templates` method.
@@ -1074,9 +1074,7 @@ class Environment:
     @internalcode
     def get_or_select_template(
         self,
-        template_name_or_list: t.Union[
-            str, "Template", t.List[t.Union[str, "Template"]]
-        ],
+        template_name_or_list: t.Union[str, "Template", list[t.Union[str, "Template"]]],
         parent: t.Optional[str] = None,
         globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
     ) -> "Template":
@@ -1095,7 +1093,7 @@ class Environment:
         self,
         source: t.Union[str, nodes.Template],
         globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
-        template_class: t.Optional[t.Type["Template"]] = None,
+        template_class: t.Optional[type["Template"]] = None,
     ) -> "Template":
         """Load a template from a source string without using
         :attr:`loader`.
@@ -1154,13 +1152,13 @@ class Template:
 
     #: Type of environment to create when creating a template directly
     #: rather than through an existing environment.
-    environment_class: t.Type[Environment] = Environment
+    environment_class: type[Environment] = Environment
 
     environment: Environment
     globals: t.MutableMapping[str, t.Any]
     name: t.Optional[str]
     filename: t.Optional[str]
-    blocks: t.Dict[str, t.Callable[[Context], t.Iterator[str]]]
+    blocks: dict[str, t.Callable[[Context], t.Iterator[str]]]
     root_render_func: t.Callable[[Context], t.Iterator[str]]
     _module: t.Optional["TemplateModule"]
     _debug_info: str
@@ -1181,9 +1179,9 @@ class Template:
         lstrip_blocks: bool = LSTRIP_BLOCKS,
         newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE,
         keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE,
-        extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (),
+        extensions: t.Sequence[t.Union[str, type["Extension"]]] = (),
         optimized: bool = True,
-        undefined: t.Type[Undefined] = Undefined,
+        undefined: type[Undefined] = Undefined,
         finalize: t.Optional[t.Callable[..., t.Any]] = None,
         autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False,
         enable_async: bool = False,
@@ -1336,7 +1334,7 @@ class Template:
         if self.environment.is_async:
             import asyncio
 
-            async def to_list() -> t.List[str]:
+            async def to_list() -> list[str]:
                 return [x async for x in self.generate_async(*args, **kwargs)]
 
             yield from asyncio.run(to_list())
@@ -1376,7 +1374,7 @@ class Template:
 
     def new_context(
         self,
-        vars: t.Optional[t.Dict[str, t.Any]] = None,
+        vars: t.Optional[dict[str, t.Any]] = None,
         shared: bool = False,
         locals: t.Optional[t.Mapping[str, t.Any]] = None,
     ) -> Context:
@@ -1393,7 +1391,7 @@ class Template:
 
     def make_module(
         self,
-        vars: t.Optional[t.Dict[str, t.Any]] = None,
+        vars: t.Optional[dict[str, t.Any]] = None,
         shared: bool = False,
         locals: t.Optional[t.Mapping[str, t.Any]] = None,
     ) -> "TemplateModule":
@@ -1408,7 +1406,7 @@ class Template:
 
     async def make_module_async(
         self,
-        vars: t.Optional[t.Dict[str, t.Any]] = None,
+        vars: t.Optional[dict[str, t.Any]] = None,
         shared: bool = False,
         locals: t.Optional[t.Mapping[str, t.Any]] = None,
     ) -> "TemplateModule":
@@ -1498,7 +1496,7 @@ class Template:
         return self._uptodate()
 
     @property
-    def debug_info(self) -> t.List[t.Tuple[int, int]]:
+    def debug_info(self) -> list[tuple[int, int]]:
         """The debug info mapping."""
         if self._debug_info:
             return [
@@ -1636,7 +1634,7 @@ class TemplateStream:
         self.buffered = False
 
     def _buffered_generator(self, size: int) -> t.Iterator[str]:
-        buf: t.List[str] = []
+        buf: list[str] = []
         c_size = 0
         push = buf.append
 
index d8ab7eff1b2899ff9785691548ee73222243c15d..1c27df94ba247db2417d249c18654f5a065618cb 100644 (file)
@@ -42,7 +42,7 @@ if t.TYPE_CHECKING:
 
 # I18N functions available in Jinja templates. If the I18N library
 # provides ugettext, it will be assigned to gettext.
-GETTEXT_FUNCTIONS: t.Tuple[str, ...] = (
+GETTEXT_FUNCTIONS: tuple[str, ...] = (
     "_",
     "gettext",
     "ngettext",
@@ -77,7 +77,7 @@ class Extension:
         cls.identifier = f"{cls.__module__}.{cls.__name__}"
 
     #: if this extension parses this is the list of tags it's listening to.
-    tags: t.Set[str] = set()
+    tags: set[str] = set()
 
     #: the priority of that extension.  This is especially useful for
     #: extensions that preprocess values.  A lower value means higher
@@ -115,7 +115,7 @@ class Extension:
         """
         return stream
 
-    def parse(self, parser: "Parser") -> t.Union[nodes.Node, t.List[nodes.Node]]:
+    def parse(self, parser: "Parser") -> t.Union[nodes.Node, list[nodes.Node]]:
         """If any of the :attr:`tags` matched this method is called with the
         parser as first argument.  The token the parser stream is pointing at
         is the name token that matched.  This method has to return one or a
@@ -138,8 +138,8 @@ class Extension:
     def call_method(
         self,
         name: str,
-        args: t.Optional[t.List[nodes.Expr]] = None,
-        kwargs: t.Optional[t.List[nodes.Keyword]] = None,
+        args: t.Optional[list[nodes.Expr]] = None,
+        kwargs: t.Optional[list[nodes.Keyword]] = None,
         dyn_args: t.Optional[nodes.Expr] = None,
         dyn_kwargs: t.Optional[nodes.Expr] = None,
         lineno: t.Optional[int] = None,
@@ -330,13 +330,13 @@ class InternationalizationExtension(Extension):
         source: t.Union[str, nodes.Template],
         gettext_functions: t.Sequence[str] = GETTEXT_FUNCTIONS,
     ) -> t.Iterator[
-        t.Tuple[int, str, t.Union[t.Optional[str], t.Tuple[t.Optional[str], ...]]]
+        tuple[int, str, t.Union[t.Optional[str], tuple[t.Optional[str], ...]]]
     ]:
         if isinstance(source, str):
             source = self.environment.parse(source)
         return extract_from_ast(source, gettext_functions)
 
-    def parse(self, parser: "Parser") -> t.Union[nodes.Node, t.List[nodes.Node]]:
+    def parse(self, parser: "Parser") -> t.Union[nodes.Node, list[nodes.Node]]:
         """Parse a translatable tag."""
         lineno = next(parser.stream).lineno
 
@@ -352,7 +352,7 @@ class InternationalizationExtension(Extension):
         plural_expr: t.Optional[nodes.Expr] = None
         plural_expr_assignment: t.Optional[nodes.Assign] = None
         num_called_num = False
-        variables: t.Dict[str, nodes.Expr] = {}
+        variables: dict[str, nodes.Expr] = {}
         trimmed = None
         while parser.stream.current.type != "block_end":
             if variables:
@@ -463,7 +463,7 @@ class InternationalizationExtension(Extension):
 
     def _parse_block(
         self, parser: "Parser", allow_pluralize: bool
-    ) -> t.Tuple[t.List[str], str]:
+    ) -> tuple[list[str], str]:
         """Parse until the next block tag with a given name."""
         referenced = []
         buf = []
@@ -513,7 +513,7 @@ class InternationalizationExtension(Extension):
         singular: str,
         plural: t.Optional[str],
         context: t.Optional[str],
-        variables: t.Dict[str, nodes.Expr],
+        variables: dict[str, nodes.Expr],
         plural_expr: t.Optional[nodes.Expr],
         vars_referenced: bool,
         num_called_num: bool,
@@ -530,7 +530,7 @@ class InternationalizationExtension(Extension):
                 plural = plural.replace("%%", "%")
 
         func_name = "gettext"
-        func_args: t.List[nodes.Expr] = [nodes.Const(singular)]
+        func_args: list[nodes.Expr] = [nodes.Const(singular)]
 
         if context is not None:
             func_args.insert(0, nodes.Const(context))
@@ -640,9 +640,7 @@ def extract_from_ast(
     ast: nodes.Template,
     gettext_functions: t.Sequence[str] = GETTEXT_FUNCTIONS,
     babel_style: bool = True,
-) -> t.Iterator[
-    t.Tuple[int, str, t.Union[t.Optional[str], t.Tuple[t.Optional[str], ...]]]
-]:
+) -> t.Iterator[tuple[int, str, t.Union[t.Optional[str], tuple[t.Optional[str], ...]]]]:
     """Extract localizable strings from the given template node.  Per
     default this function returns matches in babel style that means non string
     parameters as well as keyword arguments are returned as `None`.  This
@@ -677,7 +675,7 @@ def extract_from_ast(
     to extract any comments.  For comment support you have to use the babel
     extraction interface or extract comments yourself.
     """
-    out: t.Union[t.Optional[str], t.Tuple[t.Optional[str], ...]]
+    out: t.Union[t.Optional[str], tuple[t.Optional[str], ...]]
 
     for node in ast.find_all(nodes.Call):
         if (
@@ -686,7 +684,7 @@ def extract_from_ast(
         ):
             continue
 
-        strings: t.List[t.Optional[str]] = []
+        strings: list[t.Optional[str]] = []
 
         for arg in node.args:
             if isinstance(arg, nodes.Const) and isinstance(arg.value, str):
@@ -723,14 +721,14 @@ class _CommentFinder:
     """
 
     def __init__(
-        self, tokens: t.Sequence[t.Tuple[int, str, str]], comment_tags: t.Sequence[str]
+        self, tokens: t.Sequence[tuple[int, str, str]], comment_tags: t.Sequence[str]
     ) -> None:
         self.tokens = tokens
         self.comment_tags = comment_tags
         self.offset = 0
         self.last_lineno = 0
 
-    def find_backwards(self, offset: int) -> t.List[str]:
+    def find_backwards(self, offset: int) -> list[str]:
         try:
             for _, token_type, token_value in reversed(
                 self.tokens[self.offset : offset]
@@ -746,7 +744,7 @@ class _CommentFinder:
         finally:
             self.offset = offset
 
-    def find_comments(self, lineno: int) -> t.List[str]:
+    def find_comments(self, lineno: int) -> list[str]:
         if not self.comment_tags or self.last_lineno > lineno:
             return []
         for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset :]):
@@ -759,11 +757,9 @@ def babel_extract(
     fileobj: t.BinaryIO,
     keywords: t.Sequence[str],
     comment_tags: t.Sequence[str],
-    options: t.Dict[str, t.Any],
+    options: dict[str, t.Any],
 ) -> t.Iterator[
-    t.Tuple[
-        int, str, t.Union[t.Optional[str], t.Tuple[t.Optional[str], ...]], t.List[str]
-    ]
+    tuple[int, str, t.Union[t.Optional[str], tuple[t.Optional[str], ...]], list[str]]
 ]:
     """Babel extraction method for Jinja templates.
 
@@ -792,7 +788,7 @@ def babel_extract(
     :return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
              (comments will be empty currently)
     """
-    extensions: t.Dict[t.Type[Extension], None] = {}
+    extensions: dict[type[Extension], None] = {}
 
     for extension_name in options.get("extensions", "").split(","):
         extension_name = extension_name.strip()
index 2bcba4fbd3c660edb1166fcad6ef6fc9a4f6a1e5..73a0cdcefc6e198f9a4299ad9bd65638cdd56765 100644 (file)
@@ -87,7 +87,7 @@ def make_multi_attrgetter(
     environment: "Environment",
     attribute: t.Optional[t.Union[str, int]],
     postprocess: t.Optional[t.Callable[[t.Any], t.Any]] = None,
-) -> t.Callable[[t.Any], t.List[t.Any]]:
+) -> t.Callable[[t.Any], list[t.Any]]:
     """Returns a callable that looks up the given comma separated
     attributes from a passed object with the rules of the environment.
     Dots are allowed to access attributes of each attribute.  Integer
@@ -105,7 +105,7 @@ def make_multi_attrgetter(
 
     parts = [_prepare_attribute_parts(item) for item in split]
 
-    def attrgetter(item: t.Any) -> t.List[t.Any]:
+    def attrgetter(item: t.Any) -> list[t.Any]:
         items = [None] * len(parts)
 
         for i, attribute_part in enumerate(parts):
@@ -126,7 +126,7 @@ def make_multi_attrgetter(
 
 def _prepare_attribute_parts(
     attr: t.Optional[t.Union[str, int]],
-) -> t.List[t.Union[str, int]]:
+) -> list[t.Union[str, int]]:
     if attr is None:
         return []
 
@@ -145,7 +145,7 @@ def do_forceescape(value: "t.Union[str, HasHTML]") -> Markup:
 
 
 def do_urlencode(
-    value: t.Union[str, t.Mapping[str, t.Any], t.Iterable[t.Tuple[str, t.Any]]],
+    value: t.Union[str, t.Mapping[str, t.Any], t.Iterable[tuple[str, t.Any]]],
 ) -> str:
     """Quote data for use in a URL path or query using UTF-8.
 
@@ -166,7 +166,7 @@ def do_urlencode(
         return url_quote(value)
 
     if isinstance(value, dict):
-        items: t.Iterable[t.Tuple[str, t.Any]] = value.items()
+        items: t.Iterable[tuple[str, t.Any]] = value.items()
     else:
         items = value  # type: ignore
 
@@ -221,7 +221,7 @@ def do_lower(s: str) -> str:
     return soft_str(s).lower()
 
 
-def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K, V]]:
+def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[tuple[K, V]]:
     """Return an iterator over the ``(key, value)`` items of a mapping.
 
     ``x|items`` is the same as ``x.items()``, except if ``x`` is
@@ -346,7 +346,7 @@ def do_dictsort(
     case_sensitive: bool = False,
     by: 'te.Literal["key", "value"]' = "key",
     reverse: bool = False,
-) -> t.List[t.Tuple[K, V]]:
+) -> list[tuple[K, V]]:
     """Sort a dict and yield (key, value) pairs. Python dicts may not
     be in the order you want to display them in, so sort them first.
 
@@ -371,7 +371,7 @@ def do_dictsort(
     else:
         raise FilterArgumentError('You can only sort by either "key" or "value"')
 
-    def sort_func(item: t.Tuple[t.Any, t.Any]) -> t.Any:
+    def sort_func(item: tuple[t.Any, t.Any]) -> t.Any:
         value = item[pos]
 
         if not case_sensitive:
@@ -389,7 +389,7 @@ def do_sort(
     reverse: bool = False,
     case_sensitive: bool = False,
     attribute: t.Optional[t.Union[str, int]] = None,
-) -> "t.List[V]":
+) -> "list[V]":
     """Sort an iterable using Python's :func:`sorted`.
 
     .. sourcecode:: jinja
@@ -1058,7 +1058,7 @@ def do_striptags(value: "t.Union[str, HasHTML]") -> str:
 
 def sync_do_slice(
     value: "t.Collection[V]", slices: int, fill_with: "t.Optional[V]" = None
-) -> "t.Iterator[t.List[V]]":
+) -> "t.Iterator[list[V]]":
     """Slice an iterator and return a list of lists containing
     those items. Useful if you want to create a div containing
     three ul tags that represent columns:
@@ -1104,13 +1104,13 @@ async def do_slice(
     value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
     slices: int,
     fill_with: t.Optional[t.Any] = None,
-) -> "t.Iterator[t.List[V]]":
+) -> "t.Iterator[list[V]]":
     return sync_do_slice(await auto_to_list(value), slices, fill_with)
 
 
 def do_batch(
     value: "t.Iterable[V]", linecount: int, fill_with: "t.Optional[V]" = None
-) -> "t.Iterator[t.List[V]]":
+) -> "t.Iterator[list[V]]":
     """
     A filter that batches items. It works pretty much like `slice`
     just the other way round. It returns a list of lists with the
@@ -1129,7 +1129,7 @@ def do_batch(
         {%- endfor %}
         </table>
     """
-    tmp: t.List[V] = []
+    tmp: list[V] = []
 
     for item in value:
         if len(tmp) == linecount:
@@ -1187,7 +1187,7 @@ def do_round(
 
 class _GroupTuple(t.NamedTuple):
     grouper: t.Any
-    list: t.List[t.Any]
+    list: list[t.Any]
 
     # Use the regular tuple repr to hide this subclass if users print
     # out the value during debugging.
@@ -1205,7 +1205,7 @@ def sync_do_groupby(
     attribute: t.Union[str, int],
     default: t.Optional[t.Any] = None,
     case_sensitive: bool = False,
-) -> "t.List[_GroupTuple]":
+) -> "list[_GroupTuple]":
     """Group a sequence of objects by an attribute using Python's
     :func:`itertools.groupby`. The attribute can use dot notation for
     nested access, like ``"address.city"``. Unlike Python's ``groupby``,
@@ -1289,7 +1289,7 @@ async def do_groupby(
     attribute: t.Union[str, int],
     default: t.Optional[t.Any] = None,
     case_sensitive: bool = False,
-) -> "t.List[_GroupTuple]":
+) -> "list[_GroupTuple]":
     expr = make_attrgetter(
         environment,
         attribute,
@@ -1358,7 +1358,7 @@ async def do_sum(
     return rv
 
 
-def sync_do_list(value: "t.Iterable[V]") -> "t.List[V]":
+def sync_do_list(value: "t.Iterable[V]") -> "list[V]":
     """Convert the value into a list.  If it was a string the returned list
     will be a list of characters.
     """
@@ -1366,7 +1366,7 @@ def sync_do_list(value: "t.Iterable[V]") -> "t.List[V]":
 
 
 @async_variant(sync_do_list)  # type: ignore
-async def do_list(value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]") -> "t.List[V]":
+async def do_list(value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]") -> "list[V]":
     return await auto_to_list(value)
 
 
@@ -1722,7 +1722,7 @@ def do_tojson(
 
 
 def prepare_map(
-    context: "Context", args: t.Tuple[t.Any, ...], kwargs: t.Dict[str, t.Any]
+    context: "Context", args: tuple[t.Any, ...], kwargs: dict[str, t.Any]
 ) -> t.Callable[[t.Any], t.Any]:
     if not args and "attribute" in kwargs:
         attribute = kwargs.pop("attribute")
@@ -1751,8 +1751,8 @@ def prepare_map(
 
 def prepare_select_or_reject(
     context: "Context",
-    args: t.Tuple[t.Any, ...],
-    kwargs: t.Dict[str, t.Any],
+    args: tuple[t.Any, ...],
+    kwargs: dict[str, t.Any],
     modfunc: t.Callable[[t.Any], t.Any],
     lookup_attr: bool,
 ) -> t.Callable[[t.Any], t.Any]:
@@ -1786,8 +1786,8 @@ def prepare_select_or_reject(
 def select_or_reject(
     context: "Context",
     value: "t.Iterable[V]",
-    args: t.Tuple[t.Any, ...],
-    kwargs: t.Dict[str, t.Any],
+    args: tuple[t.Any, ...],
+    kwargs: dict[str, t.Any],
     modfunc: t.Callable[[t.Any], t.Any],
     lookup_attr: bool,
 ) -> "t.Iterator[V]":
@@ -1802,8 +1802,8 @@ def select_or_reject(
 async def async_select_or_reject(
     context: "Context",
     value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
-    args: t.Tuple[t.Any, ...],
-    kwargs: t.Dict[str, t.Any],
+    args: tuple[t.Any, ...],
+    kwargs: dict[str, t.Any],
     modfunc: t.Callable[[t.Any], t.Any],
     lookup_attr: bool,
 ) -> "t.AsyncIterator[V]":
index e6dd8cd1110e138770652506a40a5c34101508cc..d04c6d7f06584e4a30492ea7682389ec90017bf6 100644 (file)
@@ -42,16 +42,16 @@ class Symbols:
 
         self.level: int = level
         self.parent = parent
-        self.refs: t.Dict[str, str] = {}
-        self.loads: t.Dict[str, t.Any] = {}
-        self.stores: t.Set[str] = set()
+        self.refs: dict[str, str] = {}
+        self.loads: dict[str, t.Any] = {}
+        self.stores: set[str] = set()
 
     def analyze_node(self, node: nodes.Node, **kwargs: t.Any) -> None:
         visitor = RootVisitor(self)
         visitor.visit(node, **kwargs)
 
     def _define_ref(
-        self, name: str, load: t.Optional[t.Tuple[str, t.Optional[str]]] = None
+        self, name: str, load: t.Optional[tuple[str, t.Optional[str]]] = None
     ) -> str:
         ident = f"l_{self.level}_{name}"
         self.refs[name] = ident
@@ -121,7 +121,7 @@ class Symbols:
             self._define_ref(name, load=(VAR_LOAD_RESOLVE, name))
 
     def branch_update(self, branch_symbols: t.Sequence["Symbols"]) -> None:
-        stores: t.Set[str] = set()
+        stores: set[str] = set()
 
         for branch in branch_symbols:
             stores.update(branch.stores)
@@ -144,8 +144,8 @@ class Symbols:
                     continue
             self.loads[target] = (VAR_LOAD_RESOLVE, name)
 
-    def dump_stores(self) -> t.Dict[str, str]:
-        rv: t.Dict[str, str] = {}
+    def dump_stores(self) -> dict[str, str]:
+        rv: dict[str, str] = {}
         node: t.Optional[Symbols] = self
 
         while node is not None:
@@ -157,7 +157,7 @@ class Symbols:
 
         return rv
 
-    def dump_param_targets(self) -> t.Set[str]:
+    def dump_param_targets(self) -> set[str]:
         rv = set()
         node: t.Optional[Symbols] = self
 
index 9b1c969791f2ab4a263d6708d7c2d682f47f7387..d96e9a08790db310727b3813a61925e1a8529c61 100644 (file)
@@ -21,7 +21,7 @@ if t.TYPE_CHECKING:
 
 # cache for the lexers. Exists in order to be able to have multiple
 # environments with the same lexer
-_lexer_cache: t.MutableMapping[t.Tuple, "Lexer"] = LRUCache(50)  # type: ignore
+_lexer_cache: t.MutableMapping[tuple, "Lexer"] = LRUCache(50)  # type: ignore
 
 # static regular expressions
 whitespace_re = re.compile(r"\s+")
@@ -210,7 +210,7 @@ def count_newlines(value: str) -> int:
     return len(newline_re.findall(value))
 
 
-def compile_rules(environment: "Environment") -> t.List[t.Tuple[str, str]]:
+def compile_rules(environment: "Environment") -> list[tuple[str, str]]:
     """Compiles all the rules from the environment into a list of rules."""
     e = re.escape
     rules = [
@@ -257,7 +257,7 @@ class Failure:
     """
 
     def __init__(
-        self, message: str, cls: t.Type[TemplateSyntaxError] = TemplateSyntaxError
+        self, message: str, cls: type[TemplateSyntaxError] = TemplateSyntaxError
     ) -> None:
         self.message = message
         self.error_class = cls
@@ -329,7 +329,7 @@ class TokenStream:
         filename: t.Optional[str],
     ):
         self._iter = iter(generator)
-        self._pushed: te.Deque[Token] = deque()
+        self._pushed: deque[Token] = deque()
         self.name = name
         self.filename = filename
         self.closed = False
@@ -464,7 +464,7 @@ class OptionalLStrip(tuple):  # type: ignore[type-arg]
 
 class _Rule(t.NamedTuple):
     pattern: t.Pattern[str]
-    tokens: t.Union[str, t.Tuple[str, ...], t.Tuple[Failure]]
+    tokens: t.Union[str, tuple[str, ...], tuple[Failure]]
     command: t.Optional[str]
 
 
@@ -484,7 +484,7 @@ class Lexer:
             return re.compile(x, re.M | re.S)
 
         # lexing rules for tags
-        tag_rules: t.List[_Rule] = [
+        tag_rules: list[_Rule] = [
             _Rule(whitespace_re, TOKEN_WHITESPACE, None),
             _Rule(float_re, TOKEN_FLOAT, None),
             _Rule(integer_re, TOKEN_INTEGER, None),
@@ -523,7 +523,7 @@ class Lexer:
         )
 
         # global lexing rules
-        self.rules: t.Dict[str, t.List[_Rule]] = {
+        self.rules: dict[str, list[_Rule]] = {
             "root": [
                 # directives
                 _Rule(
@@ -614,7 +614,7 @@ class Lexer:
 
     def wrap(
         self,
-        stream: t.Iterable[t.Tuple[int, str, str]],
+        stream: t.Iterable[tuple[int, str, str]],
         name: t.Optional[str] = None,
         filename: t.Optional[str] = None,
     ) -> t.Iterator[Token]:
@@ -672,7 +672,7 @@ class Lexer:
         name: t.Optional[str],
         filename: t.Optional[str] = None,
         state: t.Optional[str] = None,
-    ) -> t.Iterator[t.Tuple[int, str, str]]:
+    ) -> t.Iterator[tuple[int, str, str]]:
         """This method tokenizes the text and returns the tokens in a
         generator. Use this method if you just want to tokenize a template.
 
@@ -696,7 +696,7 @@ class Lexer:
 
         statetokens = self.rules[stack[-1]]
         source_length = len(source)
-        balancing_stack: t.List[str] = []
+        balancing_stack: list[str] = []
         newlines_stripped = 0
         line_starting = True
 
index 725ecfcd579d079823ff8b17ab84a46e12bed094..e14613f7cc9808370e4b434bfb8952342f1bc53c 100644 (file)
@@ -22,7 +22,7 @@ if t.TYPE_CHECKING:
     from .environment import Template
 
 
-def split_template_path(template: str) -> t.List[str]:
+def split_template_path(template: str) -> list[str]:
     """Split a path into segments and perform a sanity check.  If it detects
     '..' in the path it will raise a `TemplateNotFound` error.
     """
@@ -74,7 +74,7 @@ class BaseLoader:
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
+    ) -> tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
         """Get the template source, filename and reload helper for a template.
         It's passed the environment and template name and has to return a
         tuple in the form ``(source, filename, uptodate)`` or raise a
@@ -98,7 +98,7 @@ class BaseLoader:
             )
         raise TemplateNotFound(template)
 
-    def list_templates(self) -> t.List[str]:
+    def list_templates(self) -> list[str]:
         """Iterates over all templates.  If the loader does not support that
         it should raise a :exc:`TypeError` which is the default behavior.
         """
@@ -193,7 +193,7 @@ class FileSystemLoader(BaseLoader):
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, str, t.Callable[[], bool]]:
+    ) -> tuple[str, str, t.Callable[[], bool]]:
         pieces = split_template_path(template)
 
         for searchpath in self.searchpath:
@@ -225,7 +225,7 @@ class FileSystemLoader(BaseLoader):
         # Use normpath to convert Windows altsep to sep.
         return contents, os.path.normpath(filename), uptodate
 
-    def list_templates(self) -> t.List[str]:
+    def list_templates(self) -> list[str]:
         found = set()
         for searchpath in self.searchpath:
             walk_dir = os.walk(searchpath, followlinks=self.followlinks)
@@ -245,24 +245,23 @@ class FileSystemLoader(BaseLoader):
 
 if sys.version_info >= (3, 13):
 
-    def _get_zipimporter_files(z: t.Any) -> t.Dict[str, object]:
+    def _get_zipimporter_files(z: t.Any) -> dict[str, object]:
         try:
             get_files = z._get_files
         except AttributeError as e:
             raise TypeError(
-                "This zip import does not have the required"
-                " metadata to list templates."
+                "This zip import does not have the required metadata to list templates."
             ) from e
         return get_files()
+
 else:
 
-    def _get_zipimporter_files(z: t.Any) -> t.Dict[str, object]:
+    def _get_zipimporter_files(z: t.Any) -> dict[str, object]:
         try:
             files = z._files
         except AttributeError as e:
             raise TypeError(
-                "This zip import does not have the required"
-                " metadata to list templates."
+                "This zip import does not have the required metadata to list templates."
             ) from e
         return files  # type: ignore[no-any-return]
 
@@ -333,7 +332,7 @@ class PackageLoader(BaseLoader):
             pkgdir = next(iter(spec.submodule_search_locations))  # type: ignore
             template_root = os.path.join(pkgdir, package_path).rstrip(os.sep)
         else:
-            roots: t.List[str] = []
+            roots: list[str] = []
 
             # One element for regular packages, multiple for namespace
             # packages, or None for single module file.
@@ -365,7 +364,7 @@ class PackageLoader(BaseLoader):
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, str, t.Optional[t.Callable[[], bool]]]:
+    ) -> tuple[str, str, t.Optional[t.Callable[[], bool]]]:
         # Use posixpath even on Windows to avoid "drive:" or UNC
         # segments breaking out of the search directory. Use normpath to
         # convert Windows altsep to sep.
@@ -401,8 +400,8 @@ class PackageLoader(BaseLoader):
 
         return source.decode(self.encoding), p, up_to_date
 
-    def list_templates(self) -> t.List[str]:
-        results: t.List[str] = []
+    def list_templates(self) -> list[str]:
+        results: list[str] = []
 
         if self._archive is None:
             # Package is a directory.
@@ -444,13 +443,13 @@ class DictLoader(BaseLoader):
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, None, t.Callable[[], bool]]:
+    ) -> tuple[str, None, t.Callable[[], bool]]:
         if template in self.mapping:
             source = self.mapping[template]
             return source, None, lambda: source == self.mapping.get(template)
         raise TemplateNotFound(template)
 
-    def list_templates(self) -> t.List[str]:
+    def list_templates(self) -> list[str]:
         return sorted(self.mapping)
 
 
@@ -478,7 +477,7 @@ class FunctionLoader(BaseLoader):
             [str],
             t.Optional[
                 t.Union[
-                    str, t.Tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]
+                    str, tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]
                 ]
             ],
         ],
@@ -487,7 +486,7 @@ class FunctionLoader(BaseLoader):
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
+    ) -> tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
         rv = self.load_func(template)
 
         if rv is None:
@@ -520,7 +519,7 @@ class PrefixLoader(BaseLoader):
         self.mapping = mapping
         self.delimiter = delimiter
 
-    def get_loader(self, template: str) -> t.Tuple[BaseLoader, str]:
+    def get_loader(self, template: str) -> tuple[BaseLoader, str]:
         try:
             prefix, name = template.split(self.delimiter, 1)
             loader = self.mapping[prefix]
@@ -530,7 +529,7 @@ class PrefixLoader(BaseLoader):
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
+    ) -> tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
         loader, name = self.get_loader(template)
         try:
             return loader.get_source(environment, name)
@@ -554,7 +553,7 @@ class PrefixLoader(BaseLoader):
             # (the one that includes the prefix)
             raise TemplateNotFound(name) from e
 
-    def list_templates(self) -> t.List[str]:
+    def list_templates(self) -> list[str]:
         result = []
         for prefix, loader in self.mapping.items():
             for template in loader.list_templates():
@@ -581,7 +580,7 @@ class ChoiceLoader(BaseLoader):
 
     def get_source(
         self, environment: "Environment", template: str
-    ) -> t.Tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
+    ) -> tuple[str, t.Optional[str], t.Optional[t.Callable[[], bool]]]:
         for loader in self.loaders:
             try:
                 return loader.get_source(environment, template)
@@ -603,7 +602,7 @@ class ChoiceLoader(BaseLoader):
                 pass
         raise TemplateNotFound(name)
 
-    def list_templates(self) -> t.List[str]:
+    def list_templates(self) -> list[str]:
         found = set()
         for loader in self.loaders:
             found.update(loader.list_templates())
index 298499e265253fb4cc5f365ea147043d0a83c6f9..33094812415aec6a47f639795d598eaaf126a3c0 100644 (file)
@@ -17,7 +17,7 @@ class TrackingCodeGenerator(CodeGenerator):
 
     def __init__(self, environment: "Environment") -> None:
         super().__init__(environment, "<introspection>", "<introspection>")
-        self.undeclared_identifiers: t.Set[str] = set()
+        self.undeclared_identifiers: set[str] = set()
 
     def write(self, x: str) -> None:
         """Don't write."""
@@ -31,7 +31,7 @@ class TrackingCodeGenerator(CodeGenerator):
                 self.undeclared_identifiers.add(param)
 
 
-def find_undeclared_variables(ast: nodes.Template) -> t.Set[str]:
+def find_undeclared_variables(ast: nodes.Template) -> set[str]:
     """Returns a set of all variables in the AST that will be looked up from
     the context at runtime.  Because at compile time it's not known which
     variables will be used depending on the path the execution takes at
index 2f93b90ec21e2302cc7149504f73b8d9cab472d9..dc8d72ba18bfe0848ffd33799997749a616b7442 100644 (file)
@@ -19,7 +19,7 @@ if t.TYPE_CHECKING:
 
 _NodeBound = t.TypeVar("_NodeBound", bound="Node")
 
-_binop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
+_binop_to_func: dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
     "*": operator.mul,
     "/": operator.truediv,
     "//": operator.floordiv,
@@ -29,13 +29,13 @@ _binop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
     "-": operator.sub,
 }
 
-_uaop_to_func: t.Dict[str, t.Callable[[t.Any], t.Any]] = {
+_uaop_to_func: dict[str, t.Callable[[t.Any], t.Any]] = {
     "not": operator.not_,
     "+": operator.pos,
     "-": operator.neg,
 }
 
-_cmpop_to_func: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
+_cmpop_to_func: dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
     "eq": operator.eq,
     "ne": operator.ne,
     "gt": operator.gt,
@@ -58,7 +58,7 @@ class NodeType(type):
 
     def __new__(mcs, name, bases, d):  # type: ignore
         for attr in "fields", "attributes":
-            storage: t.List[t.Tuple[str, ...]] = []
+            storage: list[tuple[str, ...]] = []
             storage.extend(getattr(bases[0] if bases else object, attr, ()))
             storage.extend(d.get(attr, ()))
             assert len(bases) <= 1, "multiple inheritance not allowed"
@@ -119,8 +119,8 @@ class Node(metaclass=NodeType):
     all nodes automatically.
     """
 
-    fields: t.Tuple[str, ...] = ()
-    attributes: t.Tuple[str, ...] = ("lineno", "environment")
+    fields: tuple[str, ...] = ()
+    attributes: tuple[str, ...] = ("lineno", "environment")
     abstract = True
 
     lineno: int
@@ -148,7 +148,7 @@ class Node(metaclass=NodeType):
         self,
         exclude: t.Optional[t.Container[str]] = None,
         only: t.Optional[t.Container[str]] = None,
-    ) -> t.Iterator[t.Tuple[str, t.Any]]:
+    ) -> t.Iterator[tuple[str, t.Any]]:
         """This method iterates over all fields that are defined and yields
         ``(key, value)`` tuples.  Per default all fields are returned, but
         it's possible to limit that to some fields by providing the `only`
@@ -183,7 +183,7 @@ class Node(metaclass=NodeType):
             elif isinstance(item, Node):
                 yield item
 
-    def find(self, node_type: t.Type[_NodeBound]) -> t.Optional[_NodeBound]:
+    def find(self, node_type: type[_NodeBound]) -> t.Optional[_NodeBound]:
         """Find the first node of a given type.  If no such node exists the
         return value is `None`.
         """
@@ -193,7 +193,7 @@ class Node(metaclass=NodeType):
         return None
 
     def find_all(
-        self, node_type: t.Union[t.Type[_NodeBound], t.Tuple[t.Type[_NodeBound], ...]]
+        self, node_type: t.Union[type[_NodeBound], tuple[type[_NodeBound], ...]]
     ) -> t.Iterator[_NodeBound]:
         """Find all the nodes of a given type.  If the type is a tuple,
         the check is performed for any of the tuple items.
@@ -274,7 +274,7 @@ class Node(metaclass=NodeType):
                     _dump(value)
             buf.append(")")
 
-        buf: t.List[str] = []
+        buf: list[str] = []
         _dump(self)
         return "".join(buf)
 
@@ -297,7 +297,7 @@ class Template(Node):
     """
 
     fields = ("body",)
-    body: t.List[Node]
+    body: list[Node]
 
 
 class Output(Stmt):
@@ -306,7 +306,7 @@ class Output(Stmt):
     """
 
     fields = ("nodes",)
-    nodes: t.List["Expr"]
+    nodes: list["Expr"]
 
 
 class Extends(Stmt):
@@ -328,8 +328,8 @@ class For(Stmt):
     fields = ("target", "iter", "body", "else_", "test", "recursive")
     target: Node
     iter: Node
-    body: t.List[Node]
-    else_: t.List[Node]
+    body: list[Node]
+    else_: list[Node]
     test: t.Optional[Node]
     recursive: bool
 
@@ -339,9 +339,9 @@ class If(Stmt):
 
     fields = ("test", "body", "elif_", "else_")
     test: Node
-    body: t.List[Node]
-    elif_: t.List["If"]
-    else_: t.List[Node]
+    body: list[Node]
+    elif_: list["If"]
+    else_: list[Node]
 
 
 class Macro(Stmt):
@@ -352,9 +352,9 @@ class Macro(Stmt):
 
     fields = ("name", "args", "defaults", "body")
     name: str
-    args: t.List["Name"]
-    defaults: t.List["Expr"]
-    body: t.List[Node]
+    args: list["Name"]
+    defaults: list["Expr"]
+    body: list[Node]
 
 
 class CallBlock(Stmt):
@@ -364,16 +364,16 @@ class CallBlock(Stmt):
 
     fields = ("call", "args", "defaults", "body")
     call: "Call"
-    args: t.List["Name"]
-    defaults: t.List["Expr"]
-    body: t.List[Node]
+    args: list["Name"]
+    defaults: list["Expr"]
+    body: list[Node]
 
 
 class FilterBlock(Stmt):
     """Node for filter sections."""
 
     fields = ("body", "filter")
-    body: t.List[Node]
+    body: list[Node]
     filter: "Filter"
 
 
@@ -385,9 +385,9 @@ class With(Stmt):
     """
 
     fields = ("targets", "values", "body")
-    targets: t.List["Expr"]
-    values: t.List["Expr"]
-    body: t.List[Node]
+    targets: list["Expr"]
+    values: list["Expr"]
+    body: list[Node]
 
 
 class Block(Stmt):
@@ -399,7 +399,7 @@ class Block(Stmt):
 
     fields = ("name", "body", "scoped", "required")
     name: str
-    body: t.List[Node]
+    body: list[Node]
     scoped: bool
     required: bool
 
@@ -436,7 +436,7 @@ class FromImport(Stmt):
 
     fields = ("template", "names", "with_context")
     template: "Expr"
-    names: t.List[t.Union[str, t.Tuple[str, str]]]
+    names: list[t.Union[str, tuple[str, str]]]
     with_context: bool
 
 
@@ -461,7 +461,7 @@ class AssignBlock(Stmt):
     fields = ("target", "filter", "body")
     target: "Expr"
     filter: t.Optional["Filter"]
-    body: t.List[Node]
+    body: list[Node]
 
 
 class Expr(Node):
@@ -627,10 +627,10 @@ class Tuple(Literal):
     """
 
     fields = ("items", "ctx")
-    items: t.List[Expr]
+    items: list[Expr]
     ctx: str
 
-    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[t.Any, ...]:
+    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> tuple[t.Any, ...]:
         eval_ctx = get_eval_context(self, eval_ctx)
         return tuple(x.as_const(eval_ctx) for x in self.items)
 
@@ -645,9 +645,9 @@ class List(Literal):
     """Any list literal such as ``[1, 2, 3]``"""
 
     fields = ("items",)
-    items: t.List[Expr]
+    items: list[Expr]
 
-    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.List[t.Any]:
+    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> list[t.Any]:
         eval_ctx = get_eval_context(self, eval_ctx)
         return [x.as_const(eval_ctx) for x in self.items]
 
@@ -658,11 +658,9 @@ class Dict(Literal):
     """
 
     fields = ("items",)
-    items: t.List["Pair"]
+    items: list["Pair"]
 
-    def as_const(
-        self, eval_ctx: t.Optional[EvalContext] = None
-    ) -> t.Dict[t.Any, t.Any]:
+    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> dict[t.Any, t.Any]:
         eval_ctx = get_eval_context(self, eval_ctx)
         return dict(x.as_const(eval_ctx) for x in self.items)
 
@@ -674,9 +672,7 @@ class Pair(Helper):
     key: Expr
     value: Expr
 
-    def as_const(
-        self, eval_ctx: t.Optional[EvalContext] = None
-    ) -> t.Tuple[t.Any, t.Any]:
+    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> tuple[t.Any, t.Any]:
         eval_ctx = get_eval_context(self, eval_ctx)
         return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
 
@@ -688,7 +684,7 @@ class Keyword(Helper):
     key: str
     value: Expr
 
-    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Tuple[str, t.Any]:
+    def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> tuple[str, t.Any]:
         eval_ctx = get_eval_context(self, eval_ctx)
         return self.key, self.value.as_const(eval_ctx)
 
@@ -717,7 +713,7 @@ class CondExpr(Expr):
 
 def args_as_const(
     node: t.Union["_FilterTestCommon", "Call"], eval_ctx: t.Optional[EvalContext]
-) -> t.Tuple[t.List[t.Any], t.Dict[t.Any, t.Any]]:
+) -> tuple[list[t.Any], dict[t.Any, t.Any]]:
     args = [x.as_const(eval_ctx) for x in node.args]
     kwargs = dict(x.as_const(eval_ctx) for x in node.kwargs)
 
@@ -740,8 +736,8 @@ class _FilterTestCommon(Expr):
     fields = ("node", "name", "args", "kwargs", "dyn_args", "dyn_kwargs")
     node: Expr
     name: str
-    args: t.List[Expr]
-    kwargs: t.List[Pair]
+    args: list[Expr]
+    kwargs: list[Pair]
     dyn_args: t.Optional[Expr]
     dyn_kwargs: t.Optional[Expr]
     abstract = True
@@ -824,8 +820,8 @@ class Call(Expr):
 
     fields = ("node", "args", "kwargs", "dyn_args", "dyn_kwargs")
     node: Expr
-    args: t.List[Expr]
-    kwargs: t.List[Keyword]
+    args: list[Expr]
+    kwargs: list[Keyword]
     dyn_args: t.Optional[Expr]
     dyn_kwargs: t.Optional[Expr]
 
@@ -901,7 +897,7 @@ class Concat(Expr):
     """
 
     fields = ("nodes",)
-    nodes: t.List[Expr]
+    nodes: list[Expr]
 
     def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> str:
         eval_ctx = get_eval_context(self, eval_ctx)
@@ -915,7 +911,7 @@ class Compare(Expr):
 
     fields = ("expr", "ops")
     expr: Expr
-    ops: t.List["Operand"]
+    ops: list["Operand"]
 
     def as_const(self, eval_ctx: t.Optional[EvalContext] = None) -> t.Any:
         eval_ctx = get_eval_context(self, eval_ctx)
@@ -1152,7 +1148,7 @@ class Scope(Stmt):
     """An artificial scope."""
 
     fields = ("body",)
-    body: t.List[Node]
+    body: list[Node]
 
 
 class OverlayScope(Stmt):
@@ -1171,7 +1167,7 @@ class OverlayScope(Stmt):
 
     fields = ("context", "body")
     context: Expr
-    body: t.List[Node]
+    body: list[Node]
 
 
 class EvalContextModifier(Stmt):
@@ -1184,7 +1180,7 @@ class EvalContextModifier(Stmt):
     """
 
     fields = ("options",)
-    options: t.List[Keyword]
+    options: list[Keyword]
 
 
 class ScopedEvalContextModifier(EvalContextModifier):
@@ -1194,7 +1190,7 @@ class ScopedEvalContextModifier(EvalContextModifier):
     """
 
     fields = ("body",)
-    body: t.List[Node]
+    body: list[Node]
 
 
 # make sure nobody creates custom nodes
index 5f6dfa8934e76e6dee76a5d9ec37ad6670abd741..d119507d62a0b24ed9b410ef1d090e7aaaff3ee8 100644 (file)
@@ -35,7 +35,7 @@ _statement_keywords = frozenset(
 )
 _compare_operators = frozenset(["eq", "ne", "lt", "lteq", "gt", "gteq"])
 
-_math_nodes: t.Dict[str, t.Type[nodes.Expr]] = {
+_math_nodes: dict[str, type[nodes.Expr]] = {
     "add": nodes.Add,
     "sub": nodes.Sub,
     "mul": nodes.Mul,
@@ -63,21 +63,21 @@ class Parser:
         self.name = name
         self.filename = filename
         self.closed = False
-        self.extensions: t.Dict[
-            str, t.Callable[[Parser], t.Union[nodes.Node, t.List[nodes.Node]]]
+        self.extensions: dict[
+            str, t.Callable[[Parser], t.Union[nodes.Node, list[nodes.Node]]]
         ] = {}
         for extension in environment.iter_extensions():
             for tag in extension.tags:
                 self.extensions[tag] = extension.parse
         self._last_identifier = 0
-        self._tag_stack: t.List[str] = []
-        self._end_token_stack: t.List[t.Tuple[str, ...]] = []
+        self._tag_stack: list[str] = []
+        self._end_token_stack: list[tuple[str, ...]] = []
 
     def fail(
         self,
         msg: str,
         lineno: t.Optional[int] = None,
-        exc: t.Type[TemplateSyntaxError] = TemplateSyntaxError,
+        exc: type[TemplateSyntaxError] = TemplateSyntaxError,
     ) -> "te.NoReturn":
         """Convenience method that raises `exc` with the message, passed
         line number or last line number as well as the current name and
@@ -90,10 +90,10 @@ class Parser:
     def _fail_ut_eof(
         self,
         name: t.Optional[str],
-        end_token_stack: t.List[t.Tuple[str, ...]],
+        end_token_stack: list[tuple[str, ...]],
         lineno: t.Optional[int],
     ) -> "te.NoReturn":
-        expected: t.Set[str] = set()
+        expected: set[str] = set()
         for exprs in end_token_stack:
             expected.update(map(describe_token_expr, exprs))
         if end_token_stack:
@@ -138,7 +138,7 @@ class Parser:
 
     def fail_eof(
         self,
-        end_tokens: t.Optional[t.Tuple[str, ...]] = None,
+        end_tokens: t.Optional[tuple[str, ...]] = None,
         lineno: t.Optional[int] = None,
     ) -> "te.NoReturn":
         """Like fail_unknown_tag but for end of template situations."""
@@ -147,9 +147,7 @@ class Parser:
             stack.append(end_tokens)
         self._fail_ut_eof(None, stack, lineno)
 
-    def is_tuple_end(
-        self, extra_end_rules: t.Optional[t.Tuple[str, ...]] = None
-    ) -> bool:
+    def is_tuple_end(self, extra_end_rules: t.Optional[tuple[str, ...]] = None) -> bool:
         """Are we at the end of a tuple?"""
         if self.stream.current.type in ("variable_end", "block_end", "rparen"):
             return True
@@ -164,7 +162,7 @@ class Parser:
         nodes.Node.__init__(rv, f"fi{self._last_identifier}", lineno=lineno)
         return rv
 
-    def parse_statement(self) -> t.Union[nodes.Node, t.List[nodes.Node]]:
+    def parse_statement(self) -> t.Union[nodes.Node, list[nodes.Node]]:
         """Parse a single statement."""
         token = self.stream.current
         if token.type != "name":
@@ -194,8 +192,8 @@ class Parser:
                 self._tag_stack.pop()
 
     def parse_statements(
-        self, end_tokens: t.Tuple[str, ...], drop_needle: bool = False
-    ) -> t.List[nodes.Node]:
+        self, end_tokens: tuple[str, ...], drop_needle: bool = False
+    ) -> list[nodes.Node]:
         """Parse multiple statements into a list until one of the end tokens
         is reached.  This is used to parse the body of statements as it also
         parses template data if appropriate.  The parser checks first if the
@@ -272,8 +270,8 @@ class Parser:
 
     def parse_with(self) -> nodes.With:
         node = nodes.With(lineno=next(self.stream).lineno)
-        targets: t.List[nodes.Expr] = []
-        values: t.List[nodes.Expr] = []
+        targets: list[nodes.Expr] = []
+        values: list[nodes.Expr] = []
         while self.stream.current.type != "block_end":
             if targets:
                 self.stream.expect("comma")
@@ -466,7 +464,7 @@ class Parser:
         self,
         with_tuple: bool = True,
         name_only: bool = False,
-        extra_end_rules: t.Optional[t.Tuple[str, ...]] = None,
+        extra_end_rules: t.Optional[tuple[str, ...]] = None,
         with_namespace: bool = False,
     ) -> t.Union[nodes.NSRef, nodes.Name, nodes.Tuple]: ...
 
@@ -474,7 +472,7 @@ class Parser:
         self,
         with_tuple: bool = True,
         name_only: bool = False,
-        extra_end_rules: t.Optional[t.Tuple[str, ...]] = None,
+        extra_end_rules: t.Optional[tuple[str, ...]] = None,
         with_namespace: bool = False,
     ) -> t.Union[nodes.NSRef, nodes.Name, nodes.Tuple]:
         """Parse an assignment target.  As Jinja allows assignments to
@@ -686,7 +684,7 @@ class Parser:
         self,
         simplified: bool = False,
         with_condexpr: bool = True,
-        extra_end_rules: t.Optional[t.Tuple[str, ...]] = None,
+        extra_end_rules: t.Optional[tuple[str, ...]] = None,
         explicit_parentheses: bool = False,
         with_namespace: bool = False,
     ) -> t.Union[nodes.Tuple, nodes.Expr]:
@@ -720,7 +718,7 @@ class Parser:
             def parse() -> nodes.Expr:
                 return self.parse_expression(with_condexpr=with_condexpr)
 
-        args: t.List[nodes.Expr] = []
+        args: list[nodes.Expr] = []
         is_tuple = False
 
         while True:
@@ -753,7 +751,7 @@ class Parser:
 
     def parse_list(self) -> nodes.List:
         token = self.stream.expect("lbracket")
-        items: t.List[nodes.Expr] = []
+        items: list[nodes.Expr] = []
         while self.stream.current.type != "rbracket":
             if items:
                 self.stream.expect("comma")
@@ -765,7 +763,7 @@ class Parser:
 
     def parse_dict(self) -> nodes.Dict:
         token = self.stream.expect("lbrace")
-        items: t.List[nodes.Pair] = []
+        items: list[nodes.Pair] = []
         while self.stream.current.type != "rbrace":
             if items:
                 self.stream.expect("comma")
@@ -824,7 +822,7 @@ class Parser:
             arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
             return nodes.Getitem(node, arg, "load", lineno=token.lineno)
         if token.type == "lbracket":
-            args: t.List[nodes.Expr] = []
+            args: list[nodes.Expr] = []
             while self.stream.current.type != "rbracket":
                 if args:
                     self.stream.expect("comma")
@@ -839,7 +837,7 @@ class Parser:
 
     def parse_subscribed(self) -> nodes.Expr:
         lineno = self.stream.current.lineno
-        args: t.List[t.Optional[nodes.Expr]]
+        args: list[t.Optional[nodes.Expr]]
 
         if self.stream.current.type == "colon":
             next(self.stream)
@@ -871,9 +869,9 @@ class Parser:
 
     def parse_call_args(
         self,
-    ) -> t.Tuple[
-        t.List[nodes.Expr],
-        t.List[nodes.Keyword],
+    ) -> tuple[
+        list[nodes.Expr],
+        list[nodes.Keyword],
         t.Union[nodes.Expr, None],
         t.Union[nodes.Expr, None],
     ]:
@@ -967,7 +965,7 @@ class Parser:
             next(self.stream)
             name += "." + self.stream.expect("name").value
         dyn_args = dyn_kwargs = None
-        kwargs: t.List[nodes.Keyword] = []
+        kwargs: list[nodes.Keyword] = []
         if self.stream.current.type == "lparen":
             args, kwargs, dyn_args, dyn_kwargs = self.parse_call_args()
         elif self.stream.current.type in {
@@ -994,10 +992,10 @@ class Parser:
         return node
 
     def subparse(
-        self, end_tokens: t.Optional[t.Tuple[str, ...]] = None
-    ) -> t.List[nodes.Node]:
-        body: t.List[nodes.Node] = []
-        data_buffer: t.List[nodes.Node] = []
+        self, end_tokens: t.Optional[tuple[str, ...]] = None
+    ) -> list[nodes.Node]:
+        body: list[nodes.Node] = []
+        data_buffer: list[nodes.Node] = []
         add_data = data_buffer.append
 
         if end_tokens is not None:
index da30c814fc789cedaea441c0132b1c06291c23c7..00b81e288db669667a0d76342b762d813c814835 100644 (file)
@@ -93,8 +93,8 @@ def str_join(seq: t.Iterable[t.Any]) -> str:
 def new_context(
     environment: "Environment",
     template_name: t.Optional[str],
-    blocks: t.Dict[str, t.Callable[["Context"], t.Iterator[str]]],
-    vars: t.Optional[t.Dict[str, t.Any]] = None,
+    blocks: dict[str, t.Callable[["Context"], t.Iterator[str]]],
+    vars: t.Optional[dict[str, t.Any]] = None,
     shared: bool = False,
     globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
     locals: t.Optional[t.Mapping[str, t.Any]] = None,
@@ -165,16 +165,16 @@ class Context:
     def __init__(
         self,
         environment: "Environment",
-        parent: t.Dict[str, t.Any],
+        parent: dict[str, t.Any],
         name: t.Optional[str],
-        blocks: t.Dict[str, t.Callable[["Context"], t.Iterator[str]]],
+        blocks: dict[str, t.Callable[["Context"], t.Iterator[str]]],
         globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
     ):
         self.parent = parent
-        self.vars: t.Dict[str, t.Any] = {}
+        self.vars: dict[str, t.Any] = {}
         self.environment: Environment = environment
         self.eval_ctx = EvalContext(self.environment, name)
-        self.exported_vars: t.Set[str] = set()
+        self.exported_vars: set[str] = set()
         self.name = name
         self.globals_keys = set() if globals is None else set(globals)
 
@@ -244,11 +244,11 @@ class Context:
 
         return missing
 
-    def get_exported(self) -> t.Dict[str, t.Any]:
+    def get_exported(self) -> dict[str, t.Any]:
         """Get a new dict with the exported variables."""
         return {k: self.vars[k] for k in self.exported_vars}
 
-    def get_all(self) -> t.Dict[str, t.Any]:
+    def get_all(self) -> dict[str, t.Any]:
         """Return the complete context as dict including the exported
         variables.  For optimizations reasons this might not return an
         actual copy so be careful with using it.
@@ -307,7 +307,7 @@ class Context:
                 " StopIteration exception"
             )
 
-    def derived(self, locals: t.Optional[t.Dict[str, t.Any]] = None) -> "Context":
+    def derived(self, locals: t.Optional[dict[str, t.Any]] = None) -> "Context":
         """Internal helper function to create a derived context.  This is
         used in situations where the system needs a new context in the same
         template that is independent.
@@ -348,7 +348,7 @@ class BlockReference:
         self,
         name: str,
         context: "Context",
-        stack: t.List[t.Callable[["Context"], t.Iterator[str]]],
+        stack: list[t.Callable[["Context"], t.Iterator[str]]],
         depth: int,
     ) -> None:
         self.name = name
@@ -408,7 +408,7 @@ class LoopContext:
     def __init__(
         self,
         iterable: t.Iterable[V],
-        undefined: t.Type["Undefined"],
+        undefined: type["Undefined"],
         recurse: t.Optional["LoopRenderFunc"] = None,
         depth0: int = 0,
     ) -> None:
@@ -558,7 +558,7 @@ class LoopContext:
     def __iter__(self) -> "LoopContext":
         return self
 
-    def __next__(self) -> t.Tuple[t.Any, "LoopContext"]:
+    def __next__(self) -> tuple[t.Any, "LoopContext"]:
         if self._after is not missing:
             rv = self._after
             self._after = missing
@@ -646,7 +646,7 @@ class AsyncLoopContext(LoopContext):
     def __aiter__(self) -> "AsyncLoopContext":
         return self
 
-    async def __anext__(self) -> t.Tuple[t.Any, "AsyncLoopContext"]:
+    async def __anext__(self) -> tuple[t.Any, "AsyncLoopContext"]:
         if self._after is not missing:
             rv = self._after
             self._after = missing
@@ -667,7 +667,7 @@ class Macro:
         environment: "Environment",
         func: t.Callable[..., str],
         name: str,
-        arguments: t.List[str],
+        arguments: list[str],
         catch_kwargs: bool,
         catch_varargs: bool,
         caller: bool,
@@ -769,7 +769,7 @@ class Macro:
 
         return self._invoke(arguments, autoescape)
 
-    async def _async_invoke(self, arguments: t.List[t.Any], autoescape: bool) -> str:
+    async def _async_invoke(self, arguments: list[t.Any], autoescape: bool) -> str:
         rv = await self._func(*arguments)  # type: ignore
 
         if autoescape:
@@ -777,7 +777,7 @@ class Macro:
 
         return rv  # type: ignore
 
-    def _invoke(self, arguments: t.List[t.Any], autoescape: bool) -> str:
+    def _invoke(self, arguments: list[t.Any], autoescape: bool) -> str:
         if self._environment.is_async:
             return self._async_invoke(arguments, autoescape)  # type: ignore
 
@@ -820,7 +820,7 @@ class Undefined:
         hint: t.Optional[str] = None,
         obj: t.Any = missing,
         name: t.Optional[str] = None,
-        exc: t.Type[TemplateRuntimeError] = UndefinedError,
+        exc: type[TemplateRuntimeError] = UndefinedError,
     ) -> None:
         self._undefined_hint = hint
         self._undefined_obj = obj
@@ -910,8 +910,8 @@ class Undefined:
 
 
 def make_logging_undefined(
-    logger: t.Optional["logging.Logger"] = None, base: t.Type[Undefined] = Undefined
-) -> t.Type[Undefined]:
+    logger: t.Optional["logging.Logger"] = None, base: type[Undefined] = Undefined
+) -> type[Undefined]:
     """Given a logger object this returns a new undefined class that will
     log certain failures.  It will log iterations and printing.  If no
     logger is given a default logger is created.
index 9c9dae22f1c2c19f976edeb6478bcf53c6207cb1..1e221a83fb80bbc8f1bcfe3130711517d00667ce 100644 (file)
@@ -25,10 +25,10 @@ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
 MAX_RANGE = 100000
 
 #: Unsafe function attributes.
-UNSAFE_FUNCTION_ATTRIBUTES: t.Set[str] = set()
+UNSAFE_FUNCTION_ATTRIBUTES: set[str] = set()
 
 #: Unsafe method attributes. Function attributes are unsafe for methods too.
-UNSAFE_METHOD_ATTRIBUTES: t.Set[str] = set()
+UNSAFE_METHOD_ATTRIBUTES: set[str] = set()
 
 #: unsafe generator attributes.
 UNSAFE_GENERATOR_ATTRIBUTES = {"gi_frame", "gi_code"}
@@ -39,7 +39,7 @@ UNSAFE_COROUTINE_ATTRIBUTES = {"cr_frame", "cr_code"}
 #: unsafe attributes on async generators
 UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = {"ag_code", "ag_frame"}
 
-_mutable_spec: t.Tuple[t.Tuple[t.Type[t.Any], t.FrozenSet[str]], ...] = (
+_mutable_spec: tuple[tuple[type[t.Any], frozenset[str]], ...] = (
     (
         abc.MutableSet,
         frozenset(
@@ -190,7 +190,7 @@ class SandboxedEnvironment(Environment):
     #: default callback table for the binary operators.  A copy of this is
     #: available on each instance of a sandboxed environment as
     #: :attr:`binop_table`
-    default_binop_table: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
+    default_binop_table: dict[str, t.Callable[[t.Any, t.Any], t.Any]] = {
         "+": operator.add,
         "-": operator.sub,
         "*": operator.mul,
@@ -203,7 +203,7 @@ class SandboxedEnvironment(Environment):
     #: default callback table for the unary operators.  A copy of this is
     #: available on each instance of a sandboxed environment as
     #: :attr:`unop_table`
-    default_unop_table: t.Dict[str, t.Callable[[t.Any], t.Any]] = {
+    default_unop_table: dict[str, t.Callable[[t.Any], t.Any]] = {
         "+": operator.pos,
         "-": operator.neg,
     }
@@ -222,7 +222,7 @@ class SandboxedEnvironment(Environment):
     #: interested in.
     #:
     #: .. versionadded:: 2.6
-    intercepted_binops: t.FrozenSet[str] = frozenset()
+    intercepted_binops: frozenset[str] = frozenset()
 
     #: a set of unary operators that should be intercepted.  Each operator
     #: that is added to this set (empty by default) is delegated to the
@@ -237,7 +237,7 @@ class SandboxedEnvironment(Environment):
     #: interested in.
     #:
     #: .. versionadded:: 2.6
-    intercepted_unops: t.FrozenSet[str] = frozenset()
+    intercepted_unops: frozenset[str] = frozenset()
 
     def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
         super().__init__(*args, **kwargs)
@@ -357,7 +357,7 @@ class SandboxedEnvironment(Environment):
         if not isinstance(f_self, str):
             return None
 
-        str_type: t.Type[str] = type(f_self)
+        str_type: type[str] = type(f_self)
         is_format_map = value.__name__ == "format_map"
         formatter: SandboxedFormatter
 
@@ -421,7 +421,7 @@ class SandboxedFormatter(Formatter):
 
     def get_field(
         self, field_name: str, args: t.Sequence[t.Any], kwargs: t.Mapping[str, t.Any]
-    ) -> t.Tuple[t.Any, str]:
+    ) -> tuple[t.Any, str]:
         first, rest = formatter_field_name_split(field_name)
         obj = self.get_value(first, args, kwargs)
         for is_attr, i in rest:
index 7c922629a926c83c55476bd339f6dc32e48a9aec..875300f5bb9214dae348335ed662ef820eda551a 100644 (file)
@@ -438,8 +438,8 @@ class LRUCache:
 
     def __init__(self, capacity: int) -> None:
         self.capacity = capacity
-        self._mapping: t.Dict[t.Any, t.Any] = {}
-        self._queue: te.Deque[t.Any] = deque()
+        self._mapping: dict[t.Any, t.Any] = {}
+        self._queue: deque[t.Any] = deque()
         self._postinit()
 
     def _postinit(self) -> None:
@@ -461,7 +461,7 @@ class LRUCache:
         self.__dict__.update(d)
         self._postinit()
 
-    def __getnewargs__(self) -> t.Tuple[t.Any, ...]:
+    def __getnewargs__(self) -> tuple[t.Any, ...]:
         return (self.capacity,)
 
     def copy(self) -> "te.Self":
@@ -552,7 +552,7 @@ class LRUCache:
             except ValueError:
                 pass
 
-    def items(self) -> t.Iterable[t.Tuple[t.Any, t.Any]]:
+    def items(self) -> t.Iterable[tuple[t.Any, t.Any]]:
         """Return a list of items."""
         result = [(key, self._mapping[key]) for key in list(self._queue)]
         result.reverse()
index 7b8e180601232b345e9fe13a0b2f9aa484761cdc..f25912e1ddd4d1d6a5f9dd5be87e87a1adee1ecc 100644 (file)
@@ -80,7 +80,7 @@ class NodeTransformer(NodeVisitor):
                     setattr(node, field, new_node)
         return node
 
-    def visit_list(self, node: Node, *args: t.Any, **kwargs: t.Any) -> t.List[Node]:
+    def visit_list(self, node: Node, *args: t.Any, **kwargs: t.Any) -> list[Node]:
         """As transformers may return lists in some places this method
         can be used to enforce a list as return value.
         """
index 9bd9fda17cf044801ffaf3c5c94ec0e56aa6b173..d995cd48fefd2623c250fae92c9168946dcaca1c 100644 (file)
@@ -449,9 +449,7 @@ class TestAsyncForLoop:
 
     def test_reversed_bug(self, test_env_async):
         tmpl = test_env_async.from_string(
-            "{% for i in items %}{{ i }}"
-            "{% if not loop.last %}"
-            ",{% endif %}{% endfor %}"
+            "{% for i in items %}{{ i }}{% if not loop.last %},{% endif %}{% endfor %}"
         )
         assert tmpl.render(items=reversed([3, 2, 1])) == "1,2,3"
 
index 2d847a2c9afac0e30115dc5d401c700867d029ad..6abbbdf3550771bb54b4bdb27a0ed05db43a4ec8 100644 (file)
@@ -191,9 +191,7 @@ class TestForLoop:
 
     def test_reversed_bug(self, env):
         tmpl = env.from_string(
-            "{% for i in items %}{{ i }}"
-            "{% if not loop.last %}"
-            ",{% endif %}{% endfor %}"
+            "{% for i in items %}{{ i }}{% if not loop.last %},{% endif %}{% endfor %}"
         )
         assert tmpl.render(items=reversed([3, 2, 1])) == "1,2,3"
 
index bc11f401b16b6c83567b86cbc4abd4f3882994cf..4d5cf3e549c1ff60bc37983e7966e5518f7038b3 100644 (file)
@@ -23,9 +23,9 @@ class TestDebug:
 
         tb = format_exception(exc_info.type, exc_info.value, exc_info.tb)
         m = re.search(expected_tb.strip(), "".join(tb))
-        assert (
-            m is not None
-        ), f"Traceback did not match:\n\n{''.join(tb)}\nexpected:\n{expected_tb}"
+        assert m is not None, (
+            f"Traceback did not match:\n\n{''.join(tb)}\nexpected:\n{expected_tb}"
+        )
 
     def test_runtime_error(self, fs_env):
         def test():
index 0b48ca2586949702859564a1133ab9be6f85b49d..f604121665d31281a89047e5daa306b86e035f70 100644 (file)
@@ -554,8 +554,7 @@ class TestNewstyleInternationalization:
             newstyle=True,
         )
         t = env.from_string(
-            '{% autoescape ae %}{{ gettext("foo", name='
-            '"<test>") }}{% endautoescape %}'
+            '{% autoescape ae %}{{ gettext("foo", name="<test>") }}{% endautoescape %}'
         )
         assert t.render(ae=True) == "<strong>Wert: &lt;test&gt;</strong>"
         assert t.render(ae=False) == "<strong>Wert: <test></strong>"
index 2cb53ac9d07f0c5e1d860fbd07ce3baade43cfd7..4601469a6b8638e34e0ca4863fbb901fad707a2c 100644 (file)
@@ -357,7 +357,7 @@ class TestFilter:
     def test_urlize(self, env):
         tmpl = env.from_string('{{ "foo example.org bar"|urlize }}')
         assert tmpl.render() == (
-            'foo <a href="https://example.org" rel="noopener">' "example.org</a> bar"
+            'foo <a href="https://example.org" rel="noopener">example.org</a> bar'
         )
         tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
         assert tmpl.render() == (
index c02adad5a9ecd95262ff555505aa3156bb3060a9..0f0dbf3322e25884bca96934dd2c7e43a2da476d 100644 (file)
@@ -43,8 +43,7 @@ class TestTokenStream:
 class TestLexer:
     def test_raw1(self, env):
         tmpl = env.from_string(
-            "{% raw %}foo{% endraw %}|"
-            "{%raw%}{{ bar }}|{% baz %}{%       endraw    %}"
+            "{% raw %}foo{% endraw %}|{%raw%}{{ bar }}|{% baz %}{%       endraw    %}"
         )
         assert tmpl.render() == "foo|{{ bar }}|{% baz %}"