sdoc.SDoc.SDoc._read_config_file()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 16
Code Lines 8

Duplication

Lines 16
Ratio 100 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 8
dl 16
loc 16
ccs 8
cts 8
cp 1
rs 10
c 0
b 0
f 0
cc 1
nop 1
crap 1
1 1
import configparser
2 1
import os
3 1
from typing import List, Optional
4
5 1
from sdoc import sdoc2
6 1
from sdoc.error import SDocError
7 1
from sdoc.format.Format import Format
8 1
from sdoc.io.SDocIO import SDocIO
9 1
from sdoc.sdoc1.SDoc1Interpreter import SDoc1Interpreter
10 1
from sdoc.sdoc2.NodeStore import NodeStore
11 1
from sdoc.sdoc2.SDoc2Interpreter import SDoc2Interpreter
12
13
14 1 View Code Duplication
class SDoc:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
15
    """
16
    The SDoc program.
17
    """
18
19
    # ------------------------------------------------------------------------------------------------------------------
20 1
    def __init__(self):
21
        """
22
        Object contructor.
23
        """
24 1
        self._io: Optional[SDocIO] = None
25
        """
26
        The IO object.
27
        """
28
29 1
        self._format: Optional[Format] = None
30
        """
31
        The class for generation the document in the target format.
32
        """
33
34 1
        self._target_dir: str = '.'
35
        """
36
        The directory where the document in the target format must be created.
37
        """
38
39 1
        self._temp_dir: str = '.'
40
        """
41
        The directory where temporary files are stored.
42
        """
43
44 1
        self._config_path: str = ''
45
        """
46
        The path of the config file.
47
        """
48
49 1
        self._nodes_paths: List[str] = []
50
        """
51
        A list with path names from with node modules must be imported.
52
        """
53
54 1
        self._formatter_paths: List[str] = []
55
        """
56
        A list with path names from with node modules must be imported.
57
        """
58
59 1
        self._errors: int = 0
60 1
        """
61
        The total number of errors encountered at SDoc level 1 and level 2.
62
        """
63
64
    # ------------------------------------------------------------------------------------------------------------------
65 1
    @property
66 1
    def io(self) -> SDocIO:
67
        """
68
        Getter for io.
69
        """
70
        return self._io
71
72
    # ------------------------------------------------------------------------------------------------------------------
73 1
    @io.setter
74 1
    def io(self, io: SDocIO) -> None:
75
        """
76
        Setter for io.
77
78
        :param OutputStyle io: The IO object.
79
        """
80 1
        self._io = io
81
82
    # ------------------------------------------------------------------------------------------------------------------
83 1
    @property
84 1
    def config_path(self) -> str:
85
        """
86
        Getter for config_path.
87
        """
88
        return self._config_path
89
90
    # ------------------------------------------------------------------------------------------------------------------
91 1
    @config_path.setter
92 1
    def config_path(self, config_path: str) -> None:
93
        """
94
        Setter for config_path.
95
96
        :param str config_path: The path of the config file.
97
        """
98 1
        self._config_path = config_path
99
100
    # ------------------------------------------------------------------------------------------------------------------
101 1
    @property
102 1
    def target_dir(self) -> str:
103
        """
104
        Getter for target_dir.
105
        """
106
        return self.target_dir
107
108
    # ------------------------------------------------------------------------------------------------------------------
109 1
    @property
110 1
    def temp_dir(self) -> str:
111
        """
112
        Getter for temp_dir.
113
        """
114
        return self.temp_dir
115
116
    # ------------------------------------------------------------------------------------------------------------------
117 1
    def _config_create_formatter(self, config: configparser.ConfigParser) -> None:
118
        """
119
        Creates the formatter for generating the document in the target format.
120
121
        :param configparser.ConfigParser config: The config parser.
122
        """
123 1
        available_formats = ['html']
124
125
        # Read the target format of the document.
126 1
        target_format = config.get('sdoc', 'format', fallback=None)
127 1
        if target_format not in available_formats:
128
            raise SDocError("The format '{}' is not available in SDoc. Set another in config file '{}'"
129
                            .format(target_format, self._config_path))
130
131 1
        if not target_format:
