Coverage for src/markdown_include_variants/_main.py: 100%

231 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2026-10-15 15:22 +0000

1import re 2pbqb

2from dataclasses import dataclass 2pbqb

3from pathlib import Path 2pbqb

4from typing import Any, Literal, Union 2pbqb

5 

6from markdown import Extension, Markdown 2pbqb

7from markdown.preprocessors import Preprocessor 2pbqb

8 

9AN = "_an" 2pbqb

10PY39 = "_py39" 2pbqb

11PY310 = "_py310" 2pbqb

12PY311 = "_py311" 2pbqb

13 

14SUFFIXES_TO_REMOVE = ["_an", "_py39", "_py310", "_py311"] 2pbqb

15 

16 

17@dataclass(frozen=True) 2pbqb

18class Variant: 2pbqb

19 path: Path 2pbqb

20 title: str 2pbqb

21 is_annotated: Union[bool, None] 2pbqb

22 version: Literal["py38", "py39", "py310", "py311"] 2pbqb

23 

24 

25def remove_suffixes(base_name: str, suffixes: list[str]) -> str: 2pbqb

26 for suffix in suffixes: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

27 if base_name.endswith(suffix): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

28 base_name = base_name[: -len(suffix)] 2i j e f [ a b G ] fblb` jbC gbk l g h ^ c d H _ hbmb{ kbD ib

29 return remove_suffixes(base_name, suffixes) 2i j e f [ a b G ] fblb` jbC gbk l g h ^ c d H _ hbmb{ kbD ib

30 return base_name 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

31 

32 

33def calculate_variants(base_path: Path) -> dict[tuple[str, Union[bool, None]], Variant]: 2pbqb

34 preferred_name = base_path.stem 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

35 base_name = remove_suffixes(preferred_name, SUFFIXES_TO_REMOVE) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

36 base_dir = base_path.parent 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

37 

38 an_p311_path = base_dir / f"{base_name}{AN}{PY311}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

39 an_p310_path = base_dir / f"{base_name}{AN}{PY310}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

40 an_p39_path = base_dir / f"{base_name}{AN}{PY39}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

41 an_p38_path = base_dir / f"{base_name}{AN}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

42 p311_path = base_dir / f"{base_name}{PY311}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

43 p310_path = base_dir / f"{base_name}{PY310}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

44 p39_path = base_dir / f"{base_name}{PY39}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

45 p38_path = base_dir / f"{base_name}.py" 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

46 

47 return _create_variants( 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

48 an_p311_path=an_p311_path, 

49 an_p310_path=an_p310_path, 

50 an_p39_path=an_p39_path, 

51 an_p38_path=an_p38_path, 

52 p311_path=p311_path, 

53 p310_path=p310_path, 

54 p39_path=p39_path, 

55 p38_path=p38_path, 

56 ) 

57 

58 

59def calculate_variants_folder( 2pbqb

60 base_path: Path, 

61) -> dict[tuple[str, Union[bool, None]], Variant]: 

62 file_name = base_path.name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

63 folder = base_path.parent 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

64 base_dir = folder.parent 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

65 base_name = remove_suffixes(folder.name, SUFFIXES_TO_REMOVE) 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

66 

67 an_p311_path = base_dir / f"{base_name}{AN}{PY311}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

68 an_p310_path = base_dir / f"{base_name}{AN}{PY310}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

69 an_p39_path = base_dir / f"{base_name}{AN}{PY39}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

70 an_p38_path = base_dir / f"{base_name}{AN}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

71 p311_path = base_dir / f"{base_name}{PY311}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

72 p310_path = base_dir / f"{base_name}{PY310}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

73 p39_path = base_dir / f"{base_name}{PY39}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

74 p38_path = base_dir / f"{base_name}" / file_name 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

75 

76 return _create_variants( 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

77 an_p311_path=an_p311_path, 

78 an_p310_path=an_p310_path, 

79 an_p39_path=an_p39_path, 

80 an_p38_path=an_p38_path, 

81 p311_path=p311_path, 

82 p310_path=p310_path, 

83 p39_path=p39_path, 

84 p38_path=p38_path, 

85 ) 

86 

87 

88def _create_variants( 2pbqb

89 an_p311_path: Path, 

90 an_p310_path: Path, 

91 an_p39_path: Path, 

92 an_p38_path: Path, 

93 p311_path: Path, 

94 p310_path: Path, 

95 p39_path: Path, 

96 p38_path: Path, 

97) -> dict[tuple[str, Union[bool, None]], Variant]: 

98 variants: dict[tuple[str, Union[bool, None]], Variant] = {} 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

99 if an_p311_path.exists(): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

100 v = Variant( 1ijef[abG]klgh^cdH_

101 path=an_p311_path, 

102 title="Python 3.11+", 

103 is_annotated=True, 

104 version="py311", 

105 ) 

106 variants[(v.version, v.is_annotated)] = v 1ijef[abG]klgh^cdH_

107 if p311_path.exists(): 1ijef[abG]klgh^cdH_

108 v = Variant( 1ijef[abG]klgh^cdH_

109 path=p311_path, 

110 title="Python 3.11+ - non-Annotated", 

111 is_annotated=False, 

112 version="py311", 

113 ) 

114 variants[(v.version, v.is_annotated)] = v 1ijef[abG]klgh^cdH_

115 elif p311_path.exists(): 2a b G fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbc d H hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

116 v = Variant( 2jbkb

117 path=p311_path, 

118 title="Python 3.11+", 

119 is_annotated=None, 

120 version="py311", 

121 ) 

122 variants[(v.version, v.is_annotated)] = v 2jbkb

123 if an_p310_path.exists(): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

124 v = Variant( 2i j e f [ a b G ] fblbk l g h ^ c d H _ hbmb

125 path=an_p310_path, 

126 title="Python 3.10+", 

127 is_annotated=True, 

128 version="py310", 

129 ) 

130 variants[(v.version, v.is_annotated)] = v 2i j e f [ a b G ] fblbk l g h ^ c d H _ hbmb

131 if p310_path.exists(): 2i j e f [ a b G ] fblbk l g h ^ c d H _ hbmb

132 v = Variant( 2i j e f [ a b G ] fblbk l g h ^ c d H _ hbmb

133 path=p310_path, 

134 title="Python 3.10+ - non-Annotated", 

135 is_annotated=False, 

136 version="py310", 

137 ) 

138 variants[(v.version, v.is_annotated)] = v 2i j e f [ a b G ] fblbk l g h ^ c d H _ hbmb

139 elif p310_path.exists(): 2a b G / ` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbc d H : { kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

140 v = Variant( 2` jb{ kb

141 path=p310_path, 

142 title="Python 3.10+", 

143 is_annotated=None, 

144 version="py310", 

145 ) 

146 variants[(v.version, v.is_annotated)] = v 2` jb{ kb

147 if an_p39_path.exists(): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

148 v = Variant( 2i j e f [ a b G ] C gbk l g h ^ c d H _ D ib

149 path=an_p39_path, 

150 title="Python 3.9+", 

151 is_annotated=True, 

152 version="py39", 

153 ) 

154 variants[(v.version, v.is_annotated)] = v 2i j e f [ a b G ] C gbk l g h ^ c d H _ D ib

155 if p39_path.exists(): 2i j e f [ a b G ] C gbk l g h ^ c d H _ D ib

156 v = Variant( 2i j e f [ a b G ] C gbk l g h ^ c d H _ D ib

157 path=p39_path, 

158 title="Python 3.9+ - non-Annotated", 

159 is_annotated=False, 

160 version="py39", 

161 ) 

162 variants[(v.version, v.is_annotated)] = v 2i j e f [ a b G ] C gbk l g h ^ c d H _ D ib

163 elif p39_path.exists(): 2a b G fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = c d H hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @

164 v = Variant( 2jbkb

165 path=p39_path, 

166 title="Python 3.9+", 

167 is_annotated=None, 

168 version="py39", 

169 ) 

170 variants[(v.version, v.is_annotated)] = v 2jbkb

171 if an_p38_path.exists(): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

172 v = Variant( 2i j e f [ a b G ] fbC gbk l g h ^ c d H _ hbD ib

173 path=an_p38_path, 

174 title="Python 3.8+", 

175 is_annotated=True, 

176 version="py38", 

177 ) 

178 variants[(v.version, v.is_annotated)] = v 2i j e f [ a b G ] fbC gbk l g h ^ c d H _ hbD ib

179 if p38_path.exists(): 2i j e f [ a b G ] fbC gbk l g h ^ c d H _ hbD ib

180 v = Variant( 2i j e f [ a b G ] fbC gbk l g h ^ c d H _ hbD ib

181 path=p38_path, 

182 title="Python 3.8+ - non-Annotated", 

183 is_annotated=False, 

184 version="py38", 

185 ) 

186 variants[(v.version, v.is_annotated)] = v 2i j e f [ a b G ] fbC gbk l g h ^ c d H _ hbD ib

187 elif p38_path.exists(): 2a b G / lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = c d H : mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @

188 v = Variant( 2a b G / ` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

189 path=p38_path, 

190 title="Python 3.8+", 

191 is_annotated=None, 

192 version="py38", 

193 ) 

