/usr/lib/python3/dist-packages/colorlog/colorlog.py is in python3-colorlog 3.1.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | """The ColoredFormatter class."""
from __future__ import absolute_import
import logging
import sys
from colorlog.escape_codes import escape_codes, parse_colors
__all__ = ('escape_codes', 'default_log_colors', 'ColoredFormatter',
'LevelFormatter', 'TTYColoredFormatter')
# The default colors to use for the debug levels
default_log_colors = {
'DEBUG': 'white',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'bold_red',
}
# The default format to use for each style
default_formats = {
'%': '%(log_color)s%(levelname)s:%(name)s:%(message)s',
'{': '{log_color}{levelname}:{name}:{message}',
'$': '${log_color}${levelname}:${name}:${message}'
}
class ColoredRecord(object):
"""
Wraps a LogRecord, adding named escape codes to the internal dict.
The internal dict is used when formatting the message (by the PercentStyle,
StrFormatStyle, and StringTemplateStyle classes).
"""
def __init__(self, record):
"""Add attributes from the escape_codes dict and the record."""
self.__dict__.update(escape_codes)
self.__dict__.update(record.__dict__)
# Keep a reference to the original record so ``__getattr__`` can
# access functions that are not in ``__dict__``
self.__record = record
def __getattr__(self, name):
return getattr(self.__record, name)
class ColoredFormatter(logging.Formatter):
"""
A formatter that allows colors to be placed in the format string.
Intended to help in creating more readable logging output.
"""
def __init__(self, fmt=None, datefmt=None, style='%',
log_colors=None, reset=True,
secondary_log_colors=None):
"""
Set the format and colors the ColoredFormatter will use.
The ``fmt``, ``datefmt`` and ``style`` args are passed on to the
``logging.Formatter`` constructor.
The ``secondary_log_colors`` argument can be used to create additional
``log_color`` attributes. Each key in the dictionary will set
``{key}_log_color``, using the value to select from a different
``log_colors`` set.
:Parameters:
- fmt (str): The format string to use
- datefmt (str): A format string for the date
- log_colors (dict):
A mapping of log level names to color names
- reset (bool):
Implicitly append a color reset to all records unless False
- style ('%' or '{' or '$'):
The format style to use. (*No meaning prior to Python 3.2.*)
- secondary_log_colors (dict):
Map secondary ``log_color`` attributes. (*New in version 2.6.*)
"""
if fmt is None:
if sys.version_info > (3, 2):
fmt = default_formats[style]
else:
fmt = default_formats['%']
if sys.version_info > (3, 2):
super(ColoredFormatter, self).__init__(fmt, datefmt, style)
elif sys.version_info > (2, 7):
super(ColoredFormatter, self).__init__(fmt, datefmt)
else:
logging.Formatter.__init__(self, fmt, datefmt)
self.log_colors = (
log_colors if log_colors is not None else default_log_colors)
self.secondary_log_colors = secondary_log_colors
self.reset = reset
def color(self, log_colors, level_name):
"""Return escape codes from a ``log_colors`` dict."""
return parse_colors(log_colors.get(level_name, ""))
def format(self, record):
"""Format a message from a record object."""
record = ColoredRecord(record)
record.log_color = self.color(self.log_colors, record.levelname)
# Set secondary log colors
if self.secondary_log_colors:
for name, log_colors in self.secondary_log_colors.items():
color = self.color(log_colors, record.levelname)
setattr(record, name + '_log_color', color)
# Format the message
if sys.version_info > (2, 7):
message = super(ColoredFormatter, self).format(record)
else:
message = logging.Formatter.format(self, record)
# Add a reset code to the end of the message
# (if it wasn't explicitly added in format str)
if self.reset and not message.endswith(escape_codes['reset']):
message += escape_codes['reset']
return message
class LevelFormatter(ColoredFormatter):
"""An extension of ColoredFormatter that uses per-level format strings."""
def __init__(self, fmt=None, datefmt=None, style='%',
log_colors=None, reset=True,
secondary_log_colors=None):
"""
Set the per-loglevel format that will be used.
Supports fmt as a dict. All other args are passed on to the
``colorlog.ColoredFormatter`` constructor.
:Parameters:
- fmt (dict):
A mapping of log levels (represented as strings, e.g. 'WARNING') to
different formatters. (*New in version 2.7.0)
(All other parameters are the same as in colorlog.ColoredFormatter)
Example:
formatter = colorlog.LevelFormatter(fmt={
'DEBUG':'%(log_color)s%(msg)s (%(module)s:%(lineno)d)',
'INFO': '%(log_color)s%(msg)s',
'WARNING': '%(log_color)sWARN: %(msg)s (%(module)s:%(lineno)d)',
'ERROR': '%(log_color)sERROR: %(msg)s (%(module)s:%(lineno)d)',
'CRITICAL': '%(log_color)sCRIT: %(msg)s (%(module)s:%(lineno)d)',
})
"""
if sys.version_info > (2, 7):
super(LevelFormatter, self).__init__(
fmt=fmt, datefmt=datefmt, style=style, log_colors=log_colors,
reset=reset, secondary_log_colors=secondary_log_colors)
else:
ColoredFormatter.__init__(
self, fmt=fmt, datefmt=datefmt, style=style,
log_colors=log_colors, reset=reset,
secondary_log_colors=secondary_log_colors)
self.style = style
self.fmt = fmt
def format(self, record):
"""Customize the message format based on the log level."""
if isinstance(self.fmt, dict):
self._fmt = self.fmt[record.levelname]
if sys.version_info > (3, 2):
# Update self._style because we've changed self._fmt
# (code based on stdlib's logging.Formatter.__init__())
if self.style not in logging._STYLES:
raise ValueError('Style must be one of: %s' % ','.join(
logging._STYLES.keys()))
self._style = logging._STYLES[self.style][0](self._fmt)
if sys.version_info > (2, 7):
message = super(LevelFormatter, self).format(record)
else:
message = ColoredFormatter.format(self, record)
return message
class TTYColoredFormatter(ColoredFormatter):
"""
Blanks all color codes if not running under a TTY.
This is useful when you want to be able to pipe colorlog output to a file.
"""
def __init__(self, *args, **kwargs):
"""Overwrite the `reset` argument to False if stream is not a TTY."""
self.stream = kwargs.pop('stream', sys.stdout)
# Both `reset` and `isatty` must be true to insert reset codes.
kwargs['reset'] = kwargs.get('reset', True) and self.stream.isatty()
ColoredFormatter.__init__(self, *args, **kwargs)
def color(self, log_colors, level_name):
"""Only returns colors if STDOUT is a TTY."""
if not self.stream.isatty():
log_colors = {}
return ColoredFormatter.color(self, log_colors, level_name)
|