Issue #18401: pdb tests don't read ~/.pdbrc anymore

Patch by Martin Matusiak and Sam Kimbrel.
This commit is contained in:
Łukasz Langa 2016-09-09 22:21:17 -07:00
parent a1fd0789ed
commit 2eb6eca3e5
4 changed files with 78 additions and 30 deletions

View 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: access further features, you have to do this yourself:
.. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \ .. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \
nosigint=False) nosigint=False, readrc=True)
:class:`Pdb` is the debugger class. :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 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. 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*:: Example call to enable tracing with *skip*::
import pdb; pdb.Pdb(skip=['django.*']).set_trace() 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 The *nosigint* argument. Previously, a SIGINT handler was never set by
Pdb. Pdb.
.. versionadded:: 3.5
The *readrc* argument.
.. method:: run(statement, globals=None, locals=None) .. method:: run(statement, globals=None, locals=None)
runeval(expression, globals=None, locals=None) runeval(expression, globals=None, locals=None)
runcall(function, *args, **kwds) runcall(function, *args, **kwds)

View File

@ -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 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 debugger prompt. This is particularly useful for aliases. If both
files exist, the one in the home directory is read first and aliases 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 Aside from aliases, the debugger is not directly programmable; but it
is implemented as a class from which you can derive your own debugger 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): class Pdb(bdb.Bdb, cmd.Cmd):
def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
nosigint=False): nosigint=False, readrc=True):
bdb.Bdb.__init__(self, skip=skip) bdb.Bdb.__init__(self, skip=skip)
cmd.Cmd.__init__(self, completekey, stdin, stdout) cmd.Cmd.__init__(self, completekey, stdin, stdout)
if stdout: if stdout:
@ -158,6 +159,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
# Read $HOME/.pdbrc and ./.pdbrc # Read $HOME/.pdbrc and ./.pdbrc
self.rcLines = [] self.rcLines = []
if readrc:
if 'HOME' in os.environ: if 'HOME' in os.environ:
envHome = os.environ['HOME'] envHome = os.environ['HOME']
try: try:

View File

