Skip to content

Commit b03b387

Browse files
authored
Merge pull request #3436 from brianmaissy/feature/enter_pdb_on_keyboard_interrupt
--pdb treats KeyboardInterrupt as exception
2 parents 7834b45 + 1a880be commit b03b387

File tree

5 files changed

+22
-8
lines changed

5 files changed

+22
-8
lines changed

_pytest/debugging.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def pytest_addoption(parser):
1616
group = parser.getgroup("general")
1717
group._addoption(
1818
'--pdb', dest="usepdb", action="store_true",
19-
help="start the interactive Python debugger on errors.")
19+
help="start the interactive Python debugger on errors or KeyboardInterrupt.")
2020
group._addoption(
2121
'--pdbcls', dest="usepdb_cls", metavar="modulename:classname",
2222
help="start a custom interactive Python debugger on errors. "

_pytest/runner.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,24 +176,28 @@ def check_interactive_exception(call, report):
176176
def call_runtest_hook(item, when, **kwds):
177177
hookname = "pytest_runtest_" + when
178178
ihook = getattr(item.ihook, hookname)
179-
return CallInfo(lambda: ihook(item=item, **kwds), when=when)
179+
return CallInfo(lambda: ihook(item=item, **kwds), when=when,
180+
treat_keyboard_interrupt_as_exception=item.config.getvalue("usepdb"))
180181

181182

182183
class CallInfo(object):
183184
""" Result/Exception info a function invocation. """
184185
#: None or ExceptionInfo object.
185186
excinfo = None
186187

187-
def __init__(self, func, when):
188+
def __init__(self, func, when, treat_keyboard_interrupt_as_exception=False):
188189
#: context of invocation: one of "setup", "call",
189190
#: "teardown", "memocollect"
190191
self.when = when
191192
self.start = time()
192193
try:
193194
self.result = func()
194195
except KeyboardInterrupt:
195-
self.stop = time()
196-
raise
196+
if treat_keyboard_interrupt_as_exception:
197+
self.excinfo = ExceptionInfo()
198+
else:
199+
self.stop = time()
200+
raise
197201
except: # noqa
198202
self.excinfo = ExceptionInfo()
199203
self.stop = time()

changelog/3299.feature.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The ``--pdb`` option now causes KeyboardInterrupt to enter the debugger, instead of stopping the test session.
2+
On python 2.7, hitting CTRL+C again exits the debugger. On python 3.2 and higher, use CTRL+D.

doc/en/usage.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@ allows one to drop into the PDB_ prompt via a command line option::
152152

153153
pytest --pdb
154154

155-
This will invoke the Python debugger on every failure. Often you might
156-
only want to do this for the first failing test to understand a certain
157-
failure situation::
155+
This will invoke the Python debugger on every failure (or KeyboardInterrupt).
156+
Often you might only want to do this for the first failing test to understand
157+
a certain failure situation::
158158

159159
pytest -x --pdb # drop to PDB on first failure, then end test session
160160
pytest --pdb --maxfail=3 # drop to PDB for first three failures

testing/test_pdb.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ def test_func():
114114
assert rep.failed
115115
assert len(pdblist) == 0
116116

117+
def test_pdb_on_KeyboardInterrupt(self, testdir, pdblist):
118+
rep = runpdb_and_get_report(testdir, """
119+
def test_func():
120+
raise KeyboardInterrupt
121+
""")
122+
assert rep.failed
123+
assert len(pdblist) == 1
124+
117125
def test_pdb_interaction(self, testdir):
118126
p1 = testdir.makepyfile("""
119127
def test_1():

0 commit comments

Comments
 (0)