diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 9dc757cd4..6230502d1 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -287,7 +287,7 @@ class Builder(object): logger.info(bold('building [%s]' % self.name) + ': ' + summary) # while reading, collect all warnings from docutils - with logging.pending_logging(): + with logging.pending_warnings(): updated_docnames = set(self.env.update(self.config, self.srcdir, self.doctreedir, self.app)) @@ -386,7 +386,7 @@ class Builder(object): def _write_serial(self, docnames): # type: (Sequence[unicode]) -> None - with logging.pending_logging(): + with logging.pending_warnings(): for docname in self.app.status_iterator( docnames, 'writing output... ', darkgreen, len(docnames)): doctree = self.env.get_and_resolve_doctree(docname, self) diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index 7afaadf34..a473ffc97 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -126,6 +126,11 @@ class SphinxLoggerAdapter(logging.LoggerAdapter): self.logger.handle(record) # type: ignore +class WarningStreamHandler(logging.StreamHandler): + """StreamHandler for warnings.""" + pass + + class NewLineStreamHandlerPY2(logging.StreamHandler): """StreamHandler which switches line terminator by record.nonl flag.""" @@ -195,10 +200,36 @@ class MemoryHandler(logging.handlers.BufferingHandler): return buffer +@contextmanager +def pending_warnings(): + # type: () -> Generator + """contextmanager to pend logging warnings temporary.""" + logger = logging.getLogger() + memhandler = MemoryHandler() + memhandler.setLevel(logging.WARNING) + + try: + handlers = [] + for handler in logger.handlers[:]: + if isinstance(handler, WarningStreamHandler): + logger.removeHandler(handler) + handlers.append(handler) + + logger.addHandler(memhandler) + yield memhandler + finally: + logger.removeHandler(memhandler) + + for handler in handlers: + logger.addHandler(handler) + + memhandler.flushTo(logger) + + @contextmanager def pending_logging(): # type: () -> Generator - """contextmanager to pend logging temporary.""" + """contextmanager to pend logging all logs temporary.""" logger = logging.getLogger() memhandler = MemoryHandler() @@ -357,7 +388,7 @@ def setup(app, status, warning): info_handler.setLevel(VERBOSITY_MAP.get(app.verbosity)) info_handler.setFormatter(ColorizeFormatter()) - warning_handler = logging.StreamHandler(warning) + warning_handler = WarningStreamHandler(warning) warning_handler.addFilter(WarningSuppressor(app)) warning_handler.addFilter(WarningIsErrorFilter(app)) warning_handler.addFilter(WarningLogRecordTranslator(app)) diff --git a/tests/test_util_logging.py b/tests/test_util_logging.py index 25816bf4e..984b52220 100644 --- a/tests/test_util_logging.py +++ b/tests/test_util_logging.py @@ -225,12 +225,12 @@ def test_warn_node(app, status, warning): @with_app() -def test_pending_logging(app, status, warning): +def test_pending_warnings(app, status, warning): logging.setup(app, status, warning) logger = logging.getLogger(__name__) logger.warning('message1') - with logging.pending_logging(): + with logging.pending_warnings(): # not logged yet (bufferred) in here logger.warning('message2') logger.warning('message3')