##// END OF EJS Templates
Merge pull request #12168 from itamarst/10516-interruptible-pdb...
Matthias Bussonnier -
r25660:95d5171b merge
parent child Browse files
Show More
@@ -0,0 +1,4 b''
1 IPython.core.debugger.Pdb is now interruptible
2 ==============================================
3
4 A ``KeyboardInterrupt`` will now interrupt IPython's extended debugger, in order to make Jupyter able to interrupt it.
@@ -632,6 +632,34 b' class Pdb(OldPdb):'
632 do_w = do_where
632 do_w = do_where
633
633
634
634
635 class InterruptiblePdb(Pdb):
636 """Version of debugger where KeyboardInterrupt exits the debugger altogether."""
637
638 def cmdloop(self):
639 """Wrap cmdloop() such that KeyboardInterrupt stops the debugger."""
640 try:
641 return OldPdb.cmdloop(self)
642 except KeyboardInterrupt:
643 self.stop_here = lambda frame: False
644 self.do_quit("")
645 sys.settrace(None)
646 self.quitting = False
647 raise
648
649 def _cmdloop(self):
650 while True:
651 try:
652 # keyboard interrupts allow for an easy way to cancel
653 # the current command, so allow them during interactive input
654 self.allow_kbdint = True
655 self.cmdloop()
656 self.allow_kbdint = False
657 break
658 except KeyboardInterrupt:
659 self.message('--KeyboardInterrupt--')
660 raise
661
662
635 def set_trace(frame=None):
663 def set_trace(frame=None):
636 """
664 """
637 Start debugging from `frame`.
665 Start debugging from `frame`.
@@ -4,8 +4,16 b''
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import signal
7 import sys
8 import sys
9 import time
8 import warnings
10 import warnings
11 from tempfile import NamedTemporaryFile
12 from subprocess import check_output, CalledProcessError, PIPE
13 import subprocess
14 from unittest.mock import patch
15 import builtins
16 import bdb
9
17
10 import nose.tools as nt
18 import nose.tools as nt
11
19
@@ -220,3 +228,26 b' def can_exit():'
220
228
221 >>> sys.settrace(old_trace)
229 >>> sys.settrace(old_trace)
222 '''
230 '''
231
232
233 def test_interruptible_core_debugger():
234 """The debugger can be interrupted.
235
236 The presumption is there is some mechanism that causes a KeyboardInterrupt
237 (this is implemented in ipykernel). We want to ensure the
238 KeyboardInterrupt cause debugging to cease.
239 """
240 def raising_input(msg="", called=[0]):
241 called[0] += 1
242 if called[0] == 1:
243 raise KeyboardInterrupt()
244 else:
245 raise AssertionError("input() should only be called once!")
246
247 with patch.object(builtins, "input", raising_input):
248 debugger.InterruptiblePdb().set_trace()
249 # The way this test will fail is by set_trace() never exiting,
250 # resulting in a timeout by the test runner. The alternative
251 # implementation would involve a subprocess, but that adds issues with
252 # interrupting subprocesses that are rather complex, so it's simpler
253 # just to do it this way.
General Comments 0
You need to be logged in to leave comments. Login now