Add "once" option to logger.warning()

This commit is contained in:
Takeshi KOMIYA 2020-03-21 19:39:22 +09:00
parent 0c45776c07
commit 6f60864d03
2 changed files with 33 additions and 1 deletions

View File

@ -118,7 +118,7 @@ class SphinxWarningLogRecord(SphinxLogRecord):
class SphinxLoggerAdapter(logging.LoggerAdapter):
"""LoggerAdapter allowing ``type`` and ``subtype`` keywords."""
KEYWORDS = ['type', 'subtype', 'location', 'nonl', 'color']
KEYWORDS = ['type', 'subtype', 'location', 'nonl', 'color', 'once']
def log(self, level: Union[int, str], msg: str, *args: Any, **kwargs: Any) -> None:
if isinstance(level, int):
@ -440,6 +440,26 @@ class MessagePrefixFilter(logging.Filter):
return True
class OnceFilter(logging.Filter):
"""Show the message only once."""
def __init__(self, name: str = '') -> None:
super().__init__(name)
self.messages = {} # type: Dict[str, List]
def filter(self, record: logging.LogRecord) -> bool:
once = getattr(record, 'once', '')
if not once:
return True
else:
params = self.messages.setdefault(record.msg, [])
if record.args in params:
return False
params.append(record.args)
return True
class SphinxLogRecordTranslator(logging.Filter):
"""Converts a log record to one Sphinx expects
@ -557,6 +577,7 @@ def setup(app: "Sphinx", status: IO, warning: IO) -> None:
warning_handler.addFilter(WarningSuppressor(app))
warning_handler.addFilter(WarningLogRecordTranslator(app))
warning_handler.addFilter(WarningIsErrorFilter(app))
warning_handler.addFilter(OnceFilter())
warning_handler.setLevel(logging.WARNING)
warning_handler.setFormatter(ColorizeFormatter())

View File

@ -103,6 +103,17 @@ def test_nonl_info_log(app, status, warning):
assert 'message1message2\nmessage3' in status.getvalue()
def test_once_warning_log(app, status, warning):
logging.setup(app, status, warning)
logger = logging.getLogger(__name__)
logger.warning('message: %d', 1, once=True)
logger.warning('message: %d', 1, once=True)
logger.warning('message: %d', 2, once=True)
assert 'WARNING: message: 1\nWARNING: message: 2\n' in strip_escseq(warning.getvalue())
def test_is_suppressed_warning():
suppress_warnings = ["ref", "files.*", "rest.duplicated_labels"]