diff -r b74897b69184 Lib/pdb.py --- a/Lib/pdb.py Wed Nov 02 20:33:07 2016 -0400 +++ b/Lib/pdb.py Sat Nov 05 17:40:41 2016 +0100 @@ -80,6 +80,7 @@ import inspect import traceback import linecache +import types class Restart(Exception): @@ -1584,6 +1585,52 @@ def set_trace(): Pdb().set_trace(sys._getframe().f_back) +def _compile(source, globs=None, locs=None): + class Loader: + def get_source(self, fname): + return source + + f = sys._getframe().f_back.f_back + g = f.f_globals if globs is None else globs + l = f.f_locals if locs is None else locs + trace = sys.gettrace() + if isinstance(trace, types.MethodType) and trace.__module__ == 'bdb': + _pdb = trace.__self__ + skip = _pdb.skip + _pdb.skip = set(['pdb']) if skip is None else skip.update(['pdb']) + # When the last frame where pdb stopped is in pdb, set stopframe to + # None otherwise stopframe may remain set to this frame until pdb + # exits (unless stopped at a breakpoint). + if (_pdb.stopframe and + _pdb.stopframe.f_globals.get('__name__') == 'pdb'): + _pdb.stopframe = None + + if isinstance(source, (str, bytes)): + globs = {} + globs.update(g) + globs['__loader__'] = Loader() + globs['__name__'] = 'pdb_tmp_script' + g = globs + code = compile(source, 'pdb_tmp_script.py', 'exec') + else: + code =source + else: + code = compile(source, '', 'exec') + return code, g, l + +def exec_script(source, globs=None, locs=None): + """Execute Python code while enabling the source debugging of this code. + + 'source' is source debugged if this is a string and a pdb instance is + running. The source debugging of the pdb module itself is skipped by the + pdb instance upon the first invocation of this function and on the + following invocations pdb will step direcly into 'source', skipping the + statements executed by exec_script() itself. + + """ + code, globals, locals = _compile(source, globs, locs) + exec(code, globals, locals) + # Post-Mortem interface def post_mortem(t=None):