Passed
Push — master ( 8ff2fc...2dab2b )
by P.R.
04:18 queued 10s
created

sdoc.SDoc.SDoc.run_format()   A

Complexity

Conditions 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 17
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 3.3332

Importance

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