Skip to content

Commit 8f1a038

Browse files
committed
Do not suppress pytest.exit() or keyboard interrupt when working with pdb
1 parent 810fa89 commit 8f1a038

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

src/_pytest/runner.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import TYPE_CHECKING
1717
from typing import TypeVar
1818

19+
from .config import Config
1920
from .reports import BaseReport
2021
from .reports import CollectErrorRepr
2122
from .reports import CollectReport
@@ -239,11 +240,11 @@ def call_and_report(
239240
runtest_hook = ihook.pytest_runtest_teardown
240241
else:
241242
assert False, f"Unhandled runtest hook case: {when}"
242-
reraise: tuple[type[BaseException], ...] = (Exit,)
243-
if not item.config.getoption("usepdb", False):
244-
reraise += (KeyboardInterrupt,)
243+
245244
call = CallInfo.from_call(
246-
lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise
245+
lambda: runtest_hook(item=item, **kwds),
246+
when=when,
247+
reraise=get_reraise_exceptions(item.config),
247248
)
248249
report: TestReport = ihook.pytest_runtest_makereport(item=item, call=call)
249250
if log:
@@ -253,6 +254,14 @@ def call_and_report(
253254
return report
254255

255256

257+
def get_reraise_exceptions(config: Config) -> tuple[type[BaseException], ...]:
258+
"""Return exception types that should not be suppressed in general."""
259+
reraise: tuple[type[BaseException], ...] = (Exit,)
260+
if not config.getoption("usepdb", False):
261+
reraise += (KeyboardInterrupt,)
262+
return reraise
263+
264+
256265
def check_interactive_exception(call: CallInfo[object], report: BaseReport) -> bool:
257266
"""Check whether the call raised an exception that should be reported as
258267
interactive."""

src/_pytest/subtests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from _pytest.reports import TestReport
3535
from _pytest.runner import CallInfo
3636
from _pytest.runner import check_interactive_exception
37+
from _pytest.runner import get_reraise_exceptions
3738
from _pytest.stash import StashKey
3839

3940

@@ -276,6 +277,8 @@ def __exit__(
276277
)
277278

278279
if exc_val is not None:
280+
if isinstance(exc_val, get_reraise_exceptions(self.config)):
281+
return False
279282
if self.request.session.shouldfail:
280283
return False
281284
return True

testing/test_subtests.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,3 +931,23 @@ def test_foo(subtests):
931931
consecutive=True,
932932
)
933933
result.stdout.no_fnmatch_line("*sub2*") # sub2 not executed.
934+
935+
936+
def test_do_not_swallow_pytest_exit(pytester: pytest.Pytester) -> None:
937+
pytester.makepyfile(
938+
"""
939+
import pytest
940+
def test(subtests):
941+
with subtests.test():
942+
pytest.exit()
943+
944+
def test2(): pass
945+
"""
946+
)
947+
result = pytester.runpytest_subprocess()
948+
result.stdout.fnmatch_lines(
949+
[
950+
"* _pytest.outcomes.Exit *",
951+
"* 1 failed in *",
952+
]
953+
)

0 commit comments

Comments
 (0)