Failed Conditions
Pull Request — master (#1152)
by Lasse
03:36
created

coalib.output.printers.ConfWriter.write_section()   F

Complexity

Conditions 11

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 11
dl 0
loc 27
rs 3.1765

How to fix   Complexity   

Complexity

Complex classes like coalib.output.printers.ConfWriter.write_section() 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
import traceback
2
from pyprint.ColorPrinter import ColorPrinter
3
4
from coalib.output.printers.LOG_LEVEL import LOG_LEVEL, LOG_LEVEL_COLORS
5
from coalib.processes.communication.LogMessage import LogMessage
6
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
7
8
class LogPrinter:
9
    """
10
    The LogPrinter class allows to print log messages to an underlying Printer.
11
12
    This class is an adapter, means you can create a LogPrinter from every
13
    existing Printer instance.
14
    """
15
    def __init__(self,
16
                 printer,
17
                 log_level=LOG_LEVEL.WARNING,
18
                 timestamp_format="%X"):
19
        """
20
        Creates a new log printer from an existing Printer.
21
22
        :param printer:          The underlying Printer where log messages
23
                                 shall be written to. If you inherit from
24
                                 LogPrinter, set it to self.
25
        :param log_level:        The minimum log level, everything below will
26
                                 not be logged.
27
        :param timestamp_format: The format string for the
28
                                 datetime.today().strftime(format) method.
29
        """
30
        self._printer = printer
31
        self.log_level = log_level
32
        self.timestamp_format = timestamp_format
33
34
    @property
35
    def printer(self):
36
        """
37
        Returns the underlying printer where logs are printed to.
38
        """
39
        return self._printer
40
41
    def _get_log_prefix(self, log_level, timestamp):
42
        datetime_string = timestamp.strftime(self.timestamp_format)
43
44
        if datetime_string != "":
45
            datetime_string = "[" + datetime_string + "]"
46
47
        return '[{}]{}'.format(LOG_LEVEL.reverse.get(log_level, "ERROR"),
48
                               datetime_string)
49
50
    def debug(self, *messages, delimiter=" ", timestamp=None, **kwargs):
51
        self.log_message(LogMessage(LOG_LEVEL.DEBUG,
52
                                    *messages,
53
                                    delimiter=delimiter,
54
                                    timestamp=timestamp),
55
                         **kwargs)
56
57
    def info(self, *messages, delimiter=" ", timestamp=None, **kwargs):
58
        self.log_message(LogMessage(LOG_LEVEL.INFO,
59
                                    *messages,
60
                                    delimiter=delimiter,
61
                                    timestamp=timestamp),
62
                         **kwargs)
63
64
    def warn(self, *messages, delimiter=" ", timestamp=None, **kwargs):
65
        self.log_message(LogMessage(LOG_LEVEL.WARNING,
66
                                    *messages,
67
                                    delimiter=delimiter,
68
                                    timestamp=timestamp),
69
                         **kwargs)
70
71
    def err(self, *messages, delimiter=" ", timestamp=None, **kwargs):
72
        self.log_message(LogMessage(LOG_LEVEL.ERROR,
73
                                    *messages,
74
                                    delimiter=delimiter,
75
                                    timestamp=timestamp),
76
                         **kwargs)
77
78
    def log(self, log_level, message, timestamp=None, **kwargs):
79
        self.log_message(LogMessage(log_level,
80
                                    message,
81
                                    timestamp=timestamp),
82
                         **kwargs)
83
84
    def log_exception(self,
85
                      message,
86
                      exception,
87
                      log_level=LOG_LEVEL.ERROR,
88
                      timestamp=None,
89
                      **kwargs):
90
        """
91
        If the log_level of the printer is greater than DEBUG, it prints
92
        only the message. If it is DEBUG or lower, it shows the message
93
        along with the traceback of the exception.
94
95
        :param message:   The message to print.
96
        :param exception: The exception to print.
97
        :param log_level: The log_level of this message (not used when
98
                          logging the traceback. Tracebacks always have
99
                          a level of DEBUG).
100
        :param timestamp: The time at which this log occured. Defaults to
101
                          the current time.
102
        :param kwargs:    Keyword arguments to be passed when logging the
103
                          message (not used when logging the traceback).
104
        """
105
        if not isinstance(exception, BaseException):
106
            raise TypeError("log_exception can only log derivatives of "
107
                            "BaseException.")
108
109
        traceback_str = "\n".join(
110
            traceback.format_exception(type(exception),
111
                                       exception,
112
                                       exception.__traceback__))
113
114
        self.log(log_level, message, timestamp=timestamp, **kwargs)
115
        self.log_message(
116
            LogMessage(LOG_LEVEL.DEBUG,
117
                       "Exception was:" + "\n" + traceback_str,
118
                       timestamp=timestamp),
119
            **kwargs)
120
121
    def log_message(self, log_message, **kwargs):
122
        if not isinstance(log_message, LogMessage):
123
            raise TypeError("log_message should be of type LogMessage.")
124
125
        if log_message.log_level < self.log_level:
126
            return
127
128
        self._print_log_message(
129
            self._get_log_prefix(log_message.log_level, log_message.timestamp),
130
            log_message,
131
            **kwargs)
132
133
    def _print_log_message(self, prefix, log_message, **kwargs):
134
        """
135
        Override this if you want to influence how the log message is printed.
136
137
        If the underlying printer is a ColorPrinter, then colored logging is
138
        used. You can turn it off in the underlying ColorPrinter if you want to
139
        print uncolored.
140
141
        :param prefix:      The prefix to print (as string).
142
        :param log_message: The LogMessage object to print.
143
        :param kwargs:      Any other keyword arguments.
144
        """
145
        if isinstance(self._printer, ColorPrinter):
146
            self.printer.print(prefix,
147
                               end=" ",
148
                               color=LOG_LEVEL_COLORS[log_message.log_level],
149
                               **kwargs)
150
            self.printer.print(log_message.message, **kwargs)
151
        else:
152
            self.printer.print(prefix, log_message.message, **kwargs)
153