Coverage for src/pyTRLCConverter/render_config.py: 100%

77 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-06-26 12:41 +0000

1""" Provides the render configuration to all converters. 

2 

3 Author: Andreas Merkle (andreas.merkle@newtec.de) 

4""" 

5 

6# pyTRLCConverter - A tool to convert TRLC files to specific formats. 

7# Copyright (c) 2024 - 2026 NewTec GmbH 

8# 

9# This file is part of pyTRLCConverter program. 

10# 

11# The pyTRLCConverter program is free software: you can redistribute it and/or modify it under 

12# the terms of the GNU General Public License as published by the Free Software Foundation, 

13# either version 3 of the License, or (at your option) any later version. 

14# 

15# The pyTRLCConverter program is distributed in the hope that it will be useful, but 

16# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

17# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License along with pyTRLCConverter. 

20# If not, see <https://www.gnu.org/licenses/>. 

21 

22# Imports ********************************************************************** 

23import json 

24import re 

25 

26from pyTRLCConverter.logger import log_verbose 

27 

28# Variables ******************************************************************** 

29 

30# Classes ********************************************************************** 

31 

32 

33class RenderConfig(): 

34 # lobster-trace: SwRequirements.sw_req_render_configuration 

35 """Render configuration provider. 

36 """ 

37 

38 FORMAT_SPECIFIER_PLAIN = "plain" # Plain text format; no special formatting, e.g. for line breaks, lists, etc. 

39 FORMAT_SPECIFIER_MD = "md" # CommonMark Markdown format; https://spec.commonmark.org/0.31.2/ 

40 FORMAT_SPECIFIER_RST = "rst" # ReStructuredText format; https://docutils.sourceforge.io/rst.html 

41 FORMAT_SPECIFIER_GFM = "gfm" # GitHub Flavored Markdown format; https://github.github.com/gfm/ 

42 FORMAT_SPECIFIER_XHTML = "xhtml" # XHTML format; https://www.w3.org/TR/xhtml1/ 

43 FORMAT_SPECIFIER_PATH = "path" # File path format; the value is a path to an external file. 

44 

45 def __init__(self): 

46 """Constructs the render configuration provider. 

47 """ 

48 # The render configuration as dict. 

49 # 

50 # Example in JSON format: 

51 # { "renderCfg": [{ "package": "XX", "type": "YY", "attribute": "ZZ", "format": "md", 

52 # "tableOptions": { "border": "<css-style>", "headingStyle": "<css-style>" } }] } 

53 self._cfg = {} 

54 

55 def load(self, file_name: str) -> bool: 

56 """Loads the render configuration from the given file. 

57  

58 Args: 

59 file_name (str): Path to the render configuration file. 

60  

61 Returns: 

62 bool: True if successful, False otherwise. 

63 """ 

64 status = False 

65 

66 log_verbose(f"Loading render configuration {file_name}.") 

67 

68 try: 

69 with open(file_name, 'r', encoding='utf-8') as f: 

70 self._cfg = json.load(f) 

71 status = True 

72 

73 except FileNotFoundError: 

74 pass 

75 

76 return status 

77 

78 def _is_package_match(self, item: dict, trlc_package: str) -> bool: 

79 """Checks if the given TRLC package matches the package pattern in the given item. 

80 

81 Args: 

82 item (dict): Single render configuration item. 

83 trlc_package (str): The TRLC package. 

84 

85 Returns: 

86 bool: If the given TRLC package matches the package pattern in the given item. 

87 """ 

88 it_matches = False 

89 

90 if "package" in item: 

91 if re.match(item["package"], trlc_package): 

92 it_matches = True 

93 

94 return it_matches 

95 

96 def _is_type_match(self, item: dict, trlc_type: str) -> bool: 

97 """Checks if the given TRLC type matches the type pattern in the given item. 

98 

99 Args: 

100 item (dict): Single render configuration item. 

101 trlc_type (str): The TRLC type. 

102 

103 Returns: 

104 bool: If the given TRLC type matches the type pattern in the given item. 

105 """ 

106 it_matches = False 

107 

108 if "type" in item: 

109 if re.match(item["type"], trlc_type): 

110 it_matches = True 

111 

112 return it_matches 

113 

114 def _is_type_attribute_match(self, item: dict, trlc_type_attribute: str) -> bool: 

115 """Checks if the given TRLC type attribute matches the type attribute pattern in the given item. 

116 

117 Args: 

118 item (dict): Single render configuration item. 

119 trlc_type (str): The TRLC type attribute. 

120 

121 Returns: 

122 bool: If the given TRLC type attribute matches the type attribute pattern in the given item. 

123 """ 

124 it_matches = False 

125 

126 if "attribute" in item: 

127 if re.match(item["attribute"], trlc_type_attribute): 

128 it_matches = True 

129 

130 return it_matches 

131 

