pycolib/coloredformatter.py
author Radek Brich <radek.brich@devl.cz>
Mon, 19 Aug 2013 16:32:33 +0200
changeset 10 51b7e98e1f41
parent 5 055f7dfb3e4f
permissions -rw-r--r--
Fix ColoredFormatted: Colored record could affect other formatters.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     1
import logging
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     2
from copy import copy
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     3
5
055f7dfb3e4f Refactor ansicolor, add demo.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
     4
from pycolib.ansicolor import highlight, BOLD, WHITE, YELLOW, RED
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     5
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     6
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     7
class ColoredFormatter(logging.Formatter):
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     8
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     9
    def __init__(self, fmt, datefmt):
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    10
        logging.Formatter.__init__(self, fmt, datefmt)
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    11
        self._colors = {
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    12
            'message': {
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    13
                'default': (None, None),
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    14
                'exception': (BOLD + YELLOW, RED),
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    15
                },
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    16
            'levelname': {
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    17
                'default': (BOLD + WHITE, None),
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    18
                'debug': (None, None),
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    19
                },
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    20
            'time': {
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    21
                'default': (BOLD + WHITE, None),
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    22
                'debug': (None, None),
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    23
                },
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    24
            }
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    25
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    26
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    27
    def formatTime(self, record, datefmt=None):
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    28
        """Override, add color as specified."""
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    29
        formatted = logging.Formatter.formatTime(self, record, datefmt)
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    30
        fg, bg = self.get_color('time', record)
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    31
        if fg or bg:
5
055f7dfb3e4f Refactor ansicolor, add demo.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
    32
            formatted = highlight(1, fg, bg) + formatted + highlight(0)
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    33
        return formatted
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    34
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    35
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    36
    def format(self, record):
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    37
        """Override, add color as specified."""
10
51b7e98e1f41 Fix ColoredFormatted: Colored record could affect other formatters.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    38
        # work on copy, do not alter original record, which is processed by other formatters too
51b7e98e1f41 Fix ColoredFormatted: Colored record could affect other formatters.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    39
        record = copy(record)
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    40
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    41
        ### message color
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    42
        fg, bg = self.get_color('message', record)
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    43
        if fg or bg:
5
055f7dfb3e4f Refactor ansicolor, add demo.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
    44
            record.msg = highlight(1, fg, bg) + record.msg + highlight(0)
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    45
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    46
        ### levelname color
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    47
        fg, bg = self.get_color('levelname', record)
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    48
        if fg or bg:
5
055f7dfb3e4f Refactor ansicolor, add demo.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
    49
            record.levelname = highlight(1, fg, bg) + record.levelname + highlight(0)
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    50
10
51b7e98e1f41 Fix ColoredFormatted: Colored record could affect other formatters.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    51
        return logging.Formatter.format(self, record)
2
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    52
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    53
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    54
    def set_color(self, fieldname, levelname, fg=None, bg=None):
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    55
        """Specify color for parts of log message.
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    56
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    57
        Args:
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    58
            fieldname: Which field to apply: 'message' | 'levelname' | 'time'
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    59
            levelname: Log level to apply, case insensitive: 'debug' | 'info' etc.
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    60
                Custom levels are supported too.
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    61
                Special name 'default' is used for unspecified levels.
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    62
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    63
        """
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    64
        self._colors[fieldname][levelname.lower()] = (fg, bg)
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    65
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    66
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    67
    def get_color(self, fieldname, record):
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    68
        """Get specified color for field levelname (from record)."""
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    69
        colormap = self._colors[fieldname]
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    70
        levelname = record.levelname.lower()
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    71
        fg, bg = colormap['default']
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    72
        if levelname in colormap:
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    73
            fg, bg = colormap[levelname]
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    74
        # exception is not real level, detect it using exc_info
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    75
        if record.levelno == logging.ERROR and record.exc_info is not None \
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    76
        and 'exception' in colormap:
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    77
            fg, bg = colormap['exception']
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    78
        return fg, bg
d3ffa15f5886 Add ColoredFormatter. Add setup.py.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    79