132
            raise SDocError("Option 'format' in section 'sdoc' not set in config file '{0!s}'"
133
                            .format(self._config_path))
134
135
        # Read the class name for formatting the SDoc2 nodes into the target format.
136 1
        section = 'format_' + target_format
137 1
        class_name = config.get(section, 'class', fallback=None)
138 1
        if not class_name:
139
            raise SDocError("Option 'class' in section '{0!s}' not set in config file '{1!s}'".
140
                            format(section, self._config_path))
141
142
        # Import the class.
143 1
        try:
144 1
            parts = class_name.split('.')
145 1
            module = ".".join(parts[:-1])
146 1
            __import__(module)
147 1
            m = __import__(module)
148 1
            for comp in parts[1:]:
149 1
                m = getattr(m, comp)
150
        except AttributeError:
151
            raise SDocError("There is no module named '{0!s}'! Set name correctly in config file '{1!s}'"
152
                            .format(class_name, self._config_path))
153
154
        # Create the formatter.
155 1
        self._format = m(self._io, target_format, config)
156
157
    # ------------------------------------------------------------------------------------------------------------------
158 1
    def _config_set_temp_dir(self, config: configparser.ConfigParser) -> None:
159
        """
160
        Reads the directory for storing temporary files.
161
162
        :param configparser.ConfigParser config: The config parser.
163
        """
164 1
        self._temp_dir = config.get('sdoc', 'temp_dir', fallback=self._temp_dir)
165
166 1
        if not self._temp_dir:
167
            raise SDocError("Option 'temp_dir' in section 'sdoc' not set correctly in config file '{0!s}'".
168
                            format(self._config_path))
169
170 1
        if not os.access(self._temp_dir, os.W_OK):
171
            raise SDocError("Directory '{0!s}' is not writable".format(self._temp_dir))
172
173
    # ------------------------------------------------------------------------------------------------------------------
174 1
    def _config_set_target_dir(self, config: configparser.ConfigParser) -> None:
175
        """
176
        Reads the directory where the document in the target format must be created.
177
178
        :param configparser.ConfigParser config: The config parser.
179
        """
180 1
        self._target_dir = config.get('sdoc', 'target_dir', fallback=self._target_dir)
181
182 1
        if not self._target_dir:
183
            raise SDocError("Option 'target_dir' in section 'sdoc' not set correctly in config file '{0!s}'".
184
                            format(self._config_path))
185
186 1
        if not os.access(self._target_dir, os.W_OK):
187
            raise SDocError("Directory '{0!s}' is not writable".format(self._target_dir))
188
189
    # ------------------------------------------------------------------------------------------------------------------
190 1
    def _read_config_file(self) -> None:
191
        """
192
        Reads the configuration file.
193
        """
194 1
        config = configparser.ConfigParser()
195 1
        config.read(self._config_path)
196
197
        # Get the temp and target directory.
198 1
        self._config_set_temp_dir(config)
199 1
        self._config_set_target_dir(config)
200
201
        # Create the formatter for generating the document in the target format.
202 1
        self._config_create_formatter(config)
203
204 1
        self._formatter_paths.append(os.path.dirname(__file__) + '/sdoc2/formatter')
205 1
        self._nodes_paths.append(os.path.dirname(__file__) + '/sdoc2/node')
206
207
    # ------------------------------------------------------------------------------------------------------------------
208 1
    def _create_node_store(self) -> None:
209
        """
210
        Creates the node store (for storing nodes).
211
        """
212 1
        sdoc2.node_store = NodeStore(self._io)
213
214
    # ------------------------------------------------------------------------------------------------------------------
215 1
    @staticmethod
216 1
    def importing(path: str) -> None:
217
        """
218
        Imports modules from specific path.
219
220
        :param str path: The specific path.
221
        """
222 1
        modules = os.listdir(os.path.dirname(__file__) + path)
223
224 1
        path = path.replace('/', '.')
225
226 1
        for module in modules:
227 1
            if module != '__init__.py' and module[-3:] == '.py':
228 1
                __import__('sdoc' + path + module[:-3], locals(), globals())
229
230
    # ------------------------------------------------------------------------------------------------------------------
231 1
    def _import_nodes(self) -> None:
