summaryrefslogtreecommitdiff
path: root/sphinx/util/logging.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/logging.py')
-rw-r--r--sphinx/util/logging.py144
1 files changed, 88 insertions, 56 deletions
diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py
index 09cef4b48..6e661400f 100644
--- a/sphinx/util/logging.py
+++ b/sphinx/util/logging.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
sphinx.util.logging
~~~~~~~~~~~~~~~~~~~
@@ -8,7 +7,6 @@
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-from __future__ import absolute_import
import logging
import logging.handlers
@@ -17,7 +15,6 @@ from contextlib import contextmanager
from docutils import nodes
from docutils.utils import get_source_line
-from six import PY2, StringIO
from sphinx.errors import SphinxWarning
from sphinx.util.console import colorize
@@ -50,12 +47,12 @@ VERBOSITY_MAP.update({
2: logging.DEBUG,
})
-COLOR_MAP = defaultdict(lambda: 'blue') # type: Dict[int, unicode]
-COLOR_MAP.update({
- logging.ERROR: 'darkred',
- logging.WARNING: 'red',
- logging.DEBUG: 'darkgray',
-})
+COLOR_MAP = defaultdict(lambda: 'blue',
+ {
+ logging.ERROR: 'darkred',
+ logging.WARNING: 'red',
+ logging.DEBUG: 'darkgray'
+ })
def getLogger(name):
@@ -101,7 +98,7 @@ class SphinxLogRecord(logging.LogRecord):
def getMessage(self):
# type: () -> str
- message = super(SphinxLogRecord, self).getMessage()
+ message = super().getMessage()
location = getattr(self, 'location', None)
if location:
message = '%s: %s%s' % (location, self.prefix, message)
@@ -125,19 +122,19 @@ class SphinxLoggerAdapter(logging.LoggerAdapter):
"""LoggerAdapter allowing ``type`` and ``subtype`` keywords."""
def log(self, level, msg, *args, **kwargs): # type: ignore
- # type: (Union[int, str], unicode, Any, Any) -> None
+ # type: (Union[int, str], str, Any, Any) -> None
if isinstance(level, int):
- super(SphinxLoggerAdapter, self).log(level, msg, *args, **kwargs)
+ super().log(level, msg, *args, **kwargs)
else:
levelno = LEVEL_NAMES[level]
- super(SphinxLoggerAdapter, self).log(levelno, msg, *args, **kwargs)
+ super().log(levelno, msg, *args, **kwargs)
def verbose(self, msg, *args, **kwargs):
- # type: (unicode, Any, Any) -> None
+ # type: (str, Any, Any) -> None
self.log(VERBOSE, msg, *args, **kwargs)
def process(self, msg, kwargs): # type: ignore
- # type: (unicode, Dict) -> Tuple[unicode, Dict]
+ # type: (str, Dict) -> Tuple[str, Dict]
extra = kwargs.setdefault('extra', {})
if 'type' in kwargs:
extra['type'] = kwargs.pop('type')
@@ -162,28 +159,7 @@ class WarningStreamHandler(logging.StreamHandler):
pass
-class NewLineStreamHandlerPY2(logging.StreamHandler):
- """StreamHandler which switches line terminator by record.nonl flag."""
-
- def emit(self, record):
- # type: (logging.LogRecord) -> None
- try:
- self.acquire()
- stream = self.stream
- if getattr(record, 'nonl', False):
- # remove return code forcely when nonl=True
- self.stream = StringIO()
- super(NewLineStreamHandlerPY2, self).emit(record)
- stream.write(self.stream.getvalue()[:-1])
- stream.flush()
- else:
- super(NewLineStreamHandlerPY2, self).emit(record)
- finally:
- self.stream = stream
- self.release()
-
-
-class NewLineStreamHandlerPY3(logging.StreamHandler):
+class NewLineStreamHandler(logging.StreamHandler):
"""StreamHandler which switches line terminator by record.nonl flag."""
def emit(self, record):
@@ -193,24 +169,18 @@ class NewLineStreamHandlerPY3(logging.StreamHandler):
if getattr(record, 'nonl', False):
# skip appending terminator when nonl=True
self.terminator = ''
- super(NewLineStreamHandlerPY3, self).emit(record)
+ super().emit(record)
finally:
self.terminator = '\n'
self.release()
-if PY2:
- NewLineStreamHandler = NewLineStreamHandlerPY2
-else:
- NewLineStreamHandler = NewLineStreamHandlerPY3
-
-
class MemoryHandler(logging.handlers.BufferingHandler):
"""Handler buffering all logs."""
def __init__(self):
# type: () -> None
- super(MemoryHandler, self).__init__(-1)
+ super().__init__(-1)
def shouldFlush(self, record):
# type: (logging.LogRecord) -> bool
@@ -315,7 +285,54 @@ def skip_warningiserror(skip=True):
handler.removeFilter(disabler)
-class LogCollector(object):
+@contextmanager
+def prefixed_warnings(prefix):
+ # type: (str) -> Generator
+ """Prepend prefix to all records for a while.
+
+ For example::
+
+ >>> with prefixed_warnings("prefix:"):
+ >>> logger.warning('Warning message!') # => prefix: Warning message!
+
+ .. versionadded:: 2.0
+ """
+ logger = logging.getLogger(NAMESPACE)
+ warning_handler = None
+ for handler in logger.handlers:
+ if isinstance(handler, WarningStreamHandler):
+ warning_handler = handler
+ break
+ else:
+ # warning stream not found
+ yield
+ return
+
+ prefix_filter = None
+ for _filter in warning_handler.filters:
+ if isinstance(_filter, MessagePrefixFilter):
+ prefix_filter = _filter
+ break
+
+ if prefix_filter:
+ # already prefixed
+ try:
+ previous = prefix_filter.prefix
+ prefix_filter.prefix = prefix
+ yield
+ finally:
+ prefix_filter.prefix = previous
+ else:
+ # not prefixed yet
+ try:
+ prefix_filter = MessagePrefixFilter(prefix)
+ warning_handler.addFilter(prefix_filter)
+ yield
+ finally:
+ warning_handler.removeFilter(prefix_filter)
+
+
+class LogCollector:
def __init__(self):
# type: () -> None
self.logs = [] # type: List[logging.LogRecord]
@@ -341,7 +358,7 @@ class InfoFilter(logging.Filter):
def is_suppressed_warning(type, subtype, suppress_warnings):
- # type: (unicode, unicode, List[unicode]) -> bool
+ # type: (str, str, List[str]) -> bool
"""Check the warning is suppressed or not."""
if type is None:
return False
@@ -366,7 +383,7 @@ class WarningSuppressor(logging.Filter):
def __init__(self, app):
# type: (Sphinx) -> None
self.app = app
- super(WarningSuppressor, self).__init__()
+ super().__init__()
def filter(self, record):
# type: (logging.LogRecord) -> bool
@@ -392,7 +409,7 @@ class WarningIsErrorFilter(logging.Filter):
def __init__(self, app):
# type: (Sphinx) -> None
self.app = app
- super(WarningIsErrorFilter, self).__init__()
+ super().__init__()
def filter(self, record):
# type: (logging.LogRecord) -> bool
@@ -423,6 +440,21 @@ class DisableWarningIsErrorFilter(logging.Filter):
return True
+class MessagePrefixFilter(logging.Filter):
+ """Prepend prefix to all records."""
+
+ def __init__(self, prefix):
+ # type: (str) -> None
+ self.prefix = prefix
+ super().__init__()
+
+ def filter(self, record):
+ # type: (logging.LogRecord) -> bool
+ if self.prefix:
+ record.msg = self.prefix + ' ' + record.msg
+ return True
+
+
class SphinxLogRecordTranslator(logging.Filter):
"""Converts a log record to one Sphinx expects
@@ -434,7 +466,7 @@ class SphinxLogRecordTranslator(logging.Filter):
def __init__(self, app):
# type: (Sphinx) -> None
self.app = app
- super(SphinxLogRecordTranslator, self).__init__()
+ super().__init__()
def filter(self, record): # type: ignore
# type: (SphinxWarningLogRecord) -> bool
@@ -485,18 +517,18 @@ def get_node_location(node):
class ColorizeFormatter(logging.Formatter):
def format(self, record):
# type: (logging.LogRecord) -> str
- message = super(ColorizeFormatter, self).format(record)
+ message = super().format(record)
color = getattr(record, 'color', None)
if color is None:
color = COLOR_MAP.get(record.levelno)
if color:
- return colorize(color, message) # type: ignore
+ return colorize(color, message)
else:
return message
-class SafeEncodingWriter(object):
+class SafeEncodingWriter:
"""Stream writer which ignores UnicodeEncodeError silently"""
def __init__(self, stream):
# type: (IO) -> None
@@ -504,7 +536,7 @@ class SafeEncodingWriter(object):
self.encoding = getattr(stream, 'encoding', 'ascii') or 'ascii'
def write(self, data):
- # type: (unicode) -> None
+ # type: (str) -> None
try:
self.stream.write(data)
except UnicodeEncodeError:
@@ -518,14 +550,14 @@ class SafeEncodingWriter(object):
self.stream.flush()
-class LastMessagesWriter(object):
+class LastMessagesWriter:
"""Stream writer which memories last 10 messages to save trackback"""
def __init__(self, app, stream):
# type: (Sphinx, IO) -> None
self.app = app
def write(self, data):
- # type: (unicode) -> None
+ # type: (str) -> None
self.app.messagelog.append(data)