diff --git a/CHANGES.rst b/CHANGES.rst index 1d04bc27010..2b8378b3e4c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,6 +13,10 @@ Deprecated Features added -------------- +* #12727: build: Allow :option:`sphinx-build --pdb` to debug warnings when + :option:`sphinx-build --fail-on-warning` is specified. + Patch by Jeremy Maitin-Shepard. + Bugs fixed ---------- diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 151df6aeb18..4e16ceae513 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations import codecs +import contextlib import pickle import re import time @@ -313,7 +314,9 @@ def build( logger.info(bold(__('building [%s]: ')) + summary, self.name) # while reading, collect all warnings from docutils - with logging.pending_warnings(): + with contextlib.ExitStack() as exit_stack: + if not self.app.pdb or not self.app.warningiserror: + exit_stack.enter_context(logging.pending_warnings()) updated_docnames = set(self.read()) doccount = len(updated_docnames) @@ -613,7 +616,9 @@ def write( self._write_serial(sorted(docnames)) def _write_serial(self, docnames: Sequence[str]) -> None: - with logging.pending_warnings(): + with contextlib.ExitStack() as exit_stack: + if not self.app.pdb or not self.app.warningiserror: + exit_stack.enter_context(logging.pending_warnings()) for docname in status_iterator(docnames, __('writing output... '), "darkgreen", len(docnames), self.app.verbosity): self.app.phase = BuildPhase.RESOLVING diff --git a/tests/test_builders/test_build_warnings.py b/tests/test_builders/test_build_warnings.py index 0ccade75e07..b942b2cd201 100644 --- a/tests/test_builders/test_build_warnings.py +++ b/tests/test_builders/test_build_warnings.py @@ -1,6 +1,7 @@ import os import re import sys +import traceback import pytest @@ -58,6 +59,20 @@ def test_html_warnings(app): _check_warnings(warnings_exp, app.warning.getvalue()) +@pytest.mark.parametrize('pdb', [True, False]) +@pytest.mark.sphinx('html', testroot='warnings', freshenv=True) +def test_html_warnings_pdb(app, pdb): + app.pdb = pdb + app.warningiserror = True + try: + app.build(force_all=True) + pytest.fail("Expected an exception to be raised") + except Exception: + tb = traceback.format_exc() + assert ("unindent_warning" in tb) == pdb + assert ("pending_warnings" not in tb) == pdb + + @pytest.mark.sphinx('latex', testroot='warnings', freshenv=True) def test_latex_warnings(app): app.build(force_all=True)