232
        """
233
        Imports nodes from path which is declared below.
234
        """
235
        # @todo improve
236 1
        self.importing('/sdoc2/node/')
237
238
    # ------------------------------------------------------------------------------------------------------------------
239 1
    def _import_formatters(self) -> None:
240
        """
241
        Imports formatters from path which is declared below.
242
        """
243
        # @todo improve
244 1
        self.importing('/sdoc2/formatter/html/')
245
246
    # ------------------------------------------------------------------------------------------------------------------
247 1
    def init(self) -> None:
248
        """
249
        Executes initiations required before running SDoc.
250
        """
251 1
        self._read_config_file()
252 1
        self._create_node_store()
253 1
        self._import_nodes()
254 1
        self._import_formatters()
255
256
    # ------------------------------------------------------------------------------------------------------------------
257 1
    def run_sdoc1(self, sdoc1_path: str, sdoc2_path: str, log_errors: bool = True) -> int:
258
        """
259
        Run the SDoc1 parser and returns the error count.
260
261
        :param str sdoc1_path: The path of the SDoc1 document.
262
        :param str sdoc2_path: The path were the SDoc2 document mut be stored.
263
        :param bool log_errors: If true the number of errors will be logged.
264
        """
265 1
        self._io.title('SDoc1')
266
267 1
        interpreter1 = SDoc1Interpreter(self._io)
268 1
        self._errors += interpreter1.process(sdoc1_path, sdoc2_path)
269
270 1
        if log_errors and self._errors:
271
            self._io.write_line(" ")
272
            self._io.title('Errors')
273
            self._io.write_error('There were {0} errors in total'.format(self._errors))
274
275 1
        return self._errors
276
277
    # ------------------------------------------------------------------------------------------------------------------
278 1
    def run_sdoc2(self, sdoc2_path: str, log_errors: bool = True) -> int:
279
        """
280
        Run the SDoc2 parser and returns the error count.
281
282
        :param str sdoc2_path: The path of the SDoc2 document.
283
        :param bool log_errors: If true the number of errors will be logged.
284
        """
285 1
        self._io.write_line('')
286 1
        self._io.title('SDoc2')
287
288 1
        interpreter2 = SDoc2Interpreter(self._io)
289 1
        self._errors += interpreter2.process(sdoc2_path)
290
291 1
        if log_errors and self._errors:
292
            self._io.write_line(" ")
293
            self._io.title('Errors')
294
            self._io.write_error('There were {0} errors in total'.format(self._errors))
295
296 1
        return self._errors
297
298
    # ------------------------------------------------------------------------------------------------------------------
299 1
    def run_format(self, log_errors: bool = True) -> int:
300
        """
301
        Generates the target document in the specific format and returns the error count.
302
303
        :param bool log_errors: If true the number of errors will be logged.
304
        """
305 1
        self._io.write_line('')
306 1
        self._io.title('Format')
307
308 1
        self._errors += sdoc2.node_store.generate(self._format)
309
310 1
        if log_errors and self._errors:
311
            self._io.write_line(" ")
312
            self._io.title('Errors')
313
            self._io.write_error('There were {0} errors in total'.format(self._errors))
314
315 1
        return self._errors
316
317
    # ------------------------------------------------------------------------------------------------------------------
318 1
    def run_sdoc(self, main_filename: str, log_errors: bool = True) -> int:
319
        """
320
        Runs the SDoc1 and SDoc2 parser and returns the error count.
321
322
        :param str main_filename: The path of the SDoc1 document.
323
        :param bool log_errors: If true the number of errors will be logged.
324
        """
325 1
        self.init()
326
327 1
        temp_filename = self._temp_dir + '/' + os.path.basename(main_filename) + '.sdoc2'
328 1
        self.run_sdoc1(main_filename, temp_filename, False)
329 1
        self.run_sdoc2(temp_filename, False)
330 1
        self.run_format(False)
331
332 1
        if log_errors and self._errors:
333 1
            self._io.write_line(" ")
334 1
            self._io.title('Errors')
335 1
            self._io.write_error('There were {0} errors in total'.format(self._errors))
336
337 1
        return self._errors
338
339
# ----------------------------------------------------------------------------------------------------------------------
340