Coverage for tdom / template_utils.py: 100%
32 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-17 23:32 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-17 23:32 +0000
1import typing as t
2from dataclasses import dataclass
3from string.templatelib import Interpolation, Template
6def template_from_parts(
7 strings: t.Sequence[str], interpolations: t.Sequence[Interpolation]
8) -> Template:
9 """Construct a template string from the given strings and parts."""
10 assert len(strings) == len(interpolations) + 1, (
11 "TemplateRef must have one more string than interpolation references."
12 )
13 flat = [x for pair in zip(strings, interpolations) for x in pair] + [strings[-1]]
14 return Template(*flat)
17@dataclass(slots=True, frozen=True)
18class TemplateRef:
19 """Reference to a template with indexes for its original interpolations."""
21 strings: tuple[str, ...]
22 """Static string parts of the original string.templatelib.Template"""
24 i_indexes: tuple[int, ...]
25 """Indexes of the interpolations in the original string.templatelib.Template"""
27 @property
28 def is_literal(self) -> bool:
29 """Return True if there are no interpolations."""
30 return not self.i_indexes
32 @property
33 def is_empty(self) -> bool:
34 """Return True if the template is empty."""
35 return self.is_literal and self.strings[0] == ""
37 @property
38 def is_singleton(self) -> bool:
39 """Return True if there is exactly one interpolation and no other content."""
40 return self.strings == ("", "")
42 @classmethod
43 def literal(cls, s: str) -> t.Self:
44 return cls((s,), ())
46 @classmethod
47 def empty(cls) -> t.Self:
48 return cls.literal("")
50 @classmethod
51 def singleton(cls, i_index: int) -> t.Self:
52 return cls(("", ""), (i_index,))
54 def __post_init__(self):
55 if len(self.strings) != len(self.i_indexes) + 1:
56 raise ValueError(
57 "TemplateRef must have one more string than interpolation indexes."
58 )