Repository: ipython/ipython

Issue:
IPython 5.3.0 debug mode breakpoint issue
Hi IPython Team,

I recently upgraded Python to version 2.7.8 (from 2.6.6) and IPython to version 5.3.0.  I noticed that when using the magic command (%run -d) in IPython, subsequent runs of a program seem to fail with a "KeyError", apparently due to the debugger's failure to clear breakpoints from previous runs of the program.

I attached a sample of output from one such failed run (see below), where a breakpoint that had been set at line 56 in a previous call caused the program to crash, though in the current call, only one breakpoint at line 70 is requested.

For the time being, I've downgraded to IPython version 4.2.0, which seems to work as expected.

Cheers,
Taylor

[ipython_error.txt](https://github.com/ipython/ipython/files/1004089/ipython_error.txt)


Discussion:
Can you give a self-contained example to reproduce this?

This comment in `bdb.Breakpoint` is not encouraging:

```
# XXX Keeping state in the class is a mistake -- this means
# you cannot have more than one active Bdb instance.
```
Thanks for responding.  Sure- following these steps should reproduce the issue:

1. Load Python version 2.7.8 (if necessary).

2. Load IPython version 5.3.0 (if necessary).

3. Open an ipython session and run the attached script (test.py) with the magic run command '%run', and set a breakpoint as follows:
In [1]: %run -d test.py
ipdb> b 4
ipdb> c

The program should execute successfully at this point.  However, running a second time following the same procedure produces an error.  

4. Rerun the program as before:
In [2]: %run -d test.py
ipdb> b 4
ipdb> c

This should cause a key error to appear.  Something like:
KeyError: ('<path_to_program>/test.py', 4) 

[test.py.zip](https://github.com/ipython/ipython/files/1014420/test.py.zip)



 


   

Resolving patch:
diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py
--- a/IPython/core/magics/execution.py
+++ b/IPython/core/magics/execution.py
@@ -849,6 +849,7 @@ def _run_with_debugger(self, code, code_ns, filename=None,
         bdb.Breakpoint.next = 1
         bdb.Breakpoint.bplist = {}
         bdb.Breakpoint.bpbynumber = [None]
+        deb.clear_all_breaks()
         if bp_line is not None:
             # Set an initial breakpoint to stop execution
             maxtries = 10


Test patch:
diff --git a/IPython/core/tests/test_run.py b/IPython/core/tests/test_run.py
--- a/IPython/core/tests/test_run.py
+++ b/IPython/core/tests/test_run.py
@@ -165,8 +165,8 @@ def doctest_reset_del():
 class TestMagicRunPass(tt.TempFileMixin):
 
     def setup(self):
-        """Make a valid python temp file."""
-        self.mktmp('pass\n')
+        content = "a = [1,2,3]\nb = 1"
+        self.mktmp(content)
         
     def run_tmpfile(self):
         _ip = get_ipython()
@@ -213,6 +213,16 @@ def test_run_debug_twice(self):
         with tt.fake_input(['c']):
             _ip.magic('run -d %s' % self.fname)
 
+    def test_run_debug_twice_with_breakpoint(self):
+        """Make a valid python temp file."""
+        _ip = get_ipython()
+        with tt.fake_input(['b 2', 'c', 'c']):
+            _ip.magic('run -d %s' % self.fname)
+
+        with tt.fake_input(['c']):
+            with tt.AssertNotPrints('KeyError'):
+                _ip.magic('run -d %s' % self.fname)
+
 
 class TestMagicRunSimple(tt.TempFileMixin):