diff options
Diffstat (limited to 'Lib')
-rwxr-xr-x | Lib/pdb.py | 75 | ||||
-rw-r--r-- | Lib/test/test_pdb.py | 99 |
2 files changed, 157 insertions, 17 deletions
@@ -74,6 +74,8 @@ import os import re import pprint import traceback +import inspect +import types class Restart(Exception): @@ -1028,25 +1030,62 @@ class Pdb(bdb.Bdb, cmd.Cmd): filename = self.curframe.f_code.co_filename breaklist = self.get_file_breaks(filename) try: - for lineno in range(first, last+1): - line = linecache.getline(filename, lineno, - self.curframe.f_globals) - if not line: - self.message('[EOF]') - break - else: - s = repr(lineno).rjust(3) - if len(s) < 4: s = s + ' ' - if lineno in breaklist: s = s + 'B' - else: s = s + ' ' - if lineno == self.curframe.f_lineno: - s = s + '->' - self.message(s + '\t' + line.rstrip()) - self.lineno = lineno + # XXX add tb_lineno feature + lines = linecache.getlines(filename, self.curframe.f_globals) + self._print_lines(lines[first-1:last], first, breaklist, + self.curframe.f_lineno, -1) + self.lineno = min(last, len(lines)) + if len(lines) < last: + self.message('[EOF]') except KeyboardInterrupt: pass do_l = do_list + def do_longlist(self, arg): + """longlist | ll + List the whole source code for the current function or frame. + """ + filename = self.curframe.f_code.co_filename + breaklist = self.get_file_breaks(filename) + try: + lines, lineno = inspect.getsourcelines(self.curframe) + except IOError as err: + self.error(err) + return + self._print_lines(lines, lineno, breaklist, self.curframe.f_lineno, -1) + do_ll = do_longlist + + def do_source(self, arg): + """source expression + Try to get source code for the given object and display it. + """ + try: + obj = self._getval(arg) + except: + return + try: + lines, lineno = inspect.getsourcelines(obj) + except (IOError, TypeError) as err: + self.error(err) + return + self._print_lines(lines, lineno, [], -1, -1) + + def _print_lines(self, lines, start, breaks, current, special): + """Print a range of lines.""" + for lineno, line in enumerate(lines, start): + s = str(lineno).rjust(3) + if len(s) < 4: + s += ' ' + if lineno in breaks: + s += 'B' + else: + s += ' ' + if lineno == current: + s += '->' + elif lineno == special: + s += '>>' + self.message(s + '\t' + line.rstrip()) + def do_whatis(self, arg): """whatis arg Print the type of the argument. @@ -1249,10 +1288,12 @@ class Pdb(bdb.Bdb, cmd.Cmd): _help_order = [ 'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable', 'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until', - 'jump', 'return', 'retval', 'run', 'continue', 'list', 'args', 'print', - 'whatis', 'alias', 'unalias', 'quit', + 'jump', 'return', 'retval', 'run', 'continue', 'list', 'longlist', + 'args', 'print', 'pp', 'whatis', 'source', 'alias', 'unalias', + 'debug', 'quit', ] +docs = set() for _command in _help_order: __doc__ += getattr(Pdb, 'do_' + _command).__doc__.strip() + '\n\n' __doc__ += Pdb.help_exec.__doc__ diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index aab6962..b2a441d 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -257,6 +257,105 @@ def test_pdb_breakpoint_commands(): """ +def do_nothing(): + pass + +def do_something(): + print(42) + +def test_list_commands(): + """Test the list and source commands of pdb. + + >>> def test_function_2(foo): + ... import test_pdb + ... test_pdb.do_nothing() + ... 'some...' + ... 'more...' + ... 'code...' + ... 'to...' + ... 'make...' + ... 'a...' + ... 'long...' + ... 'listing...' + ... 'useful...' + ... '...' + ... '...' + ... return foo + + >>> def test_function(): + ... import pdb; pdb.Pdb().set_trace() + ... ret = test_function_2('baz') + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'list', # list first function + ... 'step', # step into second function + ... 'list', # list second function + ... 'list', # continue listing to EOF + ... 'list 1,3', # list specific lines + ... 'list x', # invalid argument + ... 'next', # step to import + ... 'next', # step over import + ... 'step', # step into do_nothing + ... 'longlist', # list all lines + ... 'source do_something', # list all lines of function + ... 'continue', + ... ]): + ... test_function() + > <doctest test.test_pdb.test_list_commands[1]>(3)test_function() + -> ret = test_function_2('baz') + (Pdb) list + 1 def test_function(): + 2 import pdb; pdb.Pdb().set_trace() + 3 -> ret = test_function_2('baz') + [EOF] + (Pdb) step + --Call-- + > <doctest test.test_pdb.test_list_commands[0]>(1)test_function_2() + -> def test_function_2(foo): + (Pdb) list + 1 -> def test_function_2(foo): + 2 import test_pdb + 3 test_pdb.do_nothing() + 4 'some...' + 5 'more...' + 6 'code...' + 7 'to...' + 8 'make...' + 9 'a...' + 10 'long...' + 11 'listing...' + (Pdb) list + 12 'useful...' + 13 '...' + 14 '...' + 15 return foo + [EOF] + (Pdb) list 1,3 + 1 -> def test_function_2(foo): + 2 import test_pdb + 3 test_pdb.do_nothing() + (Pdb) list x + *** ... + (Pdb) next + > <doctest test.test_pdb.test_list_commands[0]>(2)test_function_2() + -> import test_pdb + (Pdb) next + > <doctest test.test_pdb.test_list_commands[0]>(3)test_function_2() + -> test_pdb.do_nothing() + (Pdb) step + --Call-- + > /home/gbr/devel/python/Lib/test/test_pdb.py(260)do_nothing() + -> def do_nothing(): + (Pdb) longlist + ... -> def do_nothing(): + ... pass + (Pdb) source do_something + ... def do_something(): + ... print(42) + (Pdb) continue + """ + + def test_pdb_skip_modules(): """This illustrates the simple case of module skipping. |