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.py116
1 files changed, 40 insertions, 76 deletions
diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py
index afa4ebd23..d6667dacd 100644
--- a/sphinx/util/logging.py
+++ b/sphinx/util/logging.py
@@ -12,8 +12,10 @@ import logging
import logging.handlers
from collections import defaultdict
from contextlib import contextmanager
+from typing import Any, Dict, Generator, IO, List, Tuple, Type, Union
from docutils import nodes
+from docutils.nodes import Node
from docutils.utils import get_source_line
from sphinx.errors import SphinxWarning
@@ -21,8 +23,7 @@ from sphinx.util.console import colorize
if False:
# For type annotation
- from typing import Any, Dict, Generator, IO, List, Tuple, Type, Union # NOQA
- from sphinx.application import Sphinx # NOQA
+ from sphinx.application import Sphinx
NAMESPACE = 'sphinx'
@@ -54,8 +55,7 @@ COLOR_MAP = defaultdict(lambda: 'blue',
})
-def getLogger(name):
- # type: (str) -> SphinxLoggerAdapter
+def getLogger(name: str) -> "SphinxLoggerAdapter":
"""Get logger wrapped by :class:`sphinx.util.logging.SphinxLoggerAdapter`.
Sphinx logger always uses ``sphinx.*`` namespace to be independent from
@@ -77,8 +77,7 @@ def getLogger(name):
return SphinxLoggerAdapter(logger, {})
-def convert_serializable(records):
- # type: (List[logging.LogRecord]) -> None
+def convert_serializable(records: List[logging.LogRecord]) -> None:
"""Convert LogRecord serializable."""
for r in records:
# extract arguments to a message and clear them
@@ -95,8 +94,7 @@ class SphinxLogRecord(logging.LogRecord):
prefix = ''
location = None # type: Any
- def getMessage(self):
- # type: () -> str
+ def getMessage(self) -> str:
message = super().getMessage()
location = getattr(self, 'location', None)
if location:
@@ -120,20 +118,17 @@ class SphinxWarningLogRecord(SphinxLogRecord):
class SphinxLoggerAdapter(logging.LoggerAdapter):
"""LoggerAdapter allowing ``type`` and ``subtype`` keywords."""
- def log(self, level, msg, *args, **kwargs):
- # type: (Union[int, str], str, Any, Any) -> None
+ def log(self, level: Union[int, str], msg: str, *args, **kwargs) -> None:
if isinstance(level, int):
super().log(level, msg, *args, **kwargs)
else:
levelno = LEVEL_NAMES[level]
super().log(levelno, msg, *args, **kwargs)
- def verbose(self, msg, *args, **kwargs):
- # type: (str, Any, Any) -> None
+ def verbose(self, msg: str, *args, **kwargs) -> None:
self.log(VERBOSE, msg, *args, **kwargs)
- def process(self, msg, kwargs): # type: ignore
- # type: (str, Dict) -> Tuple[str, Dict]
+ def process(self, msg: str, kwargs: Dict) -> Tuple[str, Dict]: # type: ignore
extra = kwargs.setdefault('extra', {})
if 'type' in kwargs:
extra['type'] = kwargs.pop('type')
@@ -148,8 +143,7 @@ class SphinxLoggerAdapter(logging.LoggerAdapter):
return msg, kwargs
- def handle(self, record):
- # type: (logging.LogRecord) -> None
+ def handle(self, record: logging.LogRecord) -> None:
self.logger.handle(record)
@@ -161,8 +155,7 @@ class WarningStreamHandler(logging.StreamHandler):
class NewLineStreamHandler(logging.StreamHandler):
"""StreamHandler which switches line terminator by record.nonl flag."""
- def emit(self, record):
- # type: (logging.LogRecord) -> None
+ def emit(self, record: logging.LogRecord) -> None:
try:
self.acquire()
if getattr(record, 'nonl', False):
@@ -177,16 +170,13 @@ class NewLineStreamHandler(logging.StreamHandler):
class MemoryHandler(logging.handlers.BufferingHandler):
"""Handler buffering all logs."""
- def __init__(self):
- # type: () -> None
+ def __init__(self) -> None:
super().__init__(-1)
- def shouldFlush(self, record):
- # type: (logging.LogRecord) -> bool
+ def shouldFlush(self, record: logging.LogRecord) -> bool:
return False # never flush
- def flushTo(self, logger):
- # type: (logging.Logger) -> None
+ def flushTo(self, logger: logging.Logger) -> None:
self.acquire()
try:
for record in self.buffer:
@@ -195,15 +185,13 @@ class MemoryHandler(logging.handlers.BufferingHandler):
finally:
self.release()
- def clear(self):
- # type: () -> List[logging.LogRecord]
+ def clear(self) -> List[logging.LogRecord]:
buffer, self.buffer = self.buffer, []
return buffer
@contextmanager
-def pending_warnings():
- # type: () -> Generator
+def pending_warnings() -> Generator[logging.Handler, None, None]:
"""Contextmanager to pend logging warnings temporary.
Similar to :func:`pending_logging`.
@@ -231,8 +219,7 @@ def pending_warnings():
@contextmanager
-def pending_logging():
- # type: () -> Generator
+def pending_logging() -> Generator[MemoryHandler, None, None]:
"""Contextmanager to pend logging all logs temporary.
For example::
@@ -264,8 +251,7 @@ def pending_logging():
@contextmanager
-def skip_warningiserror(skip=True):
- # type: (bool) -> Generator
+def skip_warningiserror(skip: bool = True) -> Generator[None, None, None]:
"""contextmanager to skip WarningIsErrorFilter for a while."""
logger = logging.getLogger(NAMESPACE)
@@ -285,8 +271,7 @@ def skip_warningiserror(skip=True):
@contextmanager
-def prefixed_warnings(prefix):
- # type: (str) -> Generator
+def prefixed_warnings(prefix: str) -> Generator[None, None, None]:
"""Prepend prefix to all records for a while.
For example::
@@ -332,13 +317,11 @@ def prefixed_warnings(prefix):
class LogCollector:
- def __init__(self):
- # type: () -> None
+ def __init__(self) -> None:
self.logs = [] # type: List[logging.LogRecord]
@contextmanager
- def collect(self):
- # type: () -> Generator
+ def collect(self) -> Generator[None, None, None]:
with pending_logging() as memhandler:
yield
@@ -348,16 +331,14 @@ class LogCollector:
class InfoFilter(logging.Filter):
"""Filter error and warning messages."""
- def filter(self, record):
- # type: (logging.LogRecord) -> bool
+ def filter(self, record: logging.LogRecord) -> bool:
if record.levelno < logging.WARNING:
return True
else:
return False
-def is_suppressed_warning(type, subtype, suppress_warnings):
- # type: (str, str, List[str]) -> bool
+def is_suppressed_warning(type: str, subtype: str, suppress_warnings: List[str]) -> bool:
"""Check the warning is suppressed or not."""
if type is None:
return False
@@ -379,13 +360,11 @@ def is_suppressed_warning(type, subtype, suppress_warnings):
class WarningSuppressor(logging.Filter):
"""Filter logs by `suppress_warnings`."""
- def __init__(self, app):
- # type: (Sphinx) -> None
+ def __init__(self, app: "Sphinx") -> None:
self.app = app
super().__init__()
- def filter(self, record):
- # type: (logging.LogRecord) -> bool
+ def filter(self, record: logging.LogRecord) -> bool:
type = getattr(record, 'type', None)
subtype = getattr(record, 'subtype', None)
@@ -405,13 +384,11 @@ class WarningSuppressor(logging.Filter):
class WarningIsErrorFilter(logging.Filter):
"""Raise exception if warning emitted."""
- def __init__(self, app):
- # type: (Sphinx) -> None
+ def __init__(self, app: "Sphinx") -> None:
self.app = app
super().__init__()
- def filter(self, record):
- # type: (logging.LogRecord) -> bool
+ def filter(self, record: logging.LogRecord) -> bool:
if getattr(record, 'skip_warningsiserror', False):
# disabled by DisableWarningIsErrorFilter
return True
@@ -433,8 +410,7 @@ class WarningIsErrorFilter(logging.Filter):
class DisableWarningIsErrorFilter(logging.Filter):
"""Disable WarningIsErrorFilter if this filter installed."""
- def filter(self, record):
- # type: (logging.LogRecord) -> bool
+ def filter(self, record: logging.LogRecord) -> bool:
record.skip_warningsiserror = True # type: ignore
return True
@@ -442,13 +418,11 @@ class DisableWarningIsErrorFilter(logging.Filter):
class MessagePrefixFilter(logging.Filter):
"""Prepend prefix to all records."""
- def __init__(self, prefix):
- # type: (str) -> None
+ def __init__(self, prefix: str) -> None:
self.prefix = prefix
super().__init__()
- def filter(self, record):
- # type: (logging.LogRecord) -> bool
+ def filter(self, record: logging.LogRecord) -> bool:
if self.prefix:
record.msg = self.prefix + ' ' + record.msg
return True
@@ -462,13 +436,11 @@ class SphinxLogRecordTranslator(logging.Filter):
"""
LogRecordClass = None # type: Type[logging.LogRecord]
- def __init__(self, app):
- # type: (Sphinx) -> None
+ def __init__(self, app: "Sphinx") -> None:
self.app = app
super().__init__()
- def filter(self, record): # type: ignore
- # type: (SphinxWarningLogRecord) -> bool
+ def filter(self, record: SphinxWarningLogRecord) -> bool: # type: ignore
if isinstance(record, logging.LogRecord):
# force subclassing to handle location
record.__class__ = self.LogRecordClass # type: ignore
@@ -500,8 +472,7 @@ class WarningLogRecordTranslator(SphinxLogRecordTranslator):
LogRecordClass = SphinxWarningLogRecord
-def get_node_location(node):
- # type: (nodes.Node) -> str
+def get_node_location(node: Node) -> str:
(source, line) = get_source_line(node)
if source and line:
return "%s:%s" % (source, line)
@@ -514,8 +485,7 @@ def get_node_location(node):
class ColorizeFormatter(logging.Formatter):
- def format(self, record):
- # type: (logging.LogRecord) -> str
+ def format(self, record: logging.LogRecord) -> str:
message = super().format(record)
color = getattr(record, 'color', None)
if color is None:
@@ -529,13 +499,11 @@ class ColorizeFormatter(logging.Formatter):
class SafeEncodingWriter:
"""Stream writer which ignores UnicodeEncodeError silently"""
- def __init__(self, stream):
- # type: (IO) -> None
+ def __init__(self, stream: IO) -> None:
self.stream = stream
self.encoding = getattr(stream, 'encoding', 'ascii') or 'ascii'
- def write(self, data):
- # type: (str) -> None
+ def write(self, data: str) -> None:
try:
self.stream.write(data)
except UnicodeEncodeError:
@@ -543,25 +511,21 @@ class SafeEncodingWriter:
# non-encodable characters, then decode them.
self.stream.write(data.encode(self.encoding, 'replace').decode(self.encoding))
- def flush(self):
- # type: () -> None
+ def flush(self) -> None:
if hasattr(self.stream, 'flush'):
self.stream.flush()
class LastMessagesWriter:
"""Stream writer which memories last 10 messages to save trackback"""
- def __init__(self, app, stream):
- # type: (Sphinx, IO) -> None
+ def __init__(self, app: "Sphinx", stream: IO) -> None:
self.app = app
- def write(self, data):
- # type: (str) -> None
+ def write(self, data: str) -> None:
self.app.messagelog.append(data)
-def setup(app, status, warning):
- # type: (Sphinx, IO, IO) -> None
+def setup(app: "Sphinx", status: IO, warning: IO) -> None:
"""Setup root logger for Sphinx"""
logger = logging.getLogger(NAMESPACE)
logger.setLevel(logging.DEBUG)