summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/pdb.py75
-rw-r--r--Lib/test/test_pdb.py99
2 files changed, 157 insertions, 17 deletions
diff --git a/Lib/pdb.py b/Lib/pdb.py
index 28e29d3..7b444b1 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -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.