Issue #18401: pdb tests don't read ~/.pdbrc anymore
Patch by Martin Matusiak and Sam Kimbrel.
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index d77de2e..4b912f7 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -144,7 +144,7 @@
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 @@
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 @@
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)
diff --git a/Lib/pdb.py b/Lib/pdb.py
index b11ac0a..7eb78b9 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -52,7 +52,8 @@
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 @@
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 @@
# 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
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
index a63ccd8..c39cc97 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -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 @@
"""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 @@
... 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 @@
"""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 @@
... 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 @@
-> 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 @@
... 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 @@
-> 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 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 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 @@
"""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 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 @@
... 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 @@
... 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 @@
... 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 @@
... 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 @@
... 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 @@
... 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 @@
import pdb
def start_pdb():
- pdb.Pdb().set_trace()
+ pdb.Pdb(readrc=False).set_trace()
x = 1
y = 1
@@ -1054,13 +1056,47 @@
.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)
diff --git a/Misc/NEWS b/Misc/NEWS
index 5628dc9..defb4f9 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -135,6 +135,10 @@
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.