Passed
Push — develop ( 97b560...fec923 )
by Christophe
01:08
created

pandoc_latex_tip._app   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 431
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 45
eloc 236
dl 0
loc 431
rs 8.8
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
C CollectionsDeleteCommand.handle() 0 50 9
A PandocBeamerFilterCommand.handle() 0 11 1
A CollectionsAddCommand.handle() 0 32 4
A PandocLaTeXFilterCommand.handle() 0 11 1
A CollectionsInfoCommand.handle() 0 25 3
A CollectionsListCommand.handle() 0 16 4
A IconsListCommand.handle() 0 27 4
C IconsAddCommand.handle() 0 73 11
B IconsDeleteCommand.handle() 0 41 7

1 Function

Rating   Name   Duplication   Size   Complexity  
A app() 0 15 1

How to fix   Complexity   

Complexity

Complex classes like pandoc_latex_tip._app often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
2
App module.
3
"""
4
5
import pathlib
6
import shutil
7
import sys
8
9
from cleo.application import Application
10
from cleo.commands.command import Command
11
from cleo.helpers import argument, option
12
13
import yaml
14
15
from ._main import get_core_icons, main
16
17
18
class CollectionsAddCommand(Command):
19
    """
20
    CollectionsAddCommand.
21
    """
22
23
    name = "collections add"
24
    description = "Add a file to a collection"
25
    arguments = [
26
        argument("name", description="Collection name"),
27
        argument("file", description="File name"),
28
    ]
29
30
    def handle(self) -> int:
31
        """
32
        Handle collections add command.
33
34
        Returns
35
        -------
36
        int
37
            status code
38
        """
39
        if self.argument("name") == "fontawesome":
40
            self.line("<error>You cannot modify core collection</error>")
41
            return 1
42
43
        try:
44
            dir_path = pathlib.Path(
45
                sys.prefix, "share", "pandoc_latex_tip", self.argument("name")
46
            )
47
            if not dir_path.exists():
48
                dir_path.mkdir(parents=True)
49
            file_path = pathlib.Path(self.argument("file"))
50
            dest_path = pathlib.Path(dir_path, file_path.parts[-1])
51
            shutil.copy(file_path, dest_path)
52
53
            self.line(
54
                f"Add file '{self.argument('file')}' to "
55
                f"collection '{self.argument('name')}'"
56
            )
57
58
        except PermissionError as error:
59
            self.line(f"<error>{error}</error>")
60
            return 1
61
        return 0
62
63
64
class CollectionsDeleteCommand(Command):
65
    """
66
    CollectionDeleteCommand.
67
    """
68
69
    name = "collections delete"
70
    description = "Delete a collection"
71
    arguments = [
72
        argument("name", description="Collection name"),
73
    ]
74
75
    def handle(self) -> int:
76
        """
77
        Handle collections delete command.
78
79
        Returns
80
        -------
81
        int
82
            status code
83
        """
84
        if self.argument("name") == "fontawesome":
85
            self.line("<error>You cannot modify core collection</error>")
86
            return 1
87
        try:
88
            dir_path = pathlib.Path(
89
                sys.prefix, "share", "pandoc_latex_tip", self.argument("name")
90
            )
91
            config_path = pathlib.Path(
92
                sys.prefix,
93
                "share",
94
                "pandoc_latex_tip",
95
                "config.yml",
96
            )
97
            try:
98
                if config_path.exists():
99
                    with config_path.open(encoding="utf-8") as stream:
100
                        icons = yaml.safe_load(stream)
101
                        for definition in icons:
102
                            if definition["collection"] == self.argument("name"):
103
                                self.line(
104
                                    f"<error>Collection '{self.argument('name')}' "
105
                                    f"is in use</error>"
106
                                )
107
                                return 1
108
            except PermissionError as error:
109
                self.line(f"<error>{error}</error>")
110
                return 1
111
112
            if dir_path.exists():
113
                shutil.rmtree(dir_path)
114
                self.line(f"Delete collection '{self.argument('name')}'")
115
            else:
116
                self.line(
117
                    f"<error>Collection '{self.argument('name')}' "
118
                    f"does not exist</error>"
119
                )
120
                return 1
121
        except PermissionError as error:
122
            self.line(f"<error>{error}</error>")
123
            return 1
124
        return 0
125
126
127
class CollectionsListCommand(Command):
128
    """