132 def get_format_specifier(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> str: 

133 """Returns the format specifier for the given TRLC package, type and attribute. 

134 

135 Args: 

136 trlc_package (str): The TRLC package. 

137 trlc_type (str): The TRLC type. 

138 trlc_type_attribute (str): The TRLC type attribute. 

139 

140 Returns: 

141 str: The format specifier for the given TRLC package, type and attribute. 

142 """ 

143 format_specifier = RenderConfig.FORMAT_SPECIFIER_PLAIN 

144 

145 if "renderCfg" in self._cfg: 

146 for item in self._cfg["renderCfg"]: 

147 match_list = [] 

148 

149 match_list.append(self._is_package_match(item, trlc_package)) 

150 match_list.append(self._is_type_match(item, trlc_type)) 

151 match_list.append(self._is_type_attribute_match(item, trlc_type_attribute)) 

152 

153 # All of the available ones must match! 

154 if all(match_list): 

155 if "format" in item: 

156 format_specifier = item["format"] 

157 

158 # First match wins. 

159 break 

160 

161 return format_specifier 

162 

163 def get_table_options(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> dict: 

164 # lobster-trace: SwRequirements.sw_req_reqif_render_table_options 

165 """Returns the table rendering options for the given TRLC package, type and attribute. 

166 

167 The returned dictionary may contain the following optional keys: 

168 

169 - ``"border"`` (str): CSS style value applied to the ``<table>`` element's ``style`` 

170 attribute (e.g. ``"border: 1px solid black; border-collapse: collapse;"``). 

171 - ``"headingStyle"`` (str): CSS style value applied to each ``<th>`` cell's ``style`` 

172 attribute (e.g. ``"background-color: #c0c0c0;"``). 

173 

174 Args: 

175 trlc_package (str): The TRLC package. 

176 trlc_type (str): The TRLC type. 

177 trlc_type_attribute (str): The TRLC type attribute. 

178 

179 Returns: 

180 dict: Table options dict, or empty dict if no table options are configured. 

181 """ 

182 table_options = {} 

183 

184 if "renderCfg" in self._cfg: 

185 for item in self._cfg["renderCfg"]: 

186 match_list = [] 

187 

188 match_list.append(self._is_package_match(item, trlc_package)) 

189 match_list.append(self._is_type_match(item, trlc_type)) 

190 match_list.append(self._is_type_attribute_match(item, trlc_type_attribute)) 

191 

192 # All of the available ones must match! 

193 if all(match_list): 

194 table_options = item.get("tableOptions", {}) 

195 

196 # First match wins. 

197 break 

198 

199 return table_options 

200 

201 def is_format_plain(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool: 

202 """Checks if the given TRLC package, type and attribute should be rendered in plain text format. 

203 

204 Args: 

205 trlc_package (str): The TRLC package. 

206 trlc_type (str): The TRLC type. 

207 trlc_type_attribute (str): The TRLC type attribute. 

208  

209 Returns: 

210 bool: True if the given TRLC attribute has plain text format, otherwise False. 

211 """ 

212 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_PLAIN 

213 

214 def is_format_md(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool: 

215 """Checks if the given TRLC package, type and attribute should be rendered in markdown format. 

216 

217 Args: 

218 trlc_package (str): The TRLC package. 

219 trlc_type (str): The TRLC type. 

220 trlc_type_attribute (str): The TRLC type attribute. 

221  

222 Returns: 

223 bool: True if the given TRLC attribute has Markdown format, otherwise False. 

224 """ 

225 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_MD 

226 

227 def is_format_rst(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool: 

228 """Checks if the given TRLC package, type and attribute should be rendered in reStructuredText format. 

229 

230 Args: 

231 trlc_package (str): The TRLC package. 

232 trlc_type (str): The TRLC type. 

233 trlc_type_attribute (str): The TRLC type attribute. 

234 

235 Returns: 

236 bool: True if the given TRLC attribute has reStructuredText format, otherwise False. 

237 """ 

238 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_RST 

239 

240 def is_format_gfm(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool: 

241 """Checks if the given TRLC package, type and attribute should be rendered in GitHub Flavored Markdown format. 

242 

243 Args: 

244 trlc_package (str): The TRLC package. 

245 trlc_type (str): The TRLC type. 

246 trlc_type_attribute (str): The TRLC type attribute. 

247  

248 Returns: 

249 bool: True if the given TRLC attribute has GitHub Flavored Markdown format, otherwise False. 

250 """ 

251 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_GFM 

252 

253 def is_format_xhtml(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool: 

254 """Checks if the given TRLC package, type and attribute should be rendered in XHTML format. 

255 

256 Args: 

257 trlc_package (str): The TRLC package. 

258 trlc_type (str): The TRLC type. 

259 trlc_type_attribute (str): The TRLC type attribute. 

260 

261 Returns: 

262 bool: True if the given TRLC attribute has XHTML format, otherwise False. 

263 """ 

264 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_XHTML 

265 

266 def is_format_path(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool: 

267 """Checks if the given TRLC package, type and attribute should be rendered as a file path. 

268 

269 Args: 

270 trlc_package (str): The TRLC package. 

271 trlc_type (str): The TRLC type. 

272 trlc_type_attribute (str): The TRLC type attribute. 

273 

274 Returns: 

275 bool: True if the given TRLC attribute has path format, otherwise False. 

276 """ 

277 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_PATH 

278 

279 

280# Functions ******************************************************************** 

281 

282# Main *************************************************************************