2 # Copyright (C) 2010-2012 Vinay Sajip. All rights reserved. Licensed under the new BSD license.
10 if platform.system() == 'Windows':
12 import ctypes.wintypes
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
21 class ColorizingStreamHandler(logging.StreamHandler):
22 # color names to indices
34 # levels to (background, foreground, bold/intense)
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)
44 disable_coloring = False
48 isatty = getattr(self.stream, 'isatty', None)
49 return isatty and isatty() and not self.disable_coloring
51 def emit(self, record):
53 message = self.format(record)
57 if message and message[0] == "\r":
61 self.output_colorized(message)
62 stream.write(getattr(self, 'terminator', '\n'))
65 except (KeyboardInterrupt, SystemExit):
70 self.handleError(record)
73 if not platform.system() == 'Windows':
74 def output_colorized(self, message):
75 self.stream.write(message)
77 ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m')
90 def output_colorized(self, message):
91 parts = self.ansi_esc.split(message)
92 write = self.stream.write
94 fd = getattr(self.stream, 'fileno', None)
99 if fd in (1, 2): # stdout or stderr
100 h = ctypes.windll.kernel32.GetStdHandle(-10 - fd)
106 if sys.version_info < (3, 0, 0):
107 write(text.encode('utf-8'))
112 params = parts.pop(0)
115 params = [int(p) for p in params.split(';')]
120 color |= self.nt_color_map[p - 40] << 4
122 color |= self.nt_color_map[p - 30]
124 color |= 0x08 # foreground intensity on
125 elif p == 0: # reset to default color
128 pass # error condition ignored
130 ctypes.windll.kernel32.SetConsoleTextAttribute(h, color)
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]
137 if bg in self.color_map:
138 params.append(str(self.color_map[bg] + 40))
140 if fg in self.color_map:
141 params.append(str(self.color_map[fg] + 30))
146 if params and message:
147 if message.lstrip() != message:
148 prefix = re.search(r"\s+", message).group(0)
149 message = message[len(prefix):]
153 message = "%s%s" % (prefix, ''.join((self.csi, ';'.join(params),
154 'm', message, self.reset)))
158 def format(self, record):
159 message = logging.StreamHandler.format(self, record)
160 return self.colorize(message, record)
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)
173 if __name__ == '__main__':
174 logger.log(15, 'nhentai')
176 logger.warning('warning')
177 logger.debug('debug')
178 logger.error('error')
179 logger.critical('critical')