Completed
Pull Request — master (#2409)
by
unknown
02:06
created

LogPrinter.__getstate__()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
dl 0
loc 5
rs 9.4285
c 1
b 0
f 0
1
import copy
2
import sys
3
import traceback
4
import logging
5
from colorama import Style
6
7
from pyprint.ColorPrinter import ColorPrinter
8
9
from coalib.output.printers.LOG_LEVEL import LOG_LEVEL, LOG_LEVEL_COLORS
10
from coalib.processes.communication.LogMessage import LogMessage
11
12
13
class PrinterHandler(logging.StreamHandler):
14
    """
15
    Handler for logging which writes messages into stdout.
16
    """
17
18
    def emit(self, record):
19
        msg = self.format(record)
20
        sys.stdout.write(msg + "\n")
21
22
23
class ColoredFormatter(logging.Formatter):
24
    """
25
    Formatter for logging which adds colors to the output by inserting special
26
    symbols where appropriate.
27
28
    Specifically, highlights levelname with respective colour.
29
    """
30
31
    def format(self, record, *args, **kwargs):
32
        # should not modify record itself, as it may be propagated to other
33
        # loggers
34
        new_record = copy.copy(record)
35
        if new_record.levelno in LOG_LEVEL_COLORS:
36
            color_begin = LOG_LEVEL_COLORS[new_record.levelno]
37
            color_end = Style.RESET_ALL
38
        else:
39
            color_begin = color_end = ''
40
        new_record.levelname = '{cb}[{levelname}]{ce}'.format(
41
            cb=color_begin,
42
            ce=color_end,
43
            levelname=new_record.levelname)
44
        return super().format(new_record, *args, **kwargs)
45
46
47
class LogPrinter:
48
    """
49
    This class is deprecated and will be soon removed. To get logger use
50
    loggin.getLogger('coala.colored') for colored logger and
51
    logging.getLogger('coala.raw') for not colored logger.
52
53
    The LogPrinter class allows to print log messages to an underlying Printer.
54
55
    This class is an adapter, means you can create a LogPrinter from every
56
    existing Printer instance.
57
    """
58
59
    def __init__(self,
60
                 printer=None,
61
                 log_level=LOG_LEVEL.INFO,
62
                 timestamp_format="%X"):
63
        """
64
        Creates a new log printer from an existing Printer.
65
66
        :param printer:          The underlying Printer where log messages
67
                                 shall be written to. If you inherit from
68
                                 LogPrinter, set it to self.
69
        :param log_level:        The minimum log level, everything below will
70
                                 not be logged.
71
        :param timestamp_format: The format string for the
72
                                 datetime.today().strftime(format) method.
73
        """
74
        if isinstance(printer, ColorPrinter):
75
            self.logger_name = 'coala.colored'
76
        else:
77
            self.logger_name = 'coala.raw'
78
        self.logger = logging.getLogger(self.logger_name)
79
80
        self._printer = printer
81
        self.log_level = log_level
82
        self.timestamp_format = timestamp_format
83
84
    @property
85
    def log_level(self):
86
        """
87
        Returns current log_level used is logger.
88
        """
89
        return self._log_level
90
91
    @log_level.setter
92
    def log_level(self, log_level):
93
        """
94
        Sets log_level for logger.
95
        """
96
        self._log_level = log_level
97
        self.logger.setLevel(log_level)
98
99
    @property
100
    def printer(self):
101
        """
102
        Returns the underlying printer where logs are printed to.
103
        """
104
        return self._printer
105
106
    def debug(self, *messages, delimiter=" ", timestamp=None, **kwargs):
107
        self.log_message(LogMessage(LOG_LEVEL.DEBUG,
108
                                    *messages,
109
                                    delimiter=delimiter,
110
                                    timestamp=timestamp),
111
                         **kwargs)
112
113
    def info(self, *messages, delimiter=" ", timestamp=None, **kwargs):
114
        self.log_message(LogMessage(LOG_LEVEL.INFO,
115
                                    *messages,
116
                                    delimiter=delimiter,
117
                                    timestamp=timestamp),
118
                         **kwargs)
119
120
    def warn(self, *messages, delimiter=" ", timestamp=None, **kwargs):
121
        self.log_message(LogMessage(LOG_LEVEL.WARNING,
122
                                    *messages,
123
                                    delimiter=delimiter,
124
                                    timestamp=timestamp),
125
                         **kwargs)
126
127
    def err(self, *messages, delimiter=" ", timestamp=None, **kwargs):
128
        self.log_message(LogMessage(LOG_LEVEL.ERROR,
129
                                    *messages,
130
                                    delimiter=delimiter,
131
                                    timestamp=timestamp),
132
                         **kwargs)
133
134
    def log(self, log_level, message, timestamp=None, **kwargs):
135
        self.log_message(LogMessage(log_level,
136
                                    message,
137
                                    timestamp=timestamp),
138
                         **kwargs)
139
140
    def log_exception(self,
141
                      message,
142
                      exception,
143
                      log_level=LOG_LEVEL.ERROR,
144
                      timestamp=None,
145
                      **kwargs):
146
        """
147
        If the log_level of the printer is greater than DEBUG, it prints
148
        only the message. If it is DEBUG or lower, it shows the message
149
        along with the traceback of the exception.
150
151
        :param message:   The message to print.
152
        :param exception: The exception to print.
153
        :param log_level: The log_level of this message (not used when
154
                          logging the traceback. Tracebacks always have
155
                          a level of DEBUG).
156
        :param timestamp: The time at which this log occured. Defaults to
157
                          the current time.
158
        :param kwargs:    Keyword arguments to be passed when logging the
159
                          message (not used when logging the traceback).
160
        """
161
        if not isinstance(exception, BaseException):
162
            raise TypeError("log_exception can only log derivatives of "
163
                            "BaseException.")
164
165
        traceback_str = "\n".join(
166
            traceback.format_exception(type(exception),
167
                                       exception,
168
                                       exception.__traceback__))
169
170
        self.log(log_level, message, timestamp=timestamp, **kwargs)
171
        self.log_message(
172
            LogMessage(LOG_LEVEL.DEBUG,
173
                       "Exception was:" + "\n" + traceback_str,
174
                       timestamp=timestamp),
175
            **kwargs)
176
177
    def log_message(self, log_message, **kwargs):
178
        if not isinstance(log_message, LogMessage):
179
            raise TypeError("log_message should be of type LogMessage.")
180
        self.logger.log(log_message.log_level, log_message.message)
181
182
    def __getstate__(self):
183
        # on Windows there are problems with serializing loggers, so omit it
184
        oldict = self.__dict__.copy()
185
        del oldict['logger']
186
        return oldict
187
188
    def __setstate__(self, newdict):
189
        self.__dict__.update(newdict)
190
        # restore logger by name
191
        self.logger = logging.getLogger(self.logger_name)
192