Skip to content

Commit

Permalink
main: wrap_session: handle exit.Exception with notify_exception
Browse files Browse the repository at this point in the history
  • Loading branch information
blueyed authored and vinaycalastry committed Dec 11, 2019
1 parent 2594786 commit 40ba953
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog/6257.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Handle `exit.Exception` raised in `notify_exception` (via `pytest_internalerror`), e.g. when quitting pdb from post mortem.
14 changes: 10 additions & 4 deletions src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,17 @@ def wrap_session(config, doit):
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
session.exitstatus = exitstatus
except: # noqa
excinfo = _pytest._code.ExceptionInfo.from_current()
config.notify_exception(excinfo, config.option)
session.exitstatus = ExitCode.INTERNAL_ERROR
if excinfo.errisinstance(SystemExit):
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
excinfo = _pytest._code.ExceptionInfo.from_current()
try:
config.notify_exception(excinfo, config.option)
except exit.Exception as exc:
if exc.returncode is not None:
session.exitstatus = exc.returncode
sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc))
else:
if excinfo.errisinstance(SystemExit):
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")

finally:
excinfo = None # Explicitly break reference cycle.
Expand Down
52 changes: 52 additions & 0 deletions testing/test_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from _pytest.main import ExitCode


@pytest.mark.parametrize(
"ret_exc",
(
pytest.param((None, ValueError)),
pytest.param((42, SystemExit)),
pytest.param((False, SystemExit)),
),
)
def test_wrap_session_notify_exception(ret_exc, testdir):
returncode, exc = ret_exc
c1 = testdir.makeconftest(
"""
import pytest
def pytest_sessionstart():
raise {exc}("boom")
def pytest_internalerror(excrepr, excinfo):
returncode = {returncode!r}
if returncode is not False:
pytest.exit("exiting after %s..." % excinfo.typename, returncode={returncode!r})
""".format(
returncode=returncode, exc=exc.__name__
)
)
result = testdir.runpytest()
if returncode:
assert result.ret == returncode
else:
assert result.ret == ExitCode.INTERNAL_ERROR
assert result.stdout.lines[0] == "INTERNALERROR> Traceback (most recent call last):"

if exc == SystemExit:
assert result.stdout.lines[-3:] == [
'INTERNALERROR> File "{}", line 4, in pytest_sessionstart'.format(c1),
'INTERNALERROR> raise SystemExit("boom")',
"INTERNALERROR> SystemExit: boom",
]
else:
assert result.stdout.lines[-3:] == [
'INTERNALERROR> File "{}", line 4, in pytest_sessionstart'.format(c1),
'INTERNALERROR> raise ValueError("boom")',
"INTERNALERROR> ValueError: boom",
]
if returncode is False:
assert result.stderr.lines == ["mainloop: caught unexpected SystemExit!"]
else:
assert result.stderr.lines == ["Exit: exiting after {}...".format(exc.__name__)]

0 comments on commit 40ba953

Please sign in to comment.