Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Fix recursive debugger #271

Merged
merged 3 commits into from
Feb 7, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 57 additions & 30 deletions spyder_kernels/customize/spydercustomize.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,18 +374,6 @@ def get_current_file_name():
return None


def get_debugger(filename):
"""Get a debugger for a given filename."""
debugger = pdb.Pdb()
filename = debugger.canonic(filename)
debugger._wait_for_mainpyfile = 1
debugger.mainpyfile = filename
debugger._user_requested_quit = 0
if os.name == 'nt':
filename = filename.replace('\\', '/')
return debugger, filename


def count_leading_empty_lines(cell):
"""Count the number of leading empty cells."""
if PY2:
Expand Down Expand Up @@ -583,6 +571,54 @@ def runfile(filename=None, args=None, wdir=None, namespace=None,
builtins.runfile = runfile


def enter_debugger(filename, continue_if_has_breakpoints, code_format):
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
"""Enter debugger. Code format should be a format that accept filename."""
if filename is None:
filename = get_current_file_name()
if filename is None:
return

kernel = get_ipython().kernel
recursive = kernel.is_debugging()
if recursive:
parent_debugger = kernel._pdb_obj
sys.settrace(None)
globals = parent_debugger.curframe.f_globals
locals = parent_debugger.curframe_locals
# Create child debugger
debugger = parent_debugger.__class__(
completekey=parent_debugger.completekey,
stdin=parent_debugger.stdin, stdout=parent_debugger.stdout)
debugger.use_rawinput = parent_debugger.use_rawinput
debugger.prompt = "(%s) " % parent_debugger.prompt.strip()
else:
debugger = pdb.Pdb()

filename = debugger.canonic(filename)
debugger._wait_for_mainpyfile = True
debugger.mainpyfile = filename
debugger.continue_if_has_breakpoints = continue_if_has_breakpoints
debugger._user_requested_quit = False

if os.name == 'nt':
filename = filename.replace('\\', '/')

code = code_format.format(repr(filename))

if recursive:
# Enter recursive debugger
parent_debugger.message("ENTERING RECURSIVE DEBUGGER")
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
sys.call_tracing(debugger.run, (code, globals, locals))
parent_debugger.message("LEAVING RECURSIVE DEBUGGER")
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
# Reset parent debugger
sys.settrace(parent_debugger.trace_dispatch)
parent_debugger.lastcmd = debugger.lastcmd
kernel._register_pdb_session(parent_debugger)
else:
# The breakpoint might not be in the cell
debugger.run(code)


def debugfile(filename=None, args=None, wdir=None, post_mortem=False,
current_namespace=False):
"""
Expand All @@ -593,14 +629,11 @@ def debugfile(filename=None, args=None, wdir=None, post_mortem=False,
"""
# Tell IPython to hide this frame (>7.16)
__tracebackhide__ = True
if filename is None:
filename = get_current_file_name()
if filename is None:
return
debugger, filename = get_debugger(filename)
debugger.continue_if_has_breakpoints = True
debugger.run("runfile(%r, args=%r, wdir=%r, current_namespace=%r)" % (
filename, args, wdir, current_namespace))
enter_debugger(
filename, True,
"runfile({}" +
", args=%r, wdir=%r, current_namespace=%r)" % (
args, wdir, current_namespace))


builtins.debugfile = debugfile
Expand Down Expand Up @@ -673,16 +706,10 @@ def debugcell(cellname, filename=None, post_mortem=False):
"""Debug a cell."""
# Tell IPython to hide this frame (>7.16)
__tracebackhide__ = True
if filename is None:
filename = get_current_file_name()
if filename is None:
return

debugger, filename = get_debugger(filename)
# The breakpoint might not be in the cell
debugger.continue_if_has_breakpoints = False
debugger.run("runcell({}, {})".format(
repr(cellname), repr(filename)))
enter_debugger(
filename, False,
"runcell({}, ".format(repr(cellname)) +
"{})")


builtins.debugcell = debugcell
Expand Down
2 changes: 1 addition & 1 deletion spyder_kernels/customize/spyderpdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ def user_return(self, frame, return_value):
if (self.mainpyfile != self.canonic(frame.f_code.co_filename)
or frame.f_lineno <= 0):
return
self._wait_for_mainpyfile = 0
self._wait_for_mainpyfile = False
super(SpyderPdb, self).user_return(frame, return_value)

def _cmdloop(self):
Expand Down