2 # Copyright (C) 2010-2012 Vinay Sajip. All rights reserved. Licensed under the new BSD license.
4 from __future__ import print_function, unicode_literals
11 if platform.system() == 'Windows':
13 import ctypes.wintypes
15 # Reference: https://gist.github.com/vsajip/758430
16 # https://github.com/ipython/ipython/issues/4252
17 # https://msdn.microsoft.com/en-us/library/windows/desktop/ms686047%28v=vs.85%29.aspx
18 ctypes.windll.kernel32.SetConsoleTextAttribute.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.WORD]
19 ctypes.windll.kernel32.SetConsoleTextAttribute.restype = ctypes.wintypes.BOOL
22 class ColorizingStreamHandler(logging.StreamHandler):
23 # color names to indices
35 # levels to (background, foreground, bold/intense)
37 logging.DEBUG: (None, 'blue', False),
38 logging.INFO: (None, 'green', False),
39 logging.WARNING: (None, 'yellow', False),
40 logging.ERROR: (None, 'red', False),
41 logging.CRITICAL: ('red', 'white', False)
45 disable_coloring = False
49 isatty = getattr(self.stream, 'isatty', None)
50 return isatty and isatty() and not self.disable_coloring
52 def emit(self, record):
54 message = self.format(record)
58 if message and message[0] == "\r":
62 self.output_colorized(message)
63 stream.write(getattr(self, 'terminator', '\n'))
66 except (KeyboardInterrupt, SystemExit):
71 self.handleError(record)
74 if not platform.system() == 'Windows':
75 def output_colorized(self, message):
76 self.stream.write(message)
78 ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m')
91 def output_colorized(self, message):
92 parts = self.ansi_esc.split(message)
93 write = self.stream.write
95 fd = getattr(self.stream, 'fileno', None)
100 if fd in (1, 2): # stdout or stderr
101 h = ctypes.windll.kernel32.GetStdHandle(-10 - fd)
107 if sys.version_info < (3, 0, 0):
108 write(text.encode('utf-8'))
113 params = parts.pop(0)
116 params = [int(p) for p in params.split(';')]
121 color |= self.nt_color_map[p - 40] << 4
123 color |= self.nt_color_map[p - 30]
125 color |= 0x08 # foreground intensity on
126 elif p == 0: # reset to default color
129 pass # error condition ignored
131 ctypes.windll.kernel32.SetConsoleTextAttribute(h, color)
133 def colorize(self, message, record):
134 if record.levelno in self.level_map and self.is_tty:
135 bg, fg, bold = self.level_map[record.levelno]
138 if bg in self.color_map:
139 params.append(str(self.color_map[bg] + 40))
141 if fg in self.color_map:
142 params.append(str(self.color_map[fg] + 30))
147 if params and message:
148 if message.lstrip() != message:
149 prefix = re.search(r"\s+", message).group(0)
150 message = message[len(prefix):]
154 message = "%s%s" % (prefix, ''.join((self.csi, ';'.join(params),
155 'm', message, self.reset)))
159 def format(self, record):
160 message = logging.StreamHandler.format(self, record)
161 return self.colorize(message, record)
164 logging.addLevelName(15, "INFO")
165 logger = logging.getLogger('nhentai')
166 LOGGER_HANDLER = ColorizingStreamHandler(sys.stdout)
167 FORMATTER = logging.Formatter("\r[%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S")
168 LOGGER_HANDLER.setFormatter(FORMATTER)
169 LOGGER_HANDLER.level_map[logging.getLevelName("INFO")] = (None, "cyan", False)
170 logger.addHandler(LOGGER_HANDLER)
171 logger.setLevel(logging.DEBUG)
174 if __name__ == '__main__':
175 logger.log(15, 'nhentai')
178 logger.debug('debug')
179 logger.error('error')
180 logger.critical('critical')