]> granicus.if.org Git - python/commitdiff
Merged revisions 72322 via svnmerge from
authorGeorg Brandl <georg@python.org>
Tue, 5 May 2009 09:00:19 +0000 (09:00 +0000)
committerGeorg Brandl <georg@python.org>
Tue, 5 May 2009 09:00:19 +0000 (09:00 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r72322 | georg.brandl | 2009-05-05 10:54:11 +0200 (Di, 05 Mai 2009) | 1 line

  #5142: add module skipping feature to pdb.
........

Doc/library/pdb.rst
Lib/bdb.py
Lib/pdb.py
Lib/test/test_pdb.py [new file with mode: 0644]
Misc/NEWS

index 63ade97dfefa0e885c6f4d376400c02362c6856d..0b29c2cd9697279b53b8cbe8839eba3bfbf49072 100644 (file)
@@ -1,4 +1,3 @@
-
 .. _debugger:
 
 :mod:`pdb` --- The Python Debugger
@@ -50,7 +49,16 @@ after normal exit of the program), pdb will restart the program. Automatic
 restarting preserves pdb's state (such as breakpoints) and in most cases is more
 useful than quitting the debugger upon program's exit.
 
-Typical usage to inspect a crashed program is::
+The typical usage to break into the debugger from a running program is to
+insert ::
+
+   import pdb; pdb.set_trace()
+
+at the location you want to break into the debugger.  You can then step through
+the code following this statement, and continue running without debugger using
+the ``c`` command.
+
+The typical usage to inspect a crashed program is::
 
    >>> import pdb
    >>> import mymodule
@@ -67,10 +75,10 @@ Typical usage to inspect a crashed program is::
    -> print(spam)
    (Pdb)
 
+
 The module defines the following functions; each enters the debugger in a
 slightly different way:
 
-
 .. function:: run(statement[, globals[, locals]])
 
    Execute the *statement* (given as a string) under debugger control.  The
@@ -113,7 +121,38 @@ slightly different way:
 
 .. function:: pm()
 
-   Enter post-mortem debugging of the traceback found in ``sys.last_traceback``.
+   Enter post-mortem debugging of the traceback found in
+   :data:`sys.last_traceback`.
+
+
+The ``run_*`` functions and :func:`set_trace` are aliases for instantiating the
+:class:`Pdb` class and calling the method of the same name.  If you want to
+access further features, you have to do this yourself:
+
+.. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None)
+
+   :class:`Pdb` is the debugger class.
+
+   The *completekey*, *stdin* and *stdout* arguments are passed to the
+   underlying :class:`cmd.Cmd` class; see the description there.
+
+   The *skip* argument, if given, must be an iterable of glob-style module name
+   patterns.  The debugger will not step into frames that originate in a module
+   that matches one of these patterns. [1]_
+
+   Example call to enable tracing with *skip*::
+
+      import pdb; pdb.Pdb(skip=['django.*']).set_trace()
+
+   .. versionadded:: 2.7
+      The *skip* argument.
+
+   .. method:: run(statement[, globals[, locals]])
+               runeval(expression[, globals[, locals]])
+               runcall(function[, argument, ...])
+               set_trace()
+
+      See the documentation for the functions explained above.
 
 
 .. _debugger-commands:
@@ -336,3 +375,9 @@ run [*args* ...]
 
 q(uit)
    Quit from the debugger. The program being executed is aborted.
+
+
+.. rubric:: Footnotes
+
+.. [1] Whether a frame is considered to originate in a certain module
+       is determined by the ``__name__`` in the frame globals.
index 6dc54eda4bbf5d4a156fbba7a20b0b071d967b53..3b4f99170bdfcdfc0fc2bddddb3ea538ec8d33d2 100644 (file)
@@ -1,5 +1,6 @@
 """Debugger basics"""
 
+import fnmatch
 import sys
 import os
 import types
