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 )