]> granicus.if.org Git - python/commitdiff
Issue #18401: pdb tests don't read ~/.pdbrc anymore
authorŁukasz Langa <lukasz@langa.pl>
Sat, 10 Sep 2016 05:21:17 +0000 (22:21 -0700)
committerŁukasz Langa <lukasz@langa.pl>
Sat, 10 Sep 2016 05:21:17 +0000 (22:21 -0700)
Patch by Martin Matusiak and Sam Kimbrel.

Doc/library/pdb.rst
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS

index d77de2e2bb976461d90e881b09e9b1888bb4abf9..4b912f767f30ff36a3b25bfc3d4024970b3d623c 100644 (file)
@@ -144,7 +144,7 @@ The ``run*`` functions and :func:`set_trace` are aliases for instantiating the
 access further features, you have to do this yourself:
 
 .. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \
-               nosigint=False)
+               nosigint=False, readrc=True)
 
    :class:`Pdb` is the debugger class.
 
@@ -160,6 +160,9 @@ access further features, you have to do this yourself:
    This allows you to break into the debugger again by pressing :kbd:`Ctrl-C`.  If you
    want Pdb not to touch the SIGINT handler, set *nosigint* to true.
 
+   The *readrc* argument defaults to True and controls whether Pdb will load
+   .pdbrc files from the filesystem.
+
    Example call to enable tracing with *skip*::
 
       import pdb; pdb.Pdb(skip=['django.*']).set_trace()
@@ -171,6 +174,9 @@ access further features, you have to do this yourself:
       The *nosigint* argument.  Previously, a SIGINT handler was never set by
       Pdb.
 
+   .. versionadded:: 3.5
+      The *readrc* argument.
+
    .. method:: run(statement, globals=None, locals=None)
                runeval(expression, globals=None, locals=None)
                runcall(function, *args, **kwds)
index b11ac0abd1682e3833fca0f489486e6595a2c1fa..7eb78b922ae731e548e005bbab6fc253bcf2c43d 100755 (executable)
@@ -52,7 +52,8 @@ If a file ".pdbrc" exists in your home directory or in the current
 directory, it is read in and executed as if it had been typed at the
 debugger prompt.  This is particularly useful for aliases.  If both
 files exist, the one in the home directory is read first and aliases
-defined there can be overridden by the local file.
+defined there can be overridden by the local file.  This behavior can be
+disabled by passing the "readrc=False" argument to the Pdb constructor.
 
 Aside from aliases, the debugger is not directly programmable; but it
 is implemented as a class from which you can derive your own debugger
@@ -135,7 +136,7 @@ line_prefix = '\n-> '   # Probably a better default
 class Pdb(bdb.Bdb, cmd.Cmd):
 
     def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
-                 nosigint=False):
+                 nosigint=False, readrc=True):
         bdb.Bdb.__init__(self, skip=skip)
         cmd.Cmd.__init__(self, completekey, stdin, stdout)
         if stdout:
@@ -158,18 +159,19 @@ class Pdb(bdb.Bdb, cmd.Cmd):
 
         # Read $HOME/.pdbrc and ./.pdbrc
         self.rcLines = []
-        if 'HOME' in os.environ:
-            envHome = os.environ['HOME']
+        if readrc:
+            if 'HOME' in os.environ:
+                envHome = os.environ['HOME']
+                try:
+                    with open(os.path.join(envHome, ".pdbrc")) as rcFile:
+                        self.rcLines.extend(rcFile)
+                except OSError:
+                    pass
             try:
-                with open(os.path.join(envHome, ".pdbrc")) as rcFile:
+                with open(".pdbrc") as rcFile:
                     self.rcLines.extend(rcFile)
             except OSError:
                 pass
-        try:
-            with open(".pdbrc") as rcFile:
-                self.rcLines.extend(rcFile)
-        except OSError:
-            pass
 
         self.commands = {} # associates a command list to breakpoint numbers
         self.commands_doprompt = {} # for each bp num, tells if the prompt
index a63ccd83ca89c2460e6f780ff555f77b98f3d7d5..c39cc97fe1de0c464c3717822158f3c47e3bb054 100644 (file)
@@ -1,8 +1,10 @@
 # A test suite for pdb; not very comprehensive at the moment.
 
 import doctest
+import os
 import pdb
 import sys
+import tempfile
 import types
 import unittest
 import subprocess
@@ -34,7 +36,7 @@ def test_pdb_displayhook():
     """This tests the custom displayhook for pdb.
 
     >>> def test_function(foo, bar):
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     pass
 
     >>> with PdbTestInput([
@@ -74,7 +76,7 @@ def test_pdb_basic_commands():
     ...     return foo.upper()
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     ret = test_function_2('baz')
     ...     print(ret)
 
@@ -173,7 +175,7 @@ def test_pdb_breakpoint_commands():
     """Test basic commands related to breakpoints.
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     print(1)
     ...     print(2)
     ...     print(3)
