[3.12] gh-90095: Make .pdbrc work properly and add some reasonable te… by gaogaotiantian · Pull Request #116661 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 13 additions & 33 deletions Lib/pdb.py
150 changes: 88 additions & 62 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1936,13 +1936,30 @@ def _run_pdb(self, pdb_args, commands, expected_returncode=0):
)
return stdout, stderr

def run_pdb_script(self, script, commands, expected_returncode=0):
def run_pdb_script(self, script, commands,
expected_returncode=0,
pdbrc=None,
remove_home=False):
"""Run 'script' lines with pdb and the pdb 'commands'."""
filename = 'main.py'
with open(filename, 'w') as f:
f.write(textwrap.dedent(script))

if pdbrc is not None:
with open('.pdbrc', 'w') as f:
f.write(textwrap.dedent(pdbrc))
self.addCleanup(os_helper.unlink, '.pdbrc')
self.addCleanup(os_helper.unlink, filename)
return self._run_pdb([filename], commands, expected_returncode)

homesave = None
if remove_home:
homesave = os.environ.pop('HOME', None)
try:
stdout, stderr = self._run_pdb([filename], commands, expected_returncode)
finally:
if homesave is not None:
os.environ['HOME'] = homesave
return stdout, stderr

def run_pdb_module(self, script, commands):
"""Runs the script code as part of a module"""
Expand Down Expand Up @@ -2182,37 +2199,80 @@ def test_issue26053(self):
self.assertRegex(res, "Restarting .* with arguments:\na b c")
self.assertRegex(res, "Restarting .* with arguments:\nd e f")

def test_readrc_kwarg(self):
def test_pdbrc_basic(self):
script = textwrap.dedent("""
import pdb; pdb.Pdb(readrc=False).set_trace()
a = 1
b = 2
""")

print('hello')
pdbrc = textwrap.dedent("""
# Comments should be fine
n
p f"{a+8=}"
""")

save_home = os.environ.pop('HOME', None)
try:
with os_helper.temp_cwd():
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,
)
with proc:
stdout, stderr = proc.communicate(b'q\n')
self.assertNotIn(b"NameError: name 'invalid' is not defined",
stdout)
stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
self.assertIn("a+8=9", stdout)

finally:
if save_home is not None:
os.environ['HOME'] = save_home
def test_pdbrc_alias(self):
script = textwrap.dedent("""
class A:
def __init__(self):
self.attr = 1
a = A()
b = 2
""")

pdbrc = textwrap.dedent("""
alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")
until 6
pi a
""")

stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
self.assertIn("a.attr = 1", stdout)

def test_pdbrc_semicolon(self):
script = textwrap.dedent("""
class A:
def __init__(self):
self.attr = 1
a = A()
b = 2
""")

pdbrc = textwrap.dedent("""
b 5;;c;;n
""")

stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
self.assertIn("-> b = 2", stdout)

def test_pdbrc_commands(self):
script = textwrap.dedent("""
class A:
def __init__(self):
self.attr = 1
a = A()
b = 2
""")

pdbrc = textwrap.dedent("""
b 6
commands 1 ;; p a;; end
c
""")

stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
self.assertIn("<__main__.A object at", stdout)

def test_readrc_kwarg(self):
script = textwrap.dedent("""
print('hello')
""")

stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc='invalid', remove_home=True)
self.assertIn("NameError: name 'invalid' is not defined", stdout)

def test_readrc_homedir(self):
save_home = os.environ.pop("HOME", None)
Expand All @@ -2227,40 +2287,6 @@ def test_readrc_homedir(self):
if save_home is not None:
os.environ["HOME"] = save_home

def test_read_pdbrc_with_ascii_encoding(self):
script = textwrap.dedent("""
import pdb; pdb.Pdb().set_trace()
print('hello')
""")
save_home = os.environ.pop('HOME', None)
try:
with os_helper.temp_cwd():
with open('.pdbrc', 'w', encoding='utf-8') as f:
f.write("Fran\u00E7ais")

with open('main.py', 'w', encoding='utf-8') as f:
f.write(script)

cmd = [sys.executable, 'main.py']
env = {'PYTHONIOENCODING': 'ascii'}
if sys.platform == 'win32':
env['PYTHONLEGACYWINDOWSSTDIO'] = 'non-empty-string'
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
env={**os.environ, **env}
)
with proc:
stdout, stderr = proc.communicate(b'c\n')
self.assertIn(b"UnicodeEncodeError: \'ascii\' codec can\'t encode character "
b"\'\\xe7\' in position 21: ordinal not in range(128)", stderr)

finally:
if save_home is not None:
os.environ['HOME'] = save_home

def test_header(self):
stdout = StringIO()
header = 'Nobody expects... blah, blah, blah'
Expand Down