Completed
Push — develop ( 538237...38b266 )
by Jace
14s queued 10s
created

doorstop.gui.main.Application.__init__()   B

Complexity

Conditions 1

Size

Total Lines 54
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 41
dl 0
loc 54
ccs 0
cts 0
cp 0
rs 8.896
c 0
b 0
f 0
cc 1
nop 4
crap 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
#!/usr/bin/env python
2
# SPDX-License-Identifier: LGPL-3.0-only
3 1
4
"""Graphical interface for Doorstop."""
5 1
6 1
import argparse
7
import functools
8
import logging
9
import os
10
import sys
11
from unittest.mock import Mock
12
13
from doorstop import common, settings
14
from doorstop.common import HelpFormatter, WarningFormatter
15 1
from doorstop.gui import application, widget
16 1
17 1
try:
18 1
    import tkinter as tk
19 1
    from tkinter import ttk
20
except ImportError as _exc:
21 1
    sys.stderr.write("WARNING: {}\n".format(_exc))
22 1
    tk = Mock()
23 1
    ttk = Mock()
24 1
25 1
26
log = common.logger(__name__)
27 1
28
29
def main(args=None):
30 1
    """Process command-line arguments and run the program."""
31
    from doorstop import GUI, VERSION
32 1
33
    # Shared options
34
    debug = argparse.ArgumentParser(add_help=False)
35 1
    debug.add_argument('-V', '--version', action='version', version=VERSION)
36 1
    debug.add_argument(
37 1
        '-v', '--verbose', action='count', default=0, help="enable verbose logging"
38
    )
39 1
    shared = {'formatter_class': HelpFormatter, 'parents': [debug]}
40 1
    parser = argparse.ArgumentParser(prog=GUI, description=__doc__, **shared)
41
42
    # Build main parser
43 1
    parser.add_argument(
44
        '-j', '--project', metavar="PATH", help="path to the root of the project"
45
    )
46
47 1
    # Parse arguments
48
    args = parser.parse_args(args=args)
49
50 1
    # Configure logging
51
    _configure_logging(args.verbose)
52
53 1
    # Run the program
54 1
    try:
55 1
        success = run(args, os.getcwd(), parser.error)
56 1
    except KeyboardInterrupt:
57 1
        log.debug("program interrupted")
58 1
        success = False
59 1
    if success:
60
        log.debug("program exited")
61 1
        return 0
62 1
    else:
63
        log.debug("program exited with error")
64
        return 1
65 1
66
67
def _configure_logging(verbosity=0):
68 1
    """Configure logging using the provided verbosity level (0+)."""
69 1
    # Configure the logging level and format
70 1
    if verbosity == 0:
71 1
        level = settings.VERBOSE_LOGGING_LEVEL
72 1
        default_format = settings.VERBOSE_LOGGING_FORMAT
73 1
        verbose_format = settings.VERBOSE_LOGGING_FORMAT
74 1
    elif verbosity == 1:
75 1
        level = settings.VERBOSE2_LOGGING_LEVEL
76
        default_format = settings.VERBOSE_LOGGING_FORMAT
77 1
        verbose_format = settings.VERBOSE_LOGGING_FORMAT
78 1
    else:
79 1
        level = settings.VERBOSE2_LOGGING_LEVEL
80
        default_format = settings.TIMED_LOGGING_FORMAT
81
        verbose_format = settings.TIMED_LOGGING_FORMAT
82 1
83 1
    # Set a custom formatter
84 1
    logging.basicConfig(level=level)
85
    formatter = WarningFormatter(default_format, verbose_format)
86
    logging.root.handlers[0].setFormatter(formatter)
87 1
88
89
def run(args, cwd, error):
90
    """Start the GUI.
91
92
    :param args: Namespace of CLI arguments (from this module or the CLI)
93
    :param cwd: current working directory
94
    :param error: function to call for CLI errors
95 1
96
    """
97 1
    from doorstop import __project__, __version__
98 1
99
    # Exit if tkinter is not available
100
    if isinstance(tk, Mock) or isinstance(ttk, Mock):
101
        return error("tkinter is not available")
102
103
    else:
104
105
        root = widget.Tk()
106
        root.title("{} ({})".format(__project__, __version__))
107
108
        from sys import platform as _platform
109
110
        # Load the icon
111
        if _platform in ("linux", "linux2"):
112
            # Linux
113
            from doorstop.gui import resources
114
115
            root.tk.call(
116
                # pylint: disable=protected-access
117
                'wm',
118
                'iconphoto',
119
                root._w,
120
                tk.PhotoImage(data=resources.b64_doorstopicon_png),
121
            )
122
        elif _platform == "darwin":
123
            # macOS
124
            pass  # TODO
125
        elif _platform in ("win32", "win64"):
126
            # Windows
127
            from doorstop.gui import resources
128
            import base64
129
            import tempfile
130
131
            try:
132
                with tempfile.TemporaryFile(
133
                    mode='w+b', suffix=".ico", delete=False
134
                ) as theTempIconFile:
135
                    theTempIconFile.write(
136
                        base64.b64decode(resources.b64_doorstopicon_ico)
137
                    )
138
                    theTempIconFile.flush()
139
                root.iconbitmap(theTempIconFile.name)
140
            finally:
141
                try:
142
                    os.unlink(theTempIconFile.name)
143
                except Exception:  # pylint: disable=W0703
144
                    pass
145
146
        app = application.Application(root, cwd, args.project)
147
148
        root.update()
149
        root.minsize(root.winfo_width(), root.winfo_height())
150
        app.mainloop()
151
152
        return True
153
154
155 View Code Duplication
def _log(func):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
156
    """Log name and arguments."""
157
158
    @functools.wraps(func)
159
    def wrapped(self, *args, **kwargs):
160
        sargs = "{}, {}".format(
161
            ', '.join(repr(a) for a in args),
162
            ', '.join("{}={}".format(k, repr(v)) for k, v in kwargs.items()),
163
        )
164
        msg = "log: {}: {}".format(func.__name__, sargs.strip(", "))
165
        if not isinstance(self, ttk.Frame) or not self.ignore:
166
            log.debug(msg.strip())
167
        return func(self, *args, **kwargs)
168
169
    return wrapped
170
171
172
if __name__ == '__main__':
173
    sys.exit(main())
174