[Python-checkins] r83287 - in python/branches/py3k: Doc/library/pdb.rst Lib/pdb.py Lib/test/test_pdb.py Misc/ACKS Misc/NEWS

georg.brandl python-checkins at python.org
Fri Jul 30 19:04:28 CEST 2010


Author: georg.brandl
Date: Fri Jul 30 19:04:28 2010
New Revision: 83287

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

Modified:
   python/branches/py3k/Doc/library/pdb.rst
   python/branches/py3k/Lib/pdb.py
   python/branches/py3k/Lib/test/test_pdb.py
   python/branches/py3k/Misc/ACKS
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/pdb.rst
==============================================================================
--- python/branches/py3k/Doc/library/pdb.rst	(original)
+++ python/branches/py3k/Doc/library/pdb.rst	Fri Jul 30 19:04:28 2010
@@ -368,6 +368,12 @@
    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 @@
 
    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]]

Modified: python/branches/py3k/Lib/pdb.py
==============================================================================
--- python/branches/py3k/Lib/pdb.py	(original)
+++ python/branches/py3k/Lib/pdb.py	Fri Jul 30 19:04:28 2010
@@ -74,6 +74,8 @@
 import re
 import pprint
 import traceback
+import inspect
+import types
 
 
 class Restart(Exception):
@@ -1028,25 +1030,62 @@
         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 @@
 _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__

Modified: python/branches/py3k/Lib/test/test_pdb.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pdb.py	(original)
+++ python/branches/py3k/Lib/test/test_pdb.py	Fri Jul 30 19:04:28 2010
@@ -257,6 +257,105 @@
     """
 
 
+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.
 

Modified: python/branches/py3k/Misc/ACKS
==============================================================================
--- python/branches/py3k/Misc/ACKS	(original)
+++ python/branches/py3k/Misc/ACKS	Fri Jul 30 19:04:28 2010
@@ -180,6 +180,7 @@
 Joaquin Cuenca Abela
 John Cugini
 Tom Culliton
+Antonio Cuni
 Brian Curtin
 Lisandro Dalcin
 Andrew Dalke

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Fri Jul 30 19:04:28 2010
@@ -475,6 +475,15 @@
 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.
 


More information about the Python-checkins mailing list