@@ -19,7 +20,8 @@ class Bdb:
     The standard debugger class (pdb.Pdb) is an example.
     """
 
-    def __init__(self):
+    def __init__(self, skip=None):
+        self.skip = set(skip) if skip else None
         self.breaks = {}
         self.fncache = {}
 
@@ -94,9 +96,18 @@ class Bdb:
     # methods, but they may if they want to redefine the
     # definition of stopping and breakpoints.
 
+    def is_skipped_module(self, module_name):
+        for pattern in self.skip:
+            if fnmatch.fnmatch(module_name, pattern):
+                return True
+        return False
+
     def stop_here(self, frame):
         # (CT) stopframe may now also be None, see dispatch_call.
         # (CT) the former test for None is therefore removed from here.
+        if self.skip and \
+               self.is_skipped_module(frame.f_globals.get('__name__')):
+            return False
         if frame is self.stopframe:
             return frame.f_lineno >= self.stoplineno
         while frame is not None and frame is not self.stopframe:
index 22fc4c53797d8c5e1963c9c1a0941aa05db725e8..c9c66c53c53685ba673ab579240ed718a36d569d 100755 (executable)
@@ -58,8 +58,8 @@ line_prefix = '\n-> '   # Probably a better default
 
 class Pdb(bdb.Bdb, cmd.Cmd):
 
-    def __init__(self, completekey='tab', stdin=None, stdout=None):
-        bdb.Bdb.__init__(self)
+    def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None):
+        bdb.Bdb.__init__(self, skip=skip)
         cmd.Cmd.__init__(self, completekey, stdin, stdout)
         if stdout:
             self.use_rawinput = 0
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
new file mode 100644 (file)
index 0000000..bcd4853
--- /dev/null
@@ -0,0 +1,99 @@
+# A test suite for pdb; at the moment, this only validates skipping of
+# specified test modules (RFE #5142).
+
+import imp
+import os
+import sys
+import doctest
+import tempfile
+
+from test import support
+# This little helper class is essential for testing pdb under doctest.
+from test.test_doctest import _FakeInput
+
+
+def test_pdb_skip_modules():
+    """This illustrates the simple case of module skipping.
+
+    >>> def skip_module():
+    ...     import string
+    ...     import pdb; pdb.Pdb(skip=['stri*']).set_trace()
+    ...     string.capwords('FOO')
+    >>> real_stdin = sys.stdin
+    >>> sys.stdin = _FakeInput([
+    ...    'step',
+    ...    'continue',
+    ...    ])
+
+    >>> try:
+    ...     skip_module()
+    ... finally:
+    ...     sys.stdin = real_stdin
+    > <doctest test.test_pdb.test_pdb_skip_modules[0]>(4)skip_module()
+    -> string.capwords('FOO')
+    (Pdb) step
+    --Return--
+    > <doctest test.test_pdb.test_pdb_skip_modules[0]>(4)skip_module()->None
+    -> string.capwords('FOO')
+    (Pdb) continue
+"""
+
+
+# Module for testing skipping of module that makes a callback
+mod = imp.new_module('module_to_skip')
+exec('def foo_pony(callback): x = 1; callback(); return None', mod.__dict__)
+
+
+def test_pdb_skip_modules_with_callback():
+    """This illustrates skipping of modules that call into other code.
+
+    >>> def skip_module():
+    ...     def callback():
+    ...         return None
+    ...     import pdb;pdb.Pdb(skip=['module_to_skip*']).set_trace()
+    ...     mod.foo_pony(callback)
+    >>> real_stdin = sys.stdin
+    >>> sys.stdin = _FakeInput([
+    ...    'step',
+    ...    'step',
+    ...    'step',
+    ...    'step',
+    ...    'step',
+    ...    'continue',
+    ...    ])
+
+    >>> try:
+    ...     skip_module()
+    ... finally:
+    ...     sys.stdin = real_stdin
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(5)skip_module()
+    -> mod.foo_pony(callback)
+    (Pdb) step
+    --Call--
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(2)callback()
+    -> def callback():
+    (Pdb) step
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(3)callback()
+    -> return None
+    (Pdb) step
+    --Return--
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(3)callback()->None
+    -> return None
+    (Pdb) step
+    --Return--
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(5)skip_module()->None
+    -> mod.foo_pony(callback)
+    (Pdb) step
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[3]>(4)<module>()
+    -> sys.stdin = real_stdin
+    (Pdb) continue
+"""
+
+
+def test_main():
+    from test import test_pdb
+    support.run_doctest(test_pdb, verbosity=True)
+
+
+if __name__ == '__main__':
+    test_main()
index 8edd8456d5cafa89e153d619afc133736b376e0f..d388be1e6dd588cdcddcd39daa43ba85a25ca098 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -118,6 +118,8 @@ Installation
 Library
 -------
 
+- Issue #5142: Add the ability to skip modules while stepping to pdb.
+
 - Issue #1309567: Fix linecache behavior of stripping subdirectories when
   looking for files given by a relative filename.