summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--sphinx/application.py4
-rw-r--r--sphinx/cmd/build.py3
-rw-r--r--sphinx/events.py3
-rw-r--r--tests/test_events.py23
5 files changed, 31 insertions, 3 deletions
diff --git a/CHANGES b/CHANGES
index cccc54985..27af998a2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -36,6 +36,7 @@ Features added
Bugs fixed
----------
+* #10634: Make -P (pdb) option work better with exceptions triggered from events
* #10031: py domain: Fix spurious whitespace in unparsing various operators (``+``,
``-``, ``~``, and ``**``). Patch by Adam Turner.
* #10460: logging: Always show node source locations as absolute paths.
diff --git a/sphinx/application.py b/sphinx/application.py
index 08c4af5ba..c11b48916 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -131,7 +131,8 @@ class Sphinx:
buildername: str, confoverrides: Dict = None,
status: Optional[IO] = sys.stdout, warning: Optional[IO] = sys.stderr,
freshenv: bool = False, warningiserror: bool = False, tags: List[str] = None,
- verbosity: int = 0, parallel: int = 0, keep_going: bool = False) -> None:
+ verbosity: int = 0, parallel: int = 0, keep_going: bool = False,
+ pdb: bool = False) -> None:
self.phase = BuildPhase.INITIALIZATION
self.verbosity = verbosity
self.extensions: Dict[str, Extension] = {}
@@ -173,6 +174,7 @@ class Sphinx:
self.warningiserror = False
else:
self.warningiserror = warningiserror
+ self.pdb = pdb
logging.setup(self, self._status, self._warning)
self.events = EventManager(self)
diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py
index ce0b14c75..259af2eb2 100644
--- a/sphinx/cmd/build.py
+++ b/sphinx/cmd/build.py
@@ -272,7 +272,8 @@ def build_main(argv: List[str] = sys.argv[1:]) -> int:
app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
args.doctreedir, args.builder, confoverrides, status,
warning, args.freshenv, args.warningiserror,
- args.tags, args.verbosity, args.jobs, args.keep_going)
+ args.tags, args.verbosity, args.jobs, args.keep_going,
+ args.pdb)
app.build(args.force_all, filenames)
return app.statuscode
except (Exception, KeyboardInterrupt) as exc:
diff --git a/sphinx/events.py b/sphinx/events.py
index 5302cd005..448af0695 100644
--- a/sphinx/events.py
+++ b/sphinx/events.py
@@ -98,6 +98,9 @@ class EventManager:
except SphinxError:
raise
except Exception as exc:
+ if self.app.pdb:
+ # Just pass through the error, so that it can be debugged.
+ raise
modname = safe_getattr(listener.handler, '__module__', None)
raise ExtensionError(__("Handler %r for event %r threw an exception") %
(listener.handler, name), exc, modname=modname) from exc
diff --git a/tests/test_events.py b/tests/test_events.py
index f36c86a87..8f01a673a 100644
--- a/tests/test_events.py
+++ b/tests/test_events.py
@@ -19,11 +19,16 @@ def test_event_priority():
assert result == [3, 1, 2, 5, 4]
+class FakeApp:
+ def __init__(self, pdb: bool = False):
+ self.pdb = pdb
+
+
def test_event_allowed_exceptions():
def raise_error(app):
raise RuntimeError
- events = EventManager(object()) # pass an dummy object as an app
+ events = EventManager(FakeApp()) # pass an dummy object as an app
events.connect('builder-inited', raise_error, priority=500)
# all errors are converted to ExtensionError
@@ -33,3 +38,19 @@ def test_event_allowed_exceptions():
# Allow RuntimeError (pass-through)
with pytest.raises(RuntimeError):
events.emit('builder-inited', allowed_exceptions=(RuntimeError,))
+
+
+def test_event_pdb():
+ def raise_error(app):
+ raise RuntimeError
+
+ events = EventManager(FakeApp(pdb=True)) # pass an dummy object as an app
+ events.connect('builder-inited', raise_error, priority=500)
+
+ # errors aren't converted
+ with pytest.raises(RuntimeError):
+ events.emit('builder-inited')
+
+ # Allow RuntimeError (pass-through)
+ with pytest.raises(RuntimeError):
+ events.emit('builder-inited', allowed_exceptions=(RuntimeError,))