summaryrefslogtreecommitdiff
path: root/gnupg/_ansistrm.py
diff options
context:
space:
mode:
Diffstat (limited to 'gnupg/_ansistrm.py')
-rw-r--r--gnupg/_ansistrm.py172
1 files changed, 172 insertions, 0 deletions
diff --git a/gnupg/_ansistrm.py b/gnupg/_ansistrm.py
new file mode 100644
index 0000000..cfd50a1
--- /dev/null
+++ b/gnupg/_ansistrm.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of python-gnupg, a Python wrapper aroung GnuPG, and it was
+# taken from https://gist.github.com/vsajip/758430 on the 14th of May, 2013. It
+# has also been included in the 'logutils' Python module, see
+# https://code.google.com/p/logutils/ .
+#
+# The original copyright and license text are as follows:
+# |
+# | Copyright (C) 2010-2012 Vinay Sajip. All rights reserved.
+# | Licensed under the new BSD license.
+# |
+#
+# This file is part of python-gnupg, a Python interface to GnuPG.
+# Copyright © 2013 Isis Lovecruft, <isis@leap.se> 0xA3ADB67A2CDB8B35
+# © 2013 Andrej B.
+# © 2013 LEAP Encryption Access Project
+# © 2008-2012 Vinay Sajip
+# © 2005 Steve Traugott
+# © 2004 A.M. Kuchling
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the included LICENSE file for details.
+
+import ctypes
+import logging
+import os
+
+class ColorizingStreamHandler(logging.StreamHandler):
+ # color names to indices
+ color_map = {
+ 'black': 0,
+ 'red': 1,
+ 'green': 2,
+ 'yellow': 3,
+ 'blue': 4,
+ 'magenta': 5,
+ 'cyan': 6,
+ 'white': 7,
+ }
+
+ #levels to (background, foreground, bold/intense)
+ if os.name == 'nt':
+ level_map = {
+ logging.DEBUG: (None, 'blue', True),
+ logging.INFO: (None, 'green', False),
+ logging.WARNING: (None, 'yellow', True),
+ logging.ERROR: (None, 'red', True),
+ logging.CRITICAL: ('red', 'white', True),
+ }
+ else:
+ level_map = {
+ logging.DEBUG: (None, 'blue', False),
+ logging.INFO: (None, 'green', False),
+ logging.WARNING: (None, 'yellow', False),
+ logging.ERROR: (None, 'red', False),
+ logging.CRITICAL: ('red', 'white', True),
+ }
+ csi = '\x1b['
+ reset = '\x1b[0m'
+
+ @property
+ def is_tty(self):
+ isatty = getattr(self.stream, 'isatty', None)
+ return isatty and isatty()
+
+ def emit(self, record):
+ try:
+ message = self.format(record)
+ stream = self.stream
+ if not self.is_tty:
+ stream.write(message)
+ else:
+ self.output_colorized(message)
+ stream.write(getattr(self, 'terminator', '\n'))
+ self.flush()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except:
+ self.handleError(record)
+
+ if os.name != 'nt':
+ def output_colorized(self, message):
+ self.stream.write(message)
+ else:
+ import re
+ ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m')
+
+ nt_color_map = {
+ 0: 0x00, # black
+ 1: 0x04, # red
+ 2: 0x02, # green
+ 3: 0x06, # yellow
+ 4: 0x01, # blue
+ 5: 0x05, # magenta
+ 6: 0x03, # cyan
+ 7: 0x07, # white
+ }
+
+ def output_colorized(self, message):
+ parts = self.ansi_esc.split(message)
+ write = self.stream.write
+ h = None
+ fd = getattr(self.stream, 'fileno', None)
+ if fd is not None:
+ fd = fd()
+ if fd in (1, 2): # stdout or stderr
+ h = ctypes.windll.kernel32.GetStdHandle(-10 - fd)
+ while parts:
+ text = parts.pop(0)
+ if text:
+ write(text)
+ if parts:
+ params = parts.pop(0)
+ if h is not None:
+ params = [int(p) for p in params.split(';')]
+ color = 0
+ for p in params:
+ if 40 <= p <= 47:
+ color |= self.nt_color_map[p - 40] << 4
+ elif 30 <= p <= 37:
+ color |= self.nt_color_map[p - 30]
+ elif p == 1:
+ color |= 0x08 # foreground intensity on
+ elif p == 0: # reset to default color
+ color = 0x07
+ else:
+ pass # error condition ignored
+ ctypes.windll.kernel32.SetConsoleTextAttribute(h, color)
+
+ def colorize(self, message, record):
+ if record.levelno in self.level_map:
+ bg, fg, bold = self.level_map[record.levelno]
+ params = []
+ if bg in self.color_map:
+ params.append(str(self.color_map[bg] + 40))
+ if fg in self.color_map:
+ params.append(str(self.color_map[fg] + 30))
+ if bold:
+ params.append('1')
+ if params:
+ message = ''.join((self.csi, ';'.join(params),
+ 'm', message, self.reset))
+ return message
+
+ def format(self, record):
+ message = logging.StreamHandler.format(self, record)
+ if self.is_tty:
+ # Don't colorize any traceback
+ parts = message.split('\n', 1)
+ parts[0] = self.colorize(parts[0], record)
+ message = '\n'.join(parts)
+ return message
+
+def main():
+ root = logging.getLogger()
+ root.setLevel(logging.DEBUG)
+ root.addHandler(ColorizingStreamHandler())
+ logging.debug('DEBUG')
+ logging.info('INFO')
+ logging.warning('WARNING')
+ logging.error('ERROR')
+ logging.critical('CRITICAL')
+
+if __name__ == '__main__':
+ main()