# HG changeset patch # User Radek Brich # Date 1365099874 -7200 # Node ID d3ffa15f58862b202b6ede8e32878bfebc42ea36 # Parent ee31f1bf17c1efd1b08add1bd6525814096651f0 Add ColoredFormatter. Add setup.py. diff -r ee31f1bf17c1 -r d3ffa15f5886 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Apr 04 20:24:34 2013 +0200 @@ -0,0 +1,4 @@ +__pycache__ +^\.(pydev)?project$ +^\.settings$ +^build/ diff -r ee31f1bf17c1 -r d3ffa15f5886 README --- a/README Wed Apr 03 20:37:05 2013 +0200 +++ b/README Thu Apr 04 20:24:34 2013 +0200 @@ -4,6 +4,7 @@ Pycolib is library of small, mostly one-file, modules with little or not (inter)dependencies. * ansicolor - change color of text in terminal using ANSI escape sequences + * coloredformatter - logging.Formatter which adds ANSI colors to output * makeurl - adjust string for using in URL by replacing symbols and combined unicode chars * prettysize - print file sizes in human readable form * soap - minimal SOAP client diff -r ee31f1bf17c1 -r d3ffa15f5886 demo/demo_coloredformatter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/demo_coloredformatter.py Thu Apr 04 20:24:34 2013 +0200 @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +from pycolib.coloredformatter import ColoredFormatter + +import logging + + +def prepare_logger(name, level=logging.DEBUG): + logger = logging.getLogger(name) + logger.setLevel(level) + return logger + + +def prepare_console_handler(level=logging.DEBUG): + handler = logging.StreamHandler() + formatter = ColoredFormatter('%(asctime)s %(levelname)-5s %(message)s', '%H:%M:%S') + formatter.set_color('message', 'RECV', 2) + formatter.set_color('message', 'SEND', 6) + handler.setFormatter(formatter) + handler.setLevel(level) + return handler + + +def setup(): + logging.addLevelName(21, 'RECV') + logging.addLevelName(22, 'SEND') + + logger_main = prepare_logger('main') + + handler_console = prepare_console_handler() + logger_main.addHandler(handler_console) + + +def finish(): + logging.shutdown() + + +def main(): + setup() + log = logging.getLogger('main') + + log.info('test') + + try: + raise Exception('test exception') + except: + log.exception('test exc') + + log.log(21, 'recv') + log.log(22, 'send') + + log.debug('debug') + + finish() + + +if __name__ == '__main__': + main() + diff -r ee31f1bf17c1 -r d3ffa15f5886 pycolib/__init__.py diff -r ee31f1bf17c1 -r d3ffa15f5886 pycolib/ansicolor.py --- a/pycolib/ansicolor.py Wed Apr 03 20:37:05 2013 +0200 +++ b/pycolib/ansicolor.py Thu Apr 04 20:24:34 2013 +0200 @@ -9,9 +9,9 @@ def color(enable, fg=None, bg=None): ''' - color(1) -- switch to bold - color(1,1) -- red foreground - color(1,3,4) -- red on blue + color(1) -- switch to bold, keep previous color + color(1, RED) -- red foreground + color(1, BOLD + YELLOW, BLUE) -- yellow on blue, bold color(0) -- reset ''' @@ -42,7 +42,7 @@ else: return "\033[0m" -def setcolor(enable, fg=None, bg=None): +def set_color(enable, fg=None, bg=None): print(color(enable, fg, bg), end='') diff -r ee31f1bf17c1 -r d3ffa15f5886 pycolib/coloredformatter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pycolib/coloredformatter.py Thu Apr 04 20:24:34 2013 +0200 @@ -0,0 +1,81 @@ +import logging +from copy import copy + +from pycolib.ansicolor import color, BOLD, WHITE, YELLOW, RED + + +class ColoredFormatter(logging.Formatter): + + def __init__(self, fmt, datefmt): + logging.Formatter.__init__(self, fmt, datefmt) + self._colors = { + 'message': { + 'default': (None, None), + 'exception': (BOLD + YELLOW, RED), + }, + 'levelname': { + 'default': (BOLD + WHITE, None), + 'debug': (None, None), + }, + 'time': { + 'default': (BOLD + WHITE, None), + 'debug': (None, None), + }, + } + + + def formatTime(self, record, datefmt=None): + """Override, add color as specified.""" + formatted = logging.Formatter.formatTime(self, record, datefmt) + fg, bg = self.get_color('time', record) + if fg or bg: + formatted = color(1, fg, bg) + formatted + color(0) + return formatted + + + def format(self, record): + """Override, add color as specified.""" + original_record = copy(record) + + ### message color + fg, bg = self.get_color('message', record) + if fg or bg: + record.msg = color(1, fg, bg) + record.msg + color(0) + + ### levelname color + fg, bg = self.get_color('levelname', record) + if fg or bg: + record.levelname = color(1, fg, bg) + record.levelname + color(0) + + res = logging.Formatter.format(self, record) + + record = original_record + return res + + + def set_color(self, fieldname, levelname, fg=None, bg=None): + """Specify color for parts of log message. + + Args: + fieldname: Which field to apply: 'message' | 'levelname' | 'time' + levelname: Log level to apply, case insensitive: 'debug' | 'info' etc. + Custom levels are supported too. + Special name 'default' is used for unspecified levels. + + """ + self._colors[fieldname][levelname.lower()] = (fg, bg) + + + def get_color(self, fieldname, record): + """Get specified color for field levelname (from record).""" + colormap = self._colors[fieldname] + levelname = record.levelname.lower() + fg, bg = colormap['default'] + if levelname in colormap: + fg, bg = colormap[levelname] + # exception is not real level, detect it using exc_info + if record.levelno == logging.ERROR and record.exc_info is not None \ + and 'exception' in colormap: + fg, bg = colormap['exception'] + return fg, bg + diff -r ee31f1bf17c1 -r d3ffa15f5886 setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Thu Apr 04 20:24:34 2013 +0200 @@ -0,0 +1,14 @@ +#!/usr/bin/env python3.2 + +from distutils.core import setup + +setup( + name='pycolib', + version='0.0.1', + description='Library of small auxiliary modules', + author='Radek Brich', + author_email='radek.brich@devl.cz', + url='http://hg.devl.cz/pycolib', + packages=['pycolib'], + ) +