# Buggy code
def _run_with_debugger(self, code, code_ns, filename=None, bp_line=None, bp_file=None):
    """
    Run `code` in debugger with a break point.

    Parameters
    ----------
    code : str
        Code to execute.
    code_ns : dict
        A namespace in which `code` is executed.
    filename : str
        `code` is ran as if it is in `filename`.
    bp_line : int, optional
        Line number of the break point.
    bp_file : str, optional
        Path to the file in which break point is specified.
        `filename` is used if not given.

    Raises
    ------
    UsageError
        If the break point given by `bp_line` is not valid.

    """
    deb = self.shell.InteractiveTB.pdb
    if not deb:
        self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
        deb = self.shell.InteractiveTB.pdb

    # reset Breakpoint state, which is moronically kept
    # in a class
    bdb.Breakpoint.next = 1
    bdb.Breakpoint.bplist = {}
    bdb.Breakpoint.bpbynumber = [None]
    if bp_line is not None:
        # Set an initial breakpoint to stop execution
        maxtries = 10
        bp_file = bp_file or filename
        checkline = deb.checkline(bp_file, bp_line)
        if not checkline:
            for bp in range(bp_line + 1, bp_line + maxtries + 1):
                if deb.checkline(bp_file, bp):
                    break
            else:
                msg = (
                    "\nI failed to find a valid line to set "
                    "a breakpoint\n"
                    "after trying up to line: %s.\n"
                    "Please set a valid breakpoint manually "
                    "with the -b option." % bp
                )
                raise UsageError(msg)
        # if we find a good linenumber, set the breakpoint
        deb.do_break("%s:%s" % (bp_file, bp_line))

    if filename:
        # Mimic Pdb._runscript(...)
        deb._wait_for_mainpyfile = True
        deb.mainpyfile = deb.canonic(filename)

    # Start file run
    print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
    try:
        if filename:
            # save filename so it can be used by methods on the deb object
            deb._exec_filename = filename
        while True:
            try:
                deb.run(code, code_ns)
            except Restart:
                print("Restarting")
                if filename:
                    deb._wait_for_mainpyfile = True
                    deb.mainpyfile = deb.canonic(filename)
                continue
            else:
                break

    except:
        etype, value, tb = sys.exc_info()
        # Skip three frames in the traceback: the %run one,
        # one inside bdb.py, and the command-line typed by the
        # user (run by exec in pdb itself).
        self.shell.InteractiveTB(etype, value, tb, tb_offset=3)


# Traceback (AttributeError)
~/Workspace/puzzles/FiveThirtyEightRiddler $ ipython
Python 3.4.2 (default, Jun 20 2016, 14:25:19)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %run -d test.py
Breakpoint 1 at /home/andrew/Workspace/puzzles/FiveThirtyEightRiddler/test.py:1
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.
/home/andrew/Workspace/puzzles/FiveThirtyEightRiddler/test.py(1)<module>()
1---> 1 print('test')

ipdb> c
test

In [2]: %run -d test.py
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-2-63fffe36c4af> in <module>()
----> 1 get_ipython().magic('run -d test.py')

/usr/lib/python3.4/site-packages/IPython/core/interactiveshell.py in magic(self, arg_s)
2156         magic_name, _, magic_arg_s = arg_s.partition(' ')
2157         magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2158         return self.run_line_magic(magic_name, magic_arg_s)
2159
2160     #-------------------------------------------------------------------------

/usr/lib/python3.4/site-packages/IPython/core/interactiveshell.py in run_line_magic(self, magic_name, line)
2077                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2078             with self.builtin_trap:
-> 2079                 result = fn(*args,**kwargs)
2080             return result
2081

<decorator-gen-57> in run(self, parameter_s, runner, file_finder)

/usr/lib/python3.4/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
186     # but it's overkill for just that one bit of state.
187     def magic_deco(arg):
--> 188         call = lambda f, *a, **k: f(*a, **k)
189
190         if callable(arg):