@ -1,8 +1,10 @@
# A test suite for pdb; not very comprehensive at the moment. # A test suite for pdb; not very comprehensive at the moment.
import doctest import doctest
import os
import pdb import pdb
import sys import sys
import tempfile
import types import types
import unittest import unittest
import subprocess import subprocess
@ -34,7 +36,7 @@ def test_pdb_displayhook():
"""This tests the custom displayhook for pdb. """This tests the custom displayhook for pdb.
>>> def test_function(foo, bar): >>> def test_function(foo, bar):
... import pdb; pdb.Pdb(nosigint=True).set_trace() ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... pass ... pass
>>> with PdbTestInput([ >>> with PdbTestInput([
@ -74,7 +76,7 @@ def test_pdb_basic_commands():
... return foo.upper() ... return foo.upper()
>>> def test_function(): >>> 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') ... ret = test_function_2('baz')
... print(ret) ... print(ret)
@ -173,7 +175,7 @@ def test_pdb_breakpoint_commands():
"""Test basic commands related to breakpoints. """Test basic commands related to breakpoints.
>>> def test_function(): >>> def test_function():
... import pdb; pdb.Pdb(nosigint=True).set_trace() ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... print(1) ... print(1)
... print(2) ... print(2)
... print(3) ... print(3)
@ -305,7 +307,7 @@ def test_list_commands():
... return foo ... return foo
>>> def test_function(): >>> 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') ... ret = test_function_2('baz')
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
@ -328,7 +330,7 @@ def test_list_commands():
-> ret = test_function_2('baz') -> ret = test_function_2('baz')
(Pdb) list (Pdb) list
1 def test_function(): 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') 3 -> ret = test_function_2('baz')
[EOF] [EOF]
(Pdb) step (Pdb) step
@ -391,7 +393,7 @@ def test_post_mortem():
... print('Exception!') ... print('Exception!')
>>> def test_function(): >>> 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()
... print('Not reached.') ... print('Not reached.')
@ -424,7 +426,7 @@ def test_post_mortem():
-> 1/0 -> 1/0
(Pdb) list (Pdb) list
1 def test_function(): 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() 3 -> test_function_2()
4 print('Not reached.') 4 print('Not reached.')
[EOF] [EOF]
@ -448,7 +450,7 @@ def test_pdb_skip_modules():
>>> def skip_module(): >>> def skip_module():
... import string ... 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') ... string.capwords('FOO')
>>> with PdbTestInput([ >>> with PdbTestInput([
@ -477,7 +479,7 @@ def test_pdb_skip_modules_with_callback():
>>> def skip_module(): >>> def skip_module():
... def callback(): ... def callback():
... return None ... 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) ... mod.foo_pony(callback)
>>> with PdbTestInput([ >>> with PdbTestInput([
@ -518,7 +520,7 @@ def test_pdb_continue_in_bottomframe():
"""Test that "continue" and "next" work properly in bottom frame (issue #5294). """Test that "continue" and "next" work properly in bottom frame (issue #5294).
>>> def test_function(): >>> 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.set_trace()
... inst.botframe = sys._getframe() # hackery to get the right botframe ... inst.botframe = sys._getframe() # hackery to get the right botframe
... print(1) ... print(1)
@ -558,7 +560,7 @@ def test_pdb_continue_in_bottomframe():
def pdb_invoke(method, arg): def pdb_invoke(method, arg):
"""Run pdb.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(): def test_pdb_run_with_incorrect_argument():
@ -607,7 +609,7 @@ def test_next_until_return_at_return_event():
... x = 2 ... x = 2
>>> def test_function(): >>> 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() ... test_function_2()
... test_function_2() ... test_function_2()
@ -673,7 +675,7 @@ def test_pdb_next_command_for_generator():
... yield 2 ... yield 2
>>> def test_function(): >>> def test_function():
... import pdb; pdb.Pdb(nosigint=True).set_trace() ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... it = test_gen() ... it = test_gen()
... try: ... try:
... if next(it) != 0: ... if next(it) != 0:
@ -733,7 +735,7 @@ def test_pdb_return_command_for_generator():
... yield 2 ... yield 2
>>> def test_function(): >>> def test_function():
... import pdb; pdb.Pdb(nosigint=True).set_trace() ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... it = test_gen() ... it = test_gen()
... try: ... try:
... if next(it) != 0: ... if next(it) != 0:
@ -788,7 +790,7 @@ def test_pdb_until_command_for_generator():
... yield 2 ... yield 2
>>> def test_function(): >>> 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(): ... for i in test_gen():
... print(i) ... print(i)
... print("finished") ... print("finished")
@ -830,7 +832,7 @@ def test_pdb_next_command_in_generator_for_loop():
... return 1 ... return 1
>>> def test_function(): >>> 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(): ... for i in test_gen():
... print('value', i) ... print('value', i)
... x = 123 ... x = 123
@ -875,7 +877,7 @@ def test_pdb_next_command_subiterator():
... return x ... return x
>>> def test_function(): >>> 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(): ... for i in test_gen():
... print('value', i) ... print('value', i)
... x = 123 ... x = 123
@ -1025,7 +1027,7 @@ class PdbTestCase(unittest.TestCase):
import pdb import pdb
def start_pdb(): def start_pdb():
pdb.Pdb().set_trace() pdb.Pdb(readrc=False).set_trace()
x = 1 x = 1
y = 1 y = 1
@ -1054,13 +1056,47 @@ class PdbTestCase(unittest.TestCase):
.format(expected, stdout)) .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): def tearDown(self):
support.unlink(support.TESTFN) support.unlink(support.TESTFN)
def load_tests(*args): def load_tests(*args):
from test import test_pdb from test import test_pdb
suites = [unittest.makeSuite(PdbTestCase), doctest.DocTestSuite(test_pdb)] suites = [unittest.makeSuite(PdbTestCase)]
return unittest.TestSuite(suites) return unittest.TestSuite(suites)

View File

@ -135,6 +135,10 @@ Core and Builtins
Library 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 - Issue #25969: Update the lib2to3 grammar to handle the unpacking
generalizations added in 3.5. generalizations added in 3.5.