Skip to content

Commit a7268aa

Browse files
authored
Merge pull request #6258 from blueyed/notify_exception-handle-exit-exc-upstream
main: wrap_session: handle exit.Exception with notify_exception
2 parents 63c9ad0 + 2344982 commit a7268aa

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

changelog/6257.improvement.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Handle `exit.Exception` raised in `notify_exception` (via `pytest_internalerror`), e.g. when quitting pdb from post mortem.

src/_pytest/main.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,17 @@ def wrap_session(config, doit):
212212
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
213213
session.exitstatus = exitstatus
214214
except: # noqa
215-
excinfo = _pytest._code.ExceptionInfo.from_current()
216-
config.notify_exception(excinfo, config.option)
217215
session.exitstatus = ExitCode.INTERNAL_ERROR
218-
if excinfo.errisinstance(SystemExit):
219-
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
216+
excinfo = _pytest._code.ExceptionInfo.from_current()
217+
try:
218+
config.notify_exception(excinfo, config.option)
219+
except exit.Exception as exc:
220+
if exc.returncode is not None:
221+
session.exitstatus = exc.returncode
222+
sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc))
223+
else:
224+
if excinfo.errisinstance(SystemExit):
225+
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
220226

221227
finally:
222228
excinfo = None # Explicitly break reference cycle.

testing/test_main.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import pytest
2+
from _pytest.main import ExitCode
3+
4+
5+
@pytest.mark.parametrize(
6+
"ret_exc",
7+
(
8+
pytest.param((None, ValueError)),
9+
pytest.param((42, SystemExit)),
10+
pytest.param((False, SystemExit)),
11+
),
12+
)
13+
def test_wrap_session_notify_exception(ret_exc, testdir):
14+
returncode, exc = ret_exc
15+
c1 = testdir.makeconftest(
16+
"""
17+
import pytest
18+
19+
def pytest_sessionstart():
20+
raise {exc}("boom")
21+
22+
def pytest_internalerror(excrepr, excinfo):
23+
returncode = {returncode!r}
24+
if returncode is not False:
25+
pytest.exit("exiting after %s..." % excinfo.typename, returncode={returncode!r})
26+
""".format(
27+
returncode=returncode, exc=exc.__name__
28+
)
29+
)
30+
result = testdir.runpytest()
31+
if returncode:
32+
assert result.ret == returncode
33+
else:
34+
assert result.ret == ExitCode.INTERNAL_ERROR
35+
assert result.stdout.lines[0] == "INTERNALERROR> Traceback (most recent call last):"
36+
37+
if exc == SystemExit:
38+
assert result.stdout.lines[-3:] == [
39+
'INTERNALERROR> File "{}", line 4, in pytest_sessionstart'.format(c1),
40+
'INTERNALERROR> raise SystemExit("boom")',
41+
"INTERNALERROR> SystemExit: boom",
42+
]
43+
else:
44+
assert result.stdout.lines[-3:] == [
45+
'INTERNALERROR> File "{}", line 4, in pytest_sessionstart'.format(c1),
46+
'INTERNALERROR> raise ValueError("boom")',
47+
"INTERNALERROR> ValueError: boom",
48+
]
49+
if returncode is False:
50+
assert result.stderr.lines == ["mainloop: caught unexpected SystemExit!"]
51+
else:
52+
assert result.stderr.lines == ["Exit: exiting after {}...".format(exc.__name__)]

0 commit comments

Comments
 (0)