194 variants[(v.version, v.is_annotated)] = v 2a b G / ` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

195 return variants 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

196 

197 

198def parse_lines_index(include_lines_config: str) -> list[tuple[int, int]]: 2pbqb

199 lines = [] 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoumCklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypznD

200 for line in include_lines_config.strip().split(","): 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoumCklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypznD

201 clean_line = line.strip() 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoumCklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypznD

202 if ":" in clean_line: 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoumCklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypznD

203 start, end = clean_line.split(":") 1ijefab'(STIUJVKLXEqArstoumCklghcd)*Z0N1O2PQ4FvBwxypznD

204 lines.append((int(start), int(end))) 1ijefab'(STIUJVKLXEqArstoumCklghcd)*Z0N1O2PQ4FvBwxypznD

205 else: 

206 lines.append((int(line), int(line))) 1/+S,KWL6M7Y89qom:-Z.P3Q!R#5$%vpn

207 lines.sort() 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoumCklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypznD

208 return lines 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoumCklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypznD

209 

210 

211@dataclass 2pbqb

212class IncludeInfo: 2pbqb

213 start: int 2pbqb

214 end: int 2pbqb

215 offset: int 2pbqb

216 hl_lines: list[tuple[int, int]] 2pbqb

217 

218 def computed_hl_lines(self) -> list[tuple[int, int]]: 2pbqb

219 return [ 1ijefabEqArstoumCklghcdFvBwxypznD

220 ( 

221 hl_line[0] - self.start + self.offset + 1, 

222 hl_line[1] - self.start + self.offset + 1, 

223 ) 

224 for hl_line in self.hl_lines 

225 ] 

226 

227 

228def calculate_includes( 2pbqb

229 lines_to_include: list[tuple[int, int]], hl_lines: list[tuple[int, int]] 

230) -> dict[tuple[int, int], IncludeInfo]: 

231 lines_groups: dict[tuple[int, int], IncludeInfo] = {} 1ijefabEqArstoumCklghcdFvBwxypznD

232 offset = 0 1ijefabEqArstoumCklghcdFvBwxypznD

233 for i, line_group in enumerate(lines_to_include): 1ijefabEqArstoumCklghcdFvBwxypznD

234 if line_group[0] > 1: 1ijefabEqArstoumCklghcdFvBwxypznD

235 if i == 0: 1ijefabqArstoumCklghcdvBwxypznD

236 offset = 2 1ijefabArstoumCklghcdBwxypznD

237 else: 

238 offset += 3 1qrstoumvwxypzn

239 info = IncludeInfo( 1ijefabEqArstoumCklghcdFvBwxypznD

240 start=line_group[0], 

241 end=line_group[1], 

242 offset=offset, 

243 hl_lines=[], 

244 ) 

245 offset += line_group[1] - line_group[0] + 1 1ijefabEqArstoumCklghcdFvBwxypznD

246 for hl_line in hl_lines: 1ijefabEqArstoumCklghcdFvBwxypznD

247 if hl_line[0] >= line_group[0] and hl_line[1] <= line_group[1]: 1ijefabEqArstoumCklghcdFvBwxypznD

248 info.hl_lines.append(hl_line) 1ijefabEqArstoumCklghcdFvBwxypznD

249 lines_groups[line_group] = info 1ijefabEqArstoumCklghcdFvBwxypznD

250 return lines_groups 1ijefabEqArstoumCklghcdFvBwxypznD

251 

252 

253def generate_hl_string(hl_lines: list[tuple[int, int]]) -> str: 2pbqb

254 hl_lines_strs: list[str] = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

255 for hl_line in hl_lines: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

256 if hl_line[0] == hl_line[1]: 1ijefab'(+S,EqArstoumCklghcd)*-Z.FvBwxypznD

257 hl_lines_strs.append(str(hl_line[0])) 1+S,qom-Z.vpn

258 else: 

259 hl_lines_strs.append(f"{hl_line[0]}-{hl_line[1]}") 1ijefab'(SEqArstumCklghcd)*ZFvBwxyznD

260 return " ".join(hl_lines_strs) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

261 

262 

263re_line = r"^\{\*\s*(\S+)\s*(.*)\*\}$" 2pbqb

264re_config = r"(\w+)\[([^\]]+)\]" 2pbqb

265 

266 

267class IncludeVariantsPreprocessor(Preprocessor): 2pbqb

268 def run(self, lines: list[str]) -> list[str]: 2pbqb

269 new_lines = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ rbnbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbsbobeb? @ D ib

270 for line in lines: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ rbnbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbsbobeb? @ D ib

271 line_match = re.match(re_line, line) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ rbnbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbsbobeb? @ D ib

272 if not line_match: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ rbnbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbsbobeb? @ D ib

273 new_lines.append(line) 2rbsb

274 continue 2rbsb

275 block_lines = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

276 src_file_str = line_match.group(1) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

277 base_path = Path(src_file_str) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

278 

279 configs_str = line_match.group(2).strip() 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

280 include_lines: list[tuple[int, int]] = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

281 highlight_lines: list[tuple[int, int]] = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

282 title: Union[str, None] = None 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

283 for config_match in re.finditer(re_config, configs_str): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

284 if config_match: 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoum;=Cklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypzn?@D

285 name = config_match.group(1) 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoum;=Cklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypzn?@D

286 value_str = config_match.group(2) 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoum;=Cklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypzn?@D

287 if name == "ln": 1ijefab/'(+S,TIUJVKWL6XM7Y89EqArstoum;=Cklghcd:)*-Z.0N1O2P3Q!4R#5$%FvBwxypzn?@D

288 include_lines.extend(parse_lines_index(value_str)) 1ijefab/TIUJVKWL6XM7Y89EqArstoumCklghcd:0N1O2P3Q!4R#5$%FvBwxypznD

289 elif name == "hl": 1ijefab'(+S,EqArstoum;=Cklghcd)*-Z.FvBwxypzn?@D

290 highlight_lines.extend(parse_lines_index(value_str)) 1ijefab'(+S,EqArstoumCklghcd)*-Z.FvBwxypznD

291 elif name == "title": 1ef;=gh?@

292 assert value_str.startswith('"') and value_str.endswith('"') 1ef;=gh?@

293 title = value_str[1:-1] 1ef;=gh?@

294 use_hl_lines: list[tuple[int, int]] = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

295 if highlight_lines: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

296 if include_lines: 1ijefab'(+S,EqArstoumCklghcd)*-Z.FvBwxypznD

297 include_infos = calculate_includes(include_lines, highlight_lines) 1ijefabEqArstoumCklghcdFvBwxypznD

298 for info in include_infos.values(): 1ijefabEqArstoumCklghcdFvBwxypznD

299 use_hl_lines.extend(info.computed_hl_lines()) 1ijefabEqArstoumCklghcdFvBwxypznD

300 else: 

301 use_hl_lines = highlight_lines 1'(+S,)*-Z.

302 use_hl_lines_str = generate_hl_string(use_hl_lines) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

303 

304 variants = calculate_variants(base_path) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

305 if len(variants) == 0: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ nbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbobeb? @ D ib

306 raise FileNotFoundError(f"Could not find any variants for {base_path}") 2nbob

307 if len(variants) == 1: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

308 folder_variants = calculate_variants_folder(base_path) 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

309 if len(folder_variants) > 1: 2a b G / ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = c d H : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

310 variants = folder_variants 1abGcdH

311 elif len(folder_variants) == 1: 2/ ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

312 file_variant_is_default = variants.get(("py38", None)) is not None 2/ ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

313 folder_variant_is_default = ( 2/ ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

314 folder_variants.get(("py38", None)) is not None 

315 ) 

316 # File name doesn't contain any suffixes, but folder does - use variants from folder 

317 if file_variant_is_default and not folder_variant_is_default: 2/ ` ' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = : { ) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @

