1from __future__ import annotations
 2
 3from typing import Any
 4
 5from jinja2 import nodes
 6from jinja2.ext import Extension
 7from jinja2.runtime import Context
 8
 9
10class InclusionTagExtension(Extension):
11    """Intended to be subclassed"""
12
13    # tags = {'inclusion_tag'}
14    tags: set[str]
15    template_name: str
16
17    def parse(self, parser: Any) -> nodes.Node:
18        lineno = next(parser.stream).lineno
19        args = [
20            nodes.DerivedContextReference(),
21        ]
22        kwargs = []
23        while parser.stream.current.type != "block_end":
24            if parser.stream.current.type == "name":
25                key = parser.stream.current.value
26                parser.stream.skip()
27                parser.stream.expect("assign")
28                value = parser.parse_expression()
29                kwargs.append(nodes.Keyword(key, value))
30            else:
31                args.append(parser.parse_expression())
32
33        call = self.call_method("_render", args=args, kwargs=kwargs, lineno=lineno)
34        return nodes.CallBlock(call, [], [], []).set_lineno(lineno)
35
36    def _render(self, context: Context, *args: Any, **kwargs: Any) -> str:
37        render_context = self.get_context(context, *args, **kwargs)
38        template = self.environment.get_template(self.template_name)
39        return template.render(render_context)
40
41    def get_context(
42        self, context: Context, *args: Any, **kwargs: Any
43    ) -> Context | dict[str, Any]:
44        raise NotImplementedError(
45            "You need to implement the `get_context` method in your subclass."
46        )