Add "longlist" and "source" commands, ideas borrowed from pdb++ by Antonio Cuni.

This commit is contained in:
Georg Brandl 2010-07-30 17:04:28 +00:00
parent 0d08962659
commit e59ca2afe3
5 changed files with 179 additions and 17 deletions

View File

@ -368,6 +368,12 @@ by the local file.
list 11 lines around at that line. With two arguments, list the given range;
if the second argument is less than the first, it is interpreted as a count.
.. pdbcommand:: ll | longlist
List all source code for the current function or frame.
.. versionadded:: 3.2
.. pdbcommand:: a(rgs)
Print the argument list of the current function.
@ -385,6 +391,12 @@ by the local file.
Print the type of the *expression*.
.. pdbcommand:: source expression
Try to get source code for the given object and display it.
.. versionadded:: 3.2
.. _debugger-aliases:
.. pdbcommand:: alias [name [command]]

View File

@ -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__

View File

@ -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.

View File

@ -180,6 +180,7 @@ Drew Csillag
Joaquin Cuenca Abela
John Cugini
Tom Culliton
Antonio Cuni
Brian Curtin
Lisandro Dalcin
Andrew Dalke

View File

@ -475,6 +475,15 @@ C-API
Library
-------
- The pdb command "source" has been added. It displays the source
code for a given object, if possible.
- The pdb command "longlist" has been added. It displays the whole
source code for the current function.
- Issue #1503502: Make pdb.Pdb easier to subclass by putting message
and error output into methods.
- Issue #809887: Make the output of pdb's breakpoint deletions more
consistent; emit a message when a breakpoint is enabled or disabled.