mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
sphinx.util.logging supports colorized log
This commit is contained in:
parent
7358512f11
commit
70d6a560f2
@ -15,11 +15,11 @@ import logging.handlers
|
||||
from contextlib import contextmanager
|
||||
from collections import defaultdict
|
||||
|
||||
from six import PY2, StringIO, string_types
|
||||
from six import PY2, StringIO
|
||||
from docutils.utils import get_source_line
|
||||
|
||||
from sphinx.errors import SphinxWarning
|
||||
from sphinx.util.console import darkred # type: ignore
|
||||
from sphinx.util.console import colorize
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -30,6 +30,7 @@ if False:
|
||||
|
||||
VERBOSE = 15
|
||||
DEBUG2 = 5
|
||||
|
||||
VERBOSITY_MAP = defaultdict(lambda: 0) # type: Dict[int, int]
|
||||
VERBOSITY_MAP.update({
|
||||
0: logging.INFO,
|
||||
@ -38,6 +39,13 @@ VERBOSITY_MAP.update({
|
||||
3: DEBUG2,
|
||||
})
|
||||
|
||||
COLOR_MAP = defaultdict(lambda text: text) # type: Dict[int, unicode]
|
||||
COLOR_MAP.update({
|
||||
logging.WARNING: 'darkred',
|
||||
logging.DEBUG: 'darkgray',
|
||||
DEBUG2: 'lightgray',
|
||||
})
|
||||
|
||||
|
||||
def getLogger(name):
|
||||
# type: (str) -> SphinxLoggerAdapter
|
||||
@ -52,15 +60,12 @@ class SphinxWarningLogRecord(logging.LogRecord):
|
||||
def getMessage(self):
|
||||
# type: () -> str
|
||||
message = super(SphinxWarningLogRecord, self).getMessage()
|
||||
if isinstance(message, string_types):
|
||||
location = getattr(self, 'location', None)
|
||||
if location:
|
||||
message = '%s: WARNING: %s' % (location, message)
|
||||
elif 'WARNING:' not in message:
|
||||
message = 'WARNING: %s' % message
|
||||
|
||||
return darkred(message)
|
||||
else:
|
||||
return message
|
||||
|
||||
|
||||
@ -103,6 +108,8 @@ class SphinxLoggerAdapter(logging.LoggerAdapter):
|
||||
extra['location'] = kwargs.pop('location')
|
||||
if 'nonl' in kwargs:
|
||||
extra['nonl'] = kwargs.pop('nonl')
|
||||
if 'color' in kwargs:
|
||||
extra['color'] = kwargs.pop('color')
|
||||
|
||||
return msg, kwargs
|
||||
|
||||
@ -293,6 +300,19 @@ class WarningLogRecordTranslator(logging.Filter):
|
||||
return True
|
||||
|
||||
|
||||
class ColorizeFormatter(logging.Formatter):
|
||||
def format(self, record):
|
||||
message = super(ColorizeFormatter, self).format(record)
|
||||
color = getattr(record, 'color', None)
|
||||
if color is None:
|
||||
color = COLOR_MAP.get(record.levelno)
|
||||
|
||||
if color:
|
||||
return colorize(color, message)
|
||||
else:
|
||||
return message
|
||||
|
||||
|
||||
def setup(app, status, warning):
|
||||
# type: (Sphinx, IO, IO) -> None
|
||||
"""Setup root logger for Sphinx"""
|
||||
@ -306,11 +326,13 @@ def setup(app, status, warning):
|
||||
info_handler = NewLineStreamHandler(status)
|
||||
info_handler.addFilter(InfoFilter())
|
||||
info_handler.setLevel(VERBOSITY_MAP.get(app.verbosity))
|
||||
info_handler.setFormatter(ColorizeFormatter())
|
||||
|
||||
warning_handler = logging.StreamHandler(warning)
|
||||
warning_handler.addFilter(WarningSuppressor(app))
|
||||
warning_handler.addFilter(WarningIsErrorFilter(app))
|
||||
warning_handler.addFilter(WarningLogRecordTranslator(app))
|
||||
warning_handler.setLevel(logging.WARNING)
|
||||
warning_handler.setFormatter(ColorizeFormatter())
|
||||
logger.addHandler(info_handler)
|
||||
logger.addHandler(warning_handler)
|
||||
|
@ -14,6 +14,7 @@ from docutils import nodes
|
||||
|
||||
from sphinx.errors import SphinxWarning
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.console import colorize
|
||||
from sphinx.util.logging import is_suppressed_warning
|
||||
|
||||
from util import with_app, raises, strip_escseq
|
||||
@ -238,3 +239,33 @@ def test_pending_logging(app, status, warning):
|
||||
|
||||
# actually logged as ordered
|
||||
assert 'WARNING: message2\nWARNING: message3' in strip_escseq(warning.getvalue())
|
||||
|
||||
|
||||
@with_app()
|
||||
def test_colored_logs(app, status, warning):
|
||||
app.verbosity = 3
|
||||
logging.setup(app, status, warning)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# default colors
|
||||
logger.debug2('message1')
|
||||
logger.debug('message2')
|
||||
logger.verbose('message3')
|
||||
logger.info('message4')
|
||||
logger.warning('message5')
|
||||
logger.critical('message6')
|
||||
logger.error('message7')
|
||||
|
||||
assert colorize('lightgray', 'message1') in status.getvalue()
|
||||
assert colorize('darkgray', 'message2') in status.getvalue()
|
||||
assert 'message3\n' in status.getvalue() # not colored
|
||||
assert 'message4\n' in status.getvalue() # not colored
|
||||
assert colorize('darkred', 'WARNING: message5') in warning.getvalue()
|
||||
assert 'WARNING: message6\n' in warning.getvalue() # not colored
|
||||
assert 'WARNING: message7\n' in warning.getvalue() # not colored
|
||||
|
||||
# color specification
|
||||
logger.debug('message8', color='white')
|
||||
logger.info('message9', color='red')
|
||||
assert colorize('white', 'message8') in status.getvalue()
|
||||
assert colorize('red', 'message9') in status.getvalue()
|
||||
|
Loading…
Reference in New Issue
Block a user