/usr/lib/python3.4/site-packages/IPython/core/magics/execution.py in run(self, parameter_s, runner, file_finder)
713                         opts.get('b', ['1'])[0], filename)
714                     self._run_with_debugger(
--> 715                         code, code_ns, filename, bp_line, bp_file)
716                 else:
717                     if 'm' in opts:

/usr/lib/python3.4/site-packages/IPython/core/magics/execution.py in _run_with_debugger(self, code, code_ns, filename, bp_line, bp_file)
816             maxtries = 10
817             bp_file = bp_file or filename
--> 818             checkline = deb.checkline(bp_file, bp_line)
819             if not checkline:
820                 for bp in range(bp_line + 1, bp_line + maxtries + 1):

/usr/lib64/python3.4/pdb.py in checkline(self, filename, lineno)
743         # this method should be callable before starting debugging, so default
744         # to "no globals" if there is no current frame
--> 745         globs = self.curframe.f_globals if hasattr(self, 'curframe') else None
746         line = linecache.getline(filename, lineno, globs)
747         if not line:

AttributeError: 'NoneType' object has no attribute 'f_globals'

In [3]:

# Fixed code
def _run_with_debugger(self, code, code_ns, filename=None, bp_line=None, bp_file=None):
    """
    Run `code` in debugger with a break point.

    Parameters
    ----------
    code : str
        Code to execute.
    code_ns : dict
        A namespace in which `code` is executed.
    filename : str
        `code` is ran as if it is in `filename`.
    bp_line : int, optional
        Line number of the break point.
    bp_file : str, optional
        Path to the file in which break point is specified.
        `filename` is used if not given.

    Raises
    ------
    UsageError
        If the break point given by `bp_line` is not valid.

    """
    deb = self.shell.InteractiveTB.pdb
    if not deb:
        self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
        deb = self.shell.InteractiveTB.pdb

    # deb.checkline() fails if deb.curframe exists but is None; it can
    # handle it not existing. https://github.com/ipython/ipython/issues/10028
    if hasattr(deb, "curframe"):
        del deb.curframe

    # reset Breakpoint state, which is moronically kept
    # in a class
    bdb.Breakpoint.next = 1
    bdb.Breakpoint.bplist = {}
    bdb.Breakpoint.bpbynumber = [None]
    if bp_line is not None:
        # Set an initial breakpoint to stop execution
        maxtries = 10
        bp_file = bp_file or filename
        checkline = deb.checkline(bp_file, bp_line)
        if not checkline:
            for bp in range(bp_line + 1, bp_line + maxtries + 1):
                if deb.checkline(bp_file, bp):
                    break
            else:
                msg = (
                    "\nI failed to find a valid line to set "
                    "a breakpoint\n"
                    "after trying up to line: %s.\n"
                    "Please set a valid breakpoint manually "
                    "with the -b option." % bp
                )
                raise UsageError(msg)
        # if we find a good linenumber, set the breakpoint
        deb.do_break("%s:%s" % (bp_file, bp_line))

    if filename:
        # Mimic Pdb._runscript(...)
        deb._wait_for_mainpyfile = True
        deb.mainpyfile = deb.canonic(filename)

    # Start file run
    print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
    try:
        if filename:
            # save filename so it can be used by methods on the deb object
            deb._exec_filename = filename
        while True:
            try:
                deb.run(code, code_ns)
            except Restart:
                print("Restarting")
                if filename:
                    deb._wait_for_mainpyfile = True
                    deb.mainpyfile = deb.canonic(filename)
                continue
            else:
                break

    except:
        etype, value, tb = sys.exc_info()
        # Skip three frames in the traceback: the %run one,
        # one inside bdb.py, and the command-line typed by the
        # user (run by exec in pdb itself).
        self.shell.InteractiveTB(etype, value, tb, tb_offset=3)