YouTubeDownloader v1.1.2
YouTube content downloader
Loading...
Searching...
No Matches
configParser.py
Go to the documentation of this file.
1"""!
2********************************************************************************
3@file configParser.py
4@brief Load and store settings from doxyfile
5 origin code see: https://github.com/TraceSoftwareInternational/doxygen-python-interface
6********************************************************************************
7"""
8
9import logging
10import os
11import re
12
13
14class ParseException(Exception):
15 """!
16 @brief Exception throw when error during parsing doxygen config.
17 Will probably means that there is an error in the doxygen config file
18 """
19
20
22 """!
23 @brief This class should be used to parse and store a doxygen configuration file
24 """
25
26 def __init__(self) -> None:
27 self.__single_line_option_regex = re.compile("^\\s*(\\w+)\\s*=\\s*([^\\\\]*)\\s*$")
28 self.__first_line_of_multine_option_regex = re.compile("^\\s*(\\w+)\\s*=\\s*(.*)\\\\$")
29
30 def load_configuration(self, doxyfile: str) -> dict[str, str | list[str]]:
31 """!
32 @brief Parse a Doxygen configuration file
33 @param doxyfile : doxyfile: Path to the Doxygen configuration file
34 @return A dict with all doxygen configuration
35 """
36
37 if not os.path.exists(doxyfile):
38 logging.error("Impossible to access to %s", doxyfile)
39 raise FileNotFoundError(doxyfile)
40
41 configuration: dict[str, str | list[str]] = {}
42
43 with open(doxyfile, 'r', encoding='utf-8') as file:
44
45 in_multiline_option = False
46 current_multiline_option_name = None
47
48 for line in file.readlines():
49 line = line.strip()
50 if len(line) == 0:
51 continue
52
53 if self.__is_comment_line(line):
54 continue
55
56 if in_multiline_option:
57 if not line.endswith('\\'):
58 in_multiline_option = False
59 option_value = line.rstrip('\\').strip()
60 if current_multiline_option_name is not None:
61 configuration[current_multiline_option_name].append(option_value)
62
64 current_multiline_option_name, option_value = self.__extract_multiline_option_name_and_first_value(line)
65 configuration[current_multiline_option_name] = [option_value]
66 in_multiline_option = True
67
68 elif self.__is_single_line_option(line):
69 option_name, option_value = self.__extract_single_line_option_name_and_value(line)
70 configuration[option_name] = option_value
71
72 return configuration
73
74 def store_configuration(self, config: dict[str, str | list[str]], doxyfile: str) -> None:
75 """!
76 @brief Store the doxygen configuration to the disk
77 @param config : The doxygen configuration you want to write on disk
78 @param doxyfile : The output path where configuration will be written. If the file exist, it will be truncated
79 """
80
81 logging.debug("Store configuration in %s", doxyfile)
82
83 lines = []
84 for option_name, option_value in config.items():
85 if isinstance(option_value, list):
86 # Changes by Timo Unger (add with force_double_quote) */
87 lines.append(f"{option_name} = {self.__add_double_quote_if_required(option_value[0], force_double_quote=True)} \\")
88 lines.extend([f"\t{self.__add_double_quote_if_required(value, force_double_quote=True)} \\" for value in option_value[1:-1]])
89 lines.append(f"\t{self.__add_double_quote_if_required(option_value[-1], force_double_quote=True)}")
90 elif isinstance(option_value, str):
91 lines.append(f"{option_name} = {self.__add_double_quote_if_required(option_value)}")
92
93 with open(doxyfile, 'w', encoding='utf-8') as file:
94 file.write("\n".join(lines))
95
96 def __extract_multiline_option_name_and_first_value(self, line: str) -> tuple[str, str]:
97 """!
98 @brief Extract the option name and the first value of multi line option
99 @param line : The line you want to parse
100 @return the option name and the option first value
101 """
102
103 matches = self.__first_line_of_multine_option_regex.search(line)
104 if matches is None or len(matches.groups()) != 2:
105 logging.error("Impossible to extract first value off multi line option from: %s", line)
106 raise ParseException(f"Impossible to extract first value off multi line option from: {line}")
107
108 return matches.group(1), self.__remove_double_quote_if_required(matches.group(2))
109
110 def __extract_single_line_option_name_and_value(self, line: str) -> tuple[str, str]:
111 """!
112 @brief Extract the option name and the value of single line option
113 @param line : The line you want to parse
114 @return the option name and the option value
115 """
116
117 matches = self.__single_line_option_regex.search(line)
118
119 if matches is None or len(matches.groups()) != 2:
120 logging.error("Impossible to extract option name and value from: %s", line)
121 raise ParseException(f"Impossible to extract option name and value from: {line}")
122
123 return matches.group(1), self.__remove_double_quote_if_required(matches.group(2))
124
125 def __is_single_line_option(self, line: str) -> bool:
126 """!
127 @brief Match single line option
128 @param line : The line you want to parse
129 @return single line option status
130 """
131 return self.__single_line_option_regex.match(line) is not None
132
133 def __is_comment_line(self, line: str) -> bool:
134 """!
135 @brief Match comment line
136 @param line : The line you want to parse
137 @return comment line option status
138 """
139 return line.startswith("#")
140
141 def __is_first_line_of_multiline_option(self, line: str) -> bool:
142 """!
143 @brief Match first line option
144 @param line : The line you want to parse
145 @return first line option status
146 """
147 return self.__first_line_of_multine_option_regex.match(line) is not None
148
149 @staticmethod
150 def __remove_double_quote_if_required(option_value: str) -> str:
151 """!
152 @brief Remove the double quote around string in option value.
153 Will be replaced when rewrite the configuration
154 @param option_value : The value you want to work on
155 @return The option value proper
156 """
157 if option_value.startswith('"') and option_value.endswith('"'):
158 option_value_formatted = option_value[1:-1]
159 logging.debug("Remove quote from %s to %s", option_value, option_value_formatted)
160 return option_value_formatted
161
162 return option_value
163
164 @staticmethod
165 def __add_double_quote_if_required(option_value: str, force_double_quote: bool = False) -> str:
166 """!
167 @brief Add the double quote around string in option value if its required
168 @param option_value : The value you want to work on
169 @param force_double_quote : force double quote
170 @return The option value proper
171 """
172 if (" " in option_value) or force_double_quote: # Changes by Timo Unger (additional force_double_quote option) */
173 option_value_formatted = f'"{option_value}"'
174 logging.debug("Add quote from %s to %s", option_value, option_value_formatted)
175 return option_value_formatted
176
177 return option_value
This class should be used to parse and store a doxygen configuration file.
None store_configuration(self, dict[str, str|list[str]] config, str doxyfile)
Store the doxygen configuration to the disk.
tuple[str, str] __extract_single_line_option_name_and_value(self, str line)
tuple[str, str] __extract_multiline_option_name_and_first_value(self, str line)
dict[str, str|list[str]] load_configuration(self, str doxyfile)
Parse a Doxygen configuration file.
Exception throw when error during parsing doxygen config.