]> git.lizzy.rs Git - nhentai.git/blob - nhentai/logger.py
fix #197 set proxy to null
[nhentai.git] / nhentai / logger.py
1 #
2 # Copyright (C) 2010-2012 Vinay Sajip. All rights reserved. Licensed under the new BSD license.
3 #
4 import logging
5 import re
6 import platform
7 import sys
8
9
10 if platform.system() == 'Windows':
11     import ctypes
12     import ctypes.wintypes
13
14     # Reference: https://gist.github.com/vsajip/758430
15     #            https://github.com/ipython/ipython/issues/4252
16     #            https://msdn.microsoft.com/en-us/library/windows/desktop/ms686047%28v=vs.85%29.aspx
17     ctypes.windll.kernel32.SetConsoleTextAttribute.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.WORD]
18     ctypes.windll.kernel32.SetConsoleTextAttribute.restype = ctypes.wintypes.BOOL
19
20
21 class ColorizingStreamHandler(logging.StreamHandler):
22     # color names to indices
23     color_map = {
24         'black': 0,
25         'red': 1,
26         'green': 2,
27         'yellow': 3,
28         'blue': 4,
29         'magenta': 5,
30         'cyan': 6,
31         'white': 7,
32     }
33
34     # levels to (background, foreground, bold/intense)
35     level_map = {
36         logging.DEBUG: (None, 'blue', False),
37         logging.INFO: (None, 'green', False),
38         logging.WARNING: (None, 'yellow', False),
39         logging.ERROR: (None, 'red', False),
40         logging.CRITICAL: ('red', 'white', False)
41     }
42     csi = '\x1b['
43     reset = '\x1b[0m'
44     disable_coloring = False
45
46     @property
47     def is_tty(self):
48         isatty = getattr(self.stream, 'isatty', None)
49         return isatty and isatty() and not self.disable_coloring
50
51     def emit(self, record):
52         try:
53             message = self.format(record)
54             stream = self.stream
55
56             if not self.is_tty:
57                 if message and message[0] == "\r":
58                     message = message[1:]
59                 stream.write(message)
60             else:
61                 self.output_colorized(message)
62             stream.write(getattr(self, 'terminator', '\n'))
63
64             self.flush()
65         except (KeyboardInterrupt, SystemExit):
66             raise
67         except IOError:
68             pass
69         except:
70             self.handleError(record)
71
72
73     if not platform.system() == 'Windows':
74         def output_colorized(self, message):
75             self.stream.write(message)
76     else:
77         ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m')
78
79         nt_color_map = {
80             0: 0x00,    # black
81             1: 0x04,    # red
82             2: 0x02,    # green
83             3: 0x06,    # yellow
84             4: 0x01,    # blue
85             5: 0x05,    # magenta
86             6: 0x03,    # cyan
87             7: 0x07,    # white
88         }
89
90         def output_colorized(self, message):
91             parts = self.ansi_esc.split(message)
92             write = self.stream.write
93             h = None
94             fd = getattr(self.stream, 'fileno', None)
95
96             if fd is not None:
97                 fd = fd()
98
99                 if fd in (1, 2): # stdout or stderr
100                     h = ctypes.windll.kernel32.GetStdHandle(-10 - fd)
101
102             while parts:
103                 text = parts.pop(0)
104
105                 if text:
106                     if sys.version_info < (3, 0, 0):
107                         write(text.encode('utf-8'))
108                     else:
109                         write(text)
110
111                 if parts:
112                     params = parts.pop(0)
113
114                     if h is not None:
115                         params = [int(p) for p in params.split(';')]
116                         color = 0
117
118                         for p in params:
119                             if 40 <= p <= 47:
120                                 color |= self.nt_color_map[p - 40] << 4
121                             elif 30 <= p <= 37:
122                                 color |= self.nt_color_map[p - 30]
123                             elif p == 1:
124                                 color |= 0x08 # foreground intensity on
125                             elif p == 0: # reset to default color
126                                 color = 0x07
127                             else:
128                                 pass # error condition ignored
129
130                         ctypes.windll.kernel32.SetConsoleTextAttribute(h, color)
131
132     def colorize(self, message, record):
133         if record.levelno in self.level_map and self.is_tty:
134             bg, fg, bold = self.level_map[record.levelno]
135             params = []
136
137             if bg in self.color_map:
138                 params.append(str(self.color_map[bg] + 40))
139
140             if fg in self.color_map:
141                 params.append(str(self.color_map[fg] + 30))
142
143             if bold:
144                 params.append('1')
145
146             if params and message:
147                 if message.lstrip() != message:
148                     prefix = re.search(r"\s+", message).group(0)
149                     message = message[len(prefix):]
150                 else:
151                     prefix = ""
152
153                 message = "%s%s" % (prefix, ''.join((self.csi, ';'.join(params),
154                                     'm', message, self.reset)))
155
156         return message
157
158     def format(self, record):
159         message = logging.StreamHandler.format(self, record)
160         return self.colorize(message, record)
161
162
163 logging.addLevelName(15, "INFO")
164 logger = logging.getLogger('nhentai')
165 LOGGER_HANDLER = ColorizingStreamHandler(sys.stdout)
166 FORMATTER = logging.Formatter("\r[%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S")
167 LOGGER_HANDLER.setFormatter(FORMATTER)
168 LOGGER_HANDLER.level_map[logging.getLevelName("INFO")] = (None, "cyan", False)
169 logger.addHandler(LOGGER_HANDLER)
170 logger.setLevel(logging.DEBUG)
171
172
173 if __name__ == '__main__':
174     logger.log(15, 'nhentai')
175     logger.info('info')
176     logger.warn('warn')
177     logger.debug('debug')
178     logger.error('error')
179     logger.critical('critical')