diff --git a/spyder_kernels/customize/spydercustomize.py b/spyder_kernels/customize/spydercustomize.py index 1bf8cb25..db78e1c7 100644 --- a/spyder_kernels/customize/spydercustomize.py +++ b/spyder_kernels/customize/spydercustomize.py @@ -27,7 +27,7 @@ from spyder_kernels.comms.frontendcomm import CommError, frontend_request from spyder_kernels.customize.namespace_manager import NamespaceManager -from spyder_kernels.customize.spyderpdb import SpyderPdb +from spyder_kernels.customize.spyderpdb import SpyderPdb, enter_debugger from spyder_kernels.customize.umr import UserModuleReloader from spyder_kernels.py3compat import TimeoutError, PY2, _print, encode @@ -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: @@ -597,10 +585,12 @@ def debugfile(filename=None, args=None, wdir=None, post_mortem=False, 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 @@ -678,11 +668,10 @@ def debugcell(cellname, filename=None, post_mortem=False): 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 diff --git a/spyder_kernels/customize/spyderpdb.py b/spyder_kernels/customize/spyderpdb.py index 385453eb..d01b0f8f 100755 --- a/spyder_kernels/customize/spyderpdb.py +++ b/spyder_kernels/customize/spyderpdb.py @@ -7,8 +7,9 @@ """Spyder debugger.""" import bdb -import sys import logging +import os +import sys import traceback from collections import namedtuple @@ -512,7 +513,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): @@ -700,3 +701,44 @@ def runcall(self, *args, **kwds): """ with DebugWrapper(self): super(SpyderPdb, self).runcall(*args, **kwds) + + +def enter_debugger(filename, continue_if_has_breakpoints, code_format): + """Enter debugger. Code format should be a format that accept filename.""" + 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 = SpyderPdb( + 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 = SpyderPdb() + + 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 + sys.call_tracing(debugger.run, (code, globals, locals)) + # 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)