@@ -305,7 +307,7 @@ def test_list_commands():
     ...     return foo
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     ret = test_function_2('baz')
 
     >>> with PdbTestInput([  # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
@@ -328,7 +330,7 @@ def test_list_commands():
     -> ret = test_function_2('baz')
     (Pdb) list
       1         def test_function():
-      2             import pdb; pdb.Pdb(nosigint=True).set_trace()
+      2             import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
       3  ->         ret = test_function_2('baz')
     [EOF]
     (Pdb) step
@@ -391,7 +393,7 @@ def test_post_mortem():
     ...         print('Exception!')
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     test_function_2()
     ...     print('Not reached.')
 
@@ -424,7 +426,7 @@ def test_post_mortem():
     -> 1/0
     (Pdb) list
       1         def test_function():
-      2             import pdb; pdb.Pdb(nosigint=True).set_trace()
+      2             import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
       3  ->         test_function_2()
       4             print('Not reached.')
     [EOF]
@@ -448,7 +450,7 @@ def test_pdb_skip_modules():
 
     >>> def skip_module():
     ...     import string
-    ...     import pdb; pdb.Pdb(skip=['stri*'], nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(skip=['stri*'], nosigint=True, readrc=False).set_trace()
     ...     string.capwords('FOO')
 
     >>> with PdbTestInput([
@@ -477,7 +479,7 @@ def test_pdb_skip_modules_with_callback():
     >>> def skip_module():
     ...     def callback():
     ...         return None
-    ...     import pdb; pdb.Pdb(skip=['module_to_skip*'], nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(skip=['module_to_skip*'], nosigint=True, readrc=False).set_trace()
     ...     mod.foo_pony(callback)
 
     >>> with PdbTestInput([
@@ -518,7 +520,7 @@ def test_pdb_continue_in_bottomframe():
     """Test that "continue" and "next" work properly in bottom frame (issue #5294).
 
     >>> def test_function():
-    ...     import pdb, sys; inst = pdb.Pdb(nosigint=True)
+    ...     import pdb, sys; inst = pdb.Pdb(nosigint=True, readrc=False)
     ...     inst.set_trace()
     ...     inst.botframe = sys._getframe()  # hackery to get the right botframe
     ...     print(1)
@@ -558,7 +560,7 @@ def test_pdb_continue_in_bottomframe():
 
 def pdb_invoke(method, arg):
     """Run pdb.method(arg)."""
-    getattr(pdb.Pdb(nosigint=True), method)(arg)
+    getattr(pdb.Pdb(nosigint=True, readrc=False), method)(arg)
 
 
 def test_pdb_run_with_incorrect_argument():
@@ -607,7 +609,7 @@ def test_next_until_return_at_return_event():
     ...     x = 2
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     test_function_2()
     ...     test_function_2()
     ...     test_function_2()
@@ -673,7 +675,7 @@ def test_pdb_next_command_for_generator():
     ...     yield 2
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     it = test_gen()
     ...     try:
     ...         if next(it) != 0:
@@ -733,7 +735,7 @@ def test_pdb_return_command_for_generator():
     ...     yield 2
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     it = test_gen()
     ...     try:
     ...         if next(it) != 0:
@@ -788,7 +790,7 @@ def test_pdb_until_command_for_generator():
     ...     yield 2
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     for i in test_gen():
     ...         print(i)
     ...     print("finished")
@@ -830,7 +832,7 @@ def test_pdb_next_command_in_generator_for_loop():
     ...     return 1
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     for i in test_gen():
     ...         print('value', i)
     ...     x = 123
@@ -875,7 +877,7 @@ def test_pdb_next_command_subiterator():
     ...     return x
 
     >>> def test_function():
-    ...     import pdb; pdb.Pdb(nosigint=True).set_trace()
+    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
     ...     for i in test_gen():
     ...         print('value', i)
     ...     x = 123
@@ -1025,7 +1027,7 @@ class PdbTestCase(unittest.TestCase):
                 import pdb
 
                 def start_pdb():
-                    pdb.Pdb().set_trace()
+                    pdb.Pdb(readrc=False).set_trace()
                     x = 1
                     y = 1
 
@@ -1054,13 +1056,47 @@ class PdbTestCase(unittest.TestCase):
             .format(expected, stdout))
 
 
+    def test_readrc_kwarg(self):
+        save_home = os.environ['HOME']
+        save_dir = os.getcwd()
+        script = """import pdb; pdb.Pdb(readrc=False).set_trace()
+
+print('hello')
+"""
+        del os.environ['HOME']
+        try:
+            with tempfile.TemporaryDirectory() as dirname:
+                os.chdir(dirname)
+                with open('.pdbrc', 'w') as f:
+                    f.write("invalid\n")
+
+                with open('main.py', 'w') as f:
+                    f.write(script)
+
+                cmd = [sys.executable, 'main.py']
+                proc = subprocess.Popen(
+                    cmd,
+                    stdout=subprocess.PIPE,
+                    stdin=subprocess.PIPE,
+                    stderr=subprocess.PIPE,
+                )
+                self.addCleanup(proc.stdout.close)
+                self.addCleanup(proc.stderr.close)
+                stdout, stderr = proc.communicate(b'q\n')
+                self.assertNotIn("NameError: name 'invalid' is not defined",
+                              stdout.decode())
+
+        finally:
+            os.environ['HOME'] = save_home
+            os.chdir(save_dir)
+
     def tearDown(self):
         support.unlink(support.TESTFN)
 
 
 def load_tests(*args):
     from test import test_pdb
-    suites = [unittest.makeSuite(PdbTestCase), doctest.DocTestSuite(test_pdb)]
+    suites = [unittest.makeSuite(PdbTestCase)]
     return unittest.TestSuite(suites)
 
 
index 5628dc9cd2ad58bd6e9a4ec81aa6b9c22e825d2c..defb4f9eb9edccde16f1cea971260e18b446d1b2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -135,6 +135,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #18401: Pdb now supports the 'readrc' keyword argument to control
+  whether .pdbrc files should be read.  Patch by Martin Matusiak and
+  Sam Kimbrel.
+
 - Issue #25969: Update the lib2to3 grammar to handle the unpacking
   generalizations added in 3.5.