_AnsiColorStreamHandler   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 29
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 8
c 0
b 0
f 0
dl 0
loc 29
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 2 1
B _get_color() 0 8 6
A format() 0 4 1
1
# Colored stream handler for python logging framework based on:
2
# http://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output/1336640#1336640
3
4
# Copyright (c) 2014 Markus Pointner
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a copy
7
# of this software and associated documentation files (the "Software"), to deal
8
# in the Software without restriction, including without limitation the rights
9
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
# copies of the Software, and to permit persons to whom the Software is
11
# furnished to do so, subject to the following conditions:
12
#
13
# The above copyright notice and this permission notice shall be included in
14
# all copies or substantial portions of the Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
# THE SOFTWARE.
23
24
import logging
25
26
class _AnsiColorStreamHandler(logging.StreamHandler):
27
    DEFAULT = '\x1b[0m'
28
    RED     = '\x1b[31m'
29
    GREEN   = '\x1b[32m'
30
    YELLOW  = '\x1b[33m'
31
    CYAN    = '\x1b[36m'
32
33
    CRITICAL = RED
34
    ERROR    = RED
35
    WARNING  = YELLOW
36
    INFO     = GREEN
37
    DEBUG    = CYAN
38
39
    @classmethod
40
    def _get_color(cls, level):
41
        if level >= logging.CRITICAL:  return cls.CRITICAL
42
        elif level >= logging.ERROR:   return cls.ERROR
43
        elif level >= logging.WARNING: return cls.WARNING
44
        elif level >= logging.INFO:    return cls.INFO
45
        elif level >= logging.DEBUG:   return cls.DEBUG
46
        else:                          return cls.DEFAULT
47
48
    def __init__(self, stream=None):
49
        logging.StreamHandler.__init__(self, stream)
50
51
    def format(self, record):
52
        text = logging.StreamHandler.format(self, record)
53
        color = self._get_color(record.levelno)
54
        return color + text + self.DEFAULT
55
56
class _WinColorStreamHandler(logging.StreamHandler):
57
    # wincon.h
58
    FOREGROUND_BLACK     = 0x0000
59
    FOREGROUND_BLUE      = 0x0001
60
    FOREGROUND_GREEN     = 0x0002
61
    FOREGROUND_CYAN      = 0x0003
62
    FOREGROUND_RED       = 0x0004
63
    FOREGROUND_MAGENTA   = 0x0005
64
    FOREGROUND_YELLOW    = 0x0006
65
    FOREGROUND_GREY      = 0x0007
66
    FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
67
    FOREGROUND_WHITE     = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
68
69
    BACKGROUND_BLACK     = 0x0000
70
    BACKGROUND_BLUE      = 0x0010
71
    BACKGROUND_GREEN     = 0x0020
72
    BACKGROUND_CYAN      = 0x0030
73
    BACKGROUND_RED       = 0x0040
74
    BACKGROUND_MAGENTA   = 0x0050
75
    BACKGROUND_YELLOW    = 0x0060
76
    BACKGROUND_GREY      = 0x0070
77
    BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
78
79
    DEFAULT  = FOREGROUND_WHITE
80
    CRITICAL = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
81
    ERROR    = FOREGROUND_RED | FOREGROUND_INTENSITY
82
    WARNING  = FOREGROUND_YELLOW | FOREGROUND_INTENSITY
83
    INFO     = FOREGROUND_GREEN
84
    DEBUG    = FOREGROUND_CYAN
85
86
    @classmethod
87
    def _get_color(cls, level):
88
        if level >= logging.CRITICAL:  return cls.CRITICAL
89
        elif level >= logging.ERROR:   return cls.ERROR
90
        elif level >= logging.WARNING: return cls.WARNING
91
        elif level >= logging.INFO:    return cls.INFO
92
        elif level >= logging.DEBUG:   return cls.DEBUG
93
        else:                          return cls.DEFAULT
94
95
    def _set_color(self, code):
96
        import ctypes
97
        ctypes.windll.kernel32.SetConsoleTextAttribute(self._outhdl, code)
98
99
    def __init__(self, stream=None):
100
        logging.StreamHandler.__init__(self, stream)
101
        # get file handle for the stream
102
        import ctypes, ctypes.util
103
        crtname = ctypes.util.find_msvcrt()
104
        crtlib = ctypes.cdll.LoadLibrary(crtname)
105
        self._outhdl = crtlib._get_osfhandle(stream.fileno())
106
107
    def emit(self, record):
108
        color = self._get_color(record.levelno)
109
        self._set_color(color)
110
        logging.StreamHandler.emit(self, record)
111
        self._set_color(self.FOREGROUND_WHITE)
112
113
# select ColorStreamHandler based on platform
114
import platform
115
if platform.system() == 'Windows':
116
    ColorStreamHandler = _WinColorStreamHandler
117
else:
118
    ColorStreamHandler = _AnsiColorStreamHandler