129
    CollectionsListCommand.
130
    """
131
132
    name = "collections"
133
    description = "List the collections"
134
135
    def handle(self) -> int:
136
        """
137
        Handle collections command.
138
139
        Returns
140
        -------
141
        int
142
            status code
143
        """
144
        dir_path = pathlib.Path(sys.prefix, "share", "pandoc_latex_tip")
145
        for folder in dir_path.iterdir():
146
            if folder.parts[-1] == "fontawesome":
147
                self.line("<info>fontawesome *</info>")
148
            elif folder.is_dir():
149
                self.line(folder.parts[-1])
150
        return 0
151
152
153
class CollectionsInfoCommand(Command):
154
    """
155
    CollectionsInfoCommand.
156
    """
157
158
    name = "collections info"
159
    description = "Display a collection"
160
    arguments = [
161
        argument("name", description="Collection name"),
162
    ]
163
164
    def handle(self) -> int:
165
        """
166
        Handle collections info command.
167
168
        Returns
169
        -------
170
        int
171
            status code
172
        """
173
        dir_path = pathlib.Path(
174
            sys.prefix,
175
            "share",
176
            "pandoc_latex_tip",
177
            self.argument("name"),
178
        )
179
        if dir_path.exists():
180
            for filename in dir_path.iterdir():
181
                self.line(filename.parts[-1])
182
        else:
183
            self.line(
184
                f"<error>Collection '{self.argument('name')}' "
185
                f"does not exist</error>"
186
            )
187
            return 1
188
        return 0
189
190
191
class IconsAddCommand(Command):
192
    """
193
    IconsAddCommand.
194
    """
195
196
    name = "icons add"
197
    description = "Add a set of icons from a collection"
198
    arguments = [
199
        argument("name", description="Collection name"),
200
    ]
201
    options = [
202
        option("css", flag=False, description="css filename from the collection"),
203
        option("ttf", flag=False, description="ttf filename from the collection"),
204
        option("prefix", flag=False, description="icon prefix"),
205
    ]
206
207
    # pylint: disable=too-many-return-statements
208
    def handle(self) -> int:
209
        """
210
        Handle icons add command.
211
212
        Returns
213
        -------
214
        int
215
            status code
216
        """
217
        if self.argument("name") == "fontawesome":
218
            self.line("<error>You cannot modify core collection</error>")
219
            return 1
220
        dir_path = pathlib.Path(
221
            sys.prefix,
222
            "share",
223
            "pandoc_latex_tip",
224
            self.argument("name"),
225
        )
226
        if dir_path.exists():
227
            css_file = pathlib.Path(dir_path, self.option("css"))
228
            if not css_file.exists():
229
                self.line(
230
                    f"<error>Collection '{self.argument('name')}' "
231
                    f"does not contain '{self.option('css')}'</error>"
232
                )
233
                return 1
234
            ttf_file = pathlib.Path(dir_path, self.option("ttf"))
235
            if not ttf_file.exists():
236
                self.line(
237
                    f"<error>Collection '{self.argument('name')}' "
238
                    f"does not contain '{self.option('ttf')}'</error>"
239
                )
240
                return 1
241
            config_path = pathlib.Path(
242
                sys.prefix,
243
                "share",
244
                "pandoc_latex_tip",
245
                "config.yml",
246
            )
247
            try:
248
                if config_path.exists():
249
                    with config_path.open(encoding="utf-8") as stream:
250
                        icons = yaml.safe_load(stream)
251
                        for definition in icons:
252
                            if definition["prefix"] == self.option("prefix"):
253
                                self.line(
254
                                    f"<error>Prefix '{self.option('prefix')}' "
255
                                    f"is already used</error>"
256
                                )
257
                                return 1
258
                else:
259
                    icons = []
260
                icons.append(
261
                    {
262
                        "collection": self.argument("name"),
263
                        "css": self.option("css"),
264
                        "ttf": self.option("ttf"),
265
                        "prefix": self.option("prefix"),
266
                    },
267
                )
268
                with config_path.open(mode="w", encoding="utf-8") as stream:
269
                    stream.write(yaml.dump(icons, sort_keys=False))
270
            except PermissionError as error:
271
                self.line(f"<error>{error}</error>")
272
                return 1
273
274
        else:
275
            self.line(
276
                f"<error>Collection '{self.argument('name')}' "
277
                f"does not exist</error>"
278
            )
279
            return 1
280
        return 0
281
282
283
class IconsDeleteCommand(Command):
284
    """
