Coverage for tdom / placeholders.py: 100%

44 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-17 23:32 +0000

1import random 

2import re 

3import string 

4 

5from .template_utils import TemplateRef 

6 

7FRAGMENT_TAG = f"t🐍f-{''.join(random.choices(string.ascii_lowercase, k=4))}-" 

8_PLACEHOLDER_PREFIX = f"t🐍{''.join(random.choices(string.ascii_lowercase, k=2))}-" 

9_PLACEHOLDER_SUFFIX = f"-{''.join(random.choices(string.ascii_lowercase, k=2))}🐍t" 

10_PLACEHOLDER_PATTERN = re.compile( 

11 re.escape(_PLACEHOLDER_PREFIX) + r"(\d+)" + re.escape(_PLACEHOLDER_SUFFIX) 

12) 

13 

14 

15def make_placeholder(i: int) -> str: 

16 """Generate a placeholder for the i-th interpolation.""" 

17 return f"{_PLACEHOLDER_PREFIX}{i}{_PLACEHOLDER_SUFFIX}" 

18 

19 

20def match_placeholders(s: str) -> list[re.Match[str]]: 

21 """Find all placeholders in a string.""" 

22 return list(_PLACEHOLDER_PATTERN.finditer(s)) 

23 

24 

25def find_placeholders(s: str) -> TemplateRef: 

26 """ 

27 Find all placeholders in a string and return a TemplateRef. 

28 

29 If no placeholders are found, returns a static TemplateRef. 

30 """ 

31 matches = match_placeholders(s) 

32 if not matches: 

33 return TemplateRef.literal(s) 

34 

35 strings: list[str] = [] 

36 i_indexes: list[int] = [] 

37 last_index = 0 

38 for match in matches: 

39 start, end = match.span() 

40 strings.append(s[last_index:start]) 

41 i_indexes.append(int(match[1])) 

42 last_index = end 

43 strings.append(s[last_index:]) 

44 

45 return TemplateRef(tuple(strings), tuple(i_indexes)) 

46 

47 

48class PlaceholderState: 

49 known: set[int] 

50 """Collection of currently 'known and active' placeholder indexes.""" 

51 

52 def __init__(self): 

53 self.known = set() 

54 

55 @property 

56 def is_empty(self) -> bool: 

57 return len(self.known) == 0 

58 

59 def add_placeholder(self, index: int) -> str: 

60 placeholder = make_placeholder(index) 

61 self.known.add(index) 

62 return placeholder 

63 

64 def remove_placeholders(self, text: str) -> TemplateRef: 

65 """ 

66 Find all known placeholders in the text and return their indices. 

67 

68 If unknown placeholders are found, raises ValueError. 

69 

70 If no placeholders are found, returns a static PlaceholderRef. 

71 """ 

72 pt = find_placeholders(text) 

73 for index in pt.i_indexes: 

74 if index not in self.known: 

75 raise ValueError(f"Unknown placeholder index {index} found in text.") 

76 self.known.remove(index) 

77 return pt