Skip to content

Commit

Permalink
Derive outcomes.exit.Exception from SystemExit instead of KeyboardInt…
Browse files Browse the repository at this point in the history
…errupt

This is required for properly getting out of pdb, where
KeyboardInterrupt is caught in py36 at least.

Ref: pytest-dev#1865 (comment)
  • Loading branch information
blueyed committed Dec 11, 2018
1 parent 8152b68 commit 283d824
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog/4292.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``pytest.outcomes.Exit`` is derived from ``SystemExit`` instead of ``KeyboardInterrupt``.
2 changes: 1 addition & 1 deletion src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def wrap_session(config, doit):
raise
except Failed:
session.exitstatus = EXIT_TESTSFAILED
except KeyboardInterrupt:
except (KeyboardInterrupt, exit.Exception):
excinfo = _pytest._code.ExceptionInfo.from_current()
exitstatus = EXIT_INTERRUPTED
if initstate <= 2 and isinstance(excinfo.value, exit.Exception):
Expand Down
6 changes: 3 additions & 3 deletions src/_pytest/outcomes.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ class Failed(OutcomeException):
__module__ = "builtins"


class Exit(KeyboardInterrupt):
class Exit(SystemExit):
""" raised for immediate program exits (no tracebacks/summaries)"""

def __init__(self, msg="unknown reason", returncode=None):
self.msg = msg
self.returncode = returncode
KeyboardInterrupt.__init__(self, msg)
SystemExit.__init__(self, msg)


# exposed helper methods


def exit(msg, returncode=None):
"""
Exit testing process as if KeyboardInterrupt was triggered.
Exit testing process as if SystemExit was triggered.
:param str msg: message to display upon exit.
:param int returncode: return code to be used when exiting pytest.
Expand Down
8 changes: 5 additions & 3 deletions src/_pytest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .reports import CollectReport
from .reports import TestReport
from _pytest._code.code import ExceptionInfo
from _pytest.outcomes import Exit
from _pytest.outcomes import skip
from _pytest.outcomes import Skipped
from _pytest.outcomes import TEST_OUTCOME
Expand Down Expand Up @@ -190,10 +191,11 @@ def check_interactive_exception(call, report):
def call_runtest_hook(item, when, **kwds):
hookname = "pytest_runtest_" + when
ihook = getattr(item.ihook, hookname)
reraise = (Exit,)
if not item.config.getvalue("usepdb"):
reraise += (KeyboardInterrupt,)
return CallInfo.from_call(
lambda: ihook(item=item, **kwds),
when=when,
reraise=KeyboardInterrupt if not item.config.getvalue("usepdb") else (),
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
)


Expand Down
2 changes: 1 addition & 1 deletion testing/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ def test_outcomeexception_passes_except_Exception():
def test_pytest_exit():
with pytest.raises(pytest.exit.Exception) as excinfo:
pytest.exit("hello")
assert excinfo.errisinstance(KeyboardInterrupt)
assert excinfo.errisinstance(pytest.exit.Exception)


def test_pytest_fail():
Expand Down

0 comments on commit 283d824

Please sign in to comment.