285
    IconsDeleteCommand.
286
    """
287
288
    name = "icons delete"
289
    description = "Delete a set of icons"
290
    options = [
291
        option("prefix", flag=False, description="icon prefix"),
292
    ]
293
294
    def handle(self) -> int:
295
        """
296
        Handle icons delete command.
297
298
        Returns
299
        -------
300
        int
301
            status code
302
        """
303
        if self.option("prefix") in ("fa-", "far-", "fab-"):
304
            self.line("<error>You cannot modify core icons</error>")
305
            return 1
306
        config_path = pathlib.Path(
307
            sys.prefix,
308
            "share",
309
            "pandoc_latex_tip",
310
            "config.yml",
311
        )
312
        try:
313
            if config_path.exists():
314
                with config_path.open(encoding="utf-8") as stream:
315
                    icons = yaml.safe_load(stream)
316
                keep = [
317
                    definition
318
                    for definition in icons
319
                    if definition["prefix"] != self.option("prefix")
320
                ]
321
                if keep != icons:
322
                    with config_path.open(mode="w", encoding="utf-8") as stream:
323
                        stream.write(yaml.dump(keep, sort_keys=False))
324
                else:
325
                    self.line("<error>Unexisting prefix</error>")
326
                    return 1
327
            else:
328
                self.line("<error>Unexisting config file</error>")
329
                return 1
330
331
        except PermissionError as error:
332
            self.line(f"<error>{error}</error>")
333
            return 1
334
        return 0
335
336
337
class IconsListCommand(Command):
338
    """
339
    IconsListCommand.
340
    """
341
342
    name = "icons"
343
    description = "List the set of icons"
344
345
    def handle(self) -> int:
346
        """
347
        Handle icons command.
348
349
        Returns
350
        -------
351
        int
352
            status code
353
        """
354
        icons = get_core_icons()
355
        config_path = pathlib.Path(
356
            sys.prefix,
357
            "share",
358
            "pandoc_latex_tip",
359
            "config.yml",
360
        )
361
        try:
362
            if config_path.exists():
363
                with config_path.open(encoding="utf-8") as stream:
364
                    icons.extend(yaml.safe_load(stream))
365
        except PermissionError as error:
366
            self.line(f"<error>{error}</error>")
367
            return 1
368
369
        self.line(yaml.dump(icons, sort_keys=False))
370
371
        return 0
372
373
374
class PandocLaTeXFilterCommand(Command):
375
    """
376
    PandocLaTeXFilterCommand.
377
    """
378
379
    name = "latex"
380
    description = "Run pandoc filter for LaTeX document"
381
382
    def handle(self) -> int:
383
        """
384
        Handle latex command.
385
386
        Returns
387
        -------
388
        int
389
            status code
390
        """
391
        main()
392
        return 0
393
394
395
class PandocBeamerFilterCommand(Command):
396
    """
397
    PandocBeamerFilterCommand.
398
    """
399
400
    name = "beamer"
401
    description = "Run pandoc filter for Beamer document"
402
403
    def handle(self) -> int:
404
        """
405
        Handle beamer command.
406
407
        Returns
408
        -------
409
        int
410
            status code
411
        """
412
        main()
413
        return 0
414
415
416
def app() -> None:
417
    """
418
    Create a cleo application.
419
    """
420
    application = Application("Pandoc LaTeX Tip Filter")
421
    application.add(CollectionsAddCommand())
422
    application.add(CollectionsDeleteCommand())
423
    application.add(CollectionsListCommand())
424
    application.add(CollectionsInfoCommand())
425
    application.add(IconsAddCommand())
426
    application.add(IconsDeleteCommand())
427
    application.add(IconsListCommand())
428
    application.add(PandocLaTeXFilterCommand())
429
    application.add(PandocBeamerFilterCommand())
430
    application.run()
431