Skip to content

Commit 40ba953

Browse files
blueyedvinaycalastry
authored andcommitted
main: wrap_session: handle exit.Exception with notify_exception
Fixes pytest-dev#6257. Via blueyed#132.
1 parent 2594786 commit 40ba953

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

changelog/6257.improvement.rst

+1
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

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

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

testing/test_main.py

+52
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)