318 variants = folder_variants 1`{

319 sorted_variants: list[Variant] = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

320 preferred_variant = None 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

321 for an in [True, False, None]: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

322 for version in ["py311", "py310", "py39", "py38"]: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

323 v = variants.get((version, an)) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

324 if v: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

325 if v.path == base_path: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

326 assert preferred_variant is None 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

327 preferred_variant = v 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

328 else: 

329 sorted_variants.append(v) 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

330 assert preferred_variant is not None 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

331 content_lines = preferred_variant.path.read_text().splitlines() 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

332 

333 internal_block_lines: list[str] = [] 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

334 if not include_lines: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

335 internal_block_lines.append( 2[ G ] fblb` jb' ( + S , | } ~ ab; = gb^ H _ hbmb{ kb) * - Z . bbcbdbeb? @ ib

336 f"{{!{preferred_variant.path}!}}", 

337 ) 

338 if include_lines != [(0, 0)]: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

339 for i, line_group in enumerate(include_lines): 2i j e f [ a b G ] fblb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hbmb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

340 if i == 0 and line_group[0] > 1: 1ijefabTIUJVKWL6XM7Y89EqArstoumCklghcd0N1O2P3Q!4R#5$%FvBwxypznD

341 internal_block_lines.extend( 1ijefabIUMY9ArstoumCklghcdN1R5%BwxypznD

342 [ 

343 "# Code above omitted 👆", 

344 "", 

345 ] 

346 ) 

347 if i >= 1: 1ijefabTIUJVKWL6XM7Y89EqArstoumCklghcd0N1O2P3Q!4R#5$%FvBwxypznD

348 internal_block_lines.extend( 1JVKWL6MqrstoumO2P3Q!Rvwxypzn

349 [ 

350 "", 

351 "# Code here omitted 👈", 

352 "", 

353 ] 

354 ) 

355 internal_block_lines.append( 1ijefabTIUJVKWL6XM7Y89EqArstoumCklghcd0N1O2P3Q!4R#5$%FvBwxypznD

356 f"{{!{preferred_variant.path}[ln:{line_group[0]}-{line_group[1]}]!}}" 

357 ) 

358 if i == len(include_lines) - 1 and line_group[1] < len( 1ijefabTIUJVKWL6XM7Y89EqArstoumCklghcd0N1O2P3Q!4R#5$%FvBwxypznD

359 content_lines 

360 ): 

361 internal_block_lines.extend( 1ijefabTIJWXM7Y8EACklghcd0NO34R#5$FBD

362 [ 

363 "", 

364 "# Code below omitted 👇", 

365 ] 

366 ) 

367 first_line = "```python" 2i j e f [ a b G ] fblb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hbmb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

368 if use_hl_lines: 2i j e f [ a b G ] fblb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hbmb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

369 first_line += f' hl_lines="{use_hl_lines_str}"' 1ijefab'(+S,EqArstoumCklghcd)*-Z.FvBwxypznD

370 if title: 2i j e f [ a b G ] fblb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hbmb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

371 first_line += f' title="{title}"' 1ef;=gh?@

372 

373 block_lines.extend( 2i j e f [ a b G ] fblb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hbmb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

374 [ 

375 f"//// tab | {preferred_variant.title}", 

376 first_line, 

377 *internal_block_lines, 

378 "```", 

379 "", 

380 "////", 

381 "", 

382 ] 

383 ) 

384 if include_lines: 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

385 first_line_full = "```python" 1ijefab/TIUJVKWL6XM7Y89EqArstoumCklghcd:0N1O2P3Q!4R#5$%FvBwxypznD

386 if highlight_lines: 1ijefab/TIUJVKWL6XM7Y89EqArstoumCklghcd:0N1O2P3Q!4R#5$%FvBwxypznD

387 hl_lines_full_str = generate_hl_string(highlight_lines) 1ijefabEqArstoumCklghcdFvBwxypznD

388 first_line_full += f' hl_lines="{hl_lines_full_str}"' 1ijefabEqArstoumCklghcdFvBwxypznD

389 if title: 1ijefab/TIUJVKWL6XM7Y89EqArstoumCklghcd:0N1O2P3Q!4R#5$%FvBwxypznD

390 first_line_full += f' title="{title}"' 1efgh

391 block_lines.extend( 1ijefab/TIUJVKWL6XM7Y89EqArstoumCklghcd:0N1O2P3Q!4R#5$%FvBwxypznD

392 [ 

393 "///// details | 👀 Full file preview", 

394 "", 

395 f"//// tab | {preferred_variant.title}", 

396 "", 

397 first_line_full, 

398 f"{{!{preferred_variant.path}!}}", 

399 "```", 

400 "", 

401 "////", 

402 "", 

403 "/////", 

404 "", 

405 ] 

406 ) 

407 if len(sorted_variants): 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

408 first_line_variant = "```python" 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

409 if title: 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

410 first_line_variant += f' title="{title}"' 1efgh

411 block_lines.extend( 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

412 [ 

413 "///// details | 🤓 Other versions and variants", 

414 "", 

415 ] 

416 ) 

417 

418 for variant in sorted_variants: 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

419 block_lines.extend([f"//// tab | {variant.title}", ""]) 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

420 if variant.is_annotated is False: 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

421 block_lines.extend( 2i j e f [ a b G ] fblbC gbk l g h ^ c d H _ hbmbD ib

422 [ 

423 "/// tip", 

424 "", 

425 "Prefer to use the `Annotated` version if possible.", 

426 "", 

427 "///", 

428 "", 

429 ] 

430 ) 

431 

432 block_lines.extend( 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

433 [ 

434 first_line_variant, 

435 f"{{!{variant.path}!}}", 

436 "```", 

437 "////", 

438 ] 

439 ) 

440 

441 block_lines.extend( 2i j e f [ a b G ] fblbjbC gbk l g h ^ c d H _ hbmbkbD ib

442 [ 

443 "", 

444 "/////", 

445 "", 

446 ] 

447 ) 

448 new_lines.extend(block_lines) 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ ab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbeb? @ D ib

449 return new_lines 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ rbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbsbeb? @ D ib

450 

451 

452class IncludeVariantsExtension(Extension): 2pbqb

453 def extendMarkdown(self, md: Markdown) -> None: 2pbqb

454 md.preprocessors.register( 2i j e f [ a b G ] fb/ lb` jb' ( + S , T I U J V K W L 6 X M 7 Y 8 9 E q A r s t o u m | } ~ rbnbab; = C gbk l g h ^ c d H _ hb: mb{ kb) * - Z . 0 N 1 O 2 P 3 Q ! 4 R # 5 $ % F v B w x y p z n bbcbdbsbobeb? @ D ib

455 IncludeVariantsPreprocessor(md), "include_variants", 110 

456 ) 

457 

458 

459def makeExtension( 2pbqb

460 *args: Any, **kwargs: Any 2pbqb

461) -> IncludeVariantsExtension: # pragma: no cover 2pbqb

462 return IncludeVariantsExtension(*args, **kwargs)