From 8563a7052ccd98e6a381d361664ce567afd5eb6e Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Wed, 12 May 2021 01:26:30 +0200 Subject: bpo-28528: Fix pdb.checkline() attribute error when 'curframe' is None. (#25438) Co-authored-by: Thomas Kluyver --- Lib/pdb.py | 3 +- Lib/test/test_pdb.py | 38 ++++++++++++++++++++++ .../2021-04-29-00-48-00.bpo-28528.JLAVWj.rst | 2 ++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2021-04-29-00-48-00.bpo-28528.JLAVWj.rst diff --git a/Lib/pdb.py b/Lib/pdb.py index 98dc975..a888a0a 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -752,7 +752,8 @@ class Pdb(bdb.Bdb, cmd.Cmd): """ # this method should be callable before starting debugging, so default # to "no globals" if there is no current frame - globs = self.curframe.f_globals if hasattr(self, 'curframe') else None + frame = getattr(self, 'curframe', None) + globs = frame.f_globals if frame else None line = linecache.getline(filename, lineno, globs) if not line: self.message('End of file') diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 870eab4..cd096e7 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -9,6 +9,7 @@ import codecs import unittest import subprocess import textwrap +import linecache from contextlib import ExitStack from io import StringIO @@ -1807,10 +1808,47 @@ def bœr(): self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected) +class ChecklineTests(unittest.TestCase): + def setUp(self): + linecache.clearcache() # Pdb.checkline() uses linecache.getline() + + def tearDown(self): + os_helper.unlink(os_helper.TESTFN) + + def test_checkline_before_debugging(self): + with open(os_helper.TESTFN, "w") as f: + f.write("print(123)") + db = pdb.Pdb() + self.assertEqual(db.checkline(os_helper.TESTFN, 1), 1) + + def test_checkline_after_reset(self): + with open(os_helper.TESTFN, "w") as f: + f.write("print(123)") + db = pdb.Pdb() + db.reset() + self.assertEqual(db.checkline(os_helper.TESTFN, 1), 1) + + def test_checkline_is_not_executable(self): + with open(os_helper.TESTFN, "w") as f: + # Test for comments, docstrings and empty lines + s = textwrap.dedent(""" + # Comment + \"\"\" docstring \"\"\" + ''' docstring ''' + + """) + f.write(s) + db = pdb.Pdb() + num_lines = len(s.splitlines()) + 2 # Test for EOF + for lineno in range(num_lines): + self.assertFalse(db.checkline(os_helper.TESTFN, lineno)) + + def load_tests(*args): from test import test_pdb suites = [ unittest.makeSuite(PdbTestCase), + unittest.makeSuite(ChecklineTests), doctest.DocTestSuite(test_pdb) ] return unittest.TestSuite(suites) diff --git a/Misc/NEWS.d/next/Library/2021-04-29-00-48-00.bpo-28528.JLAVWj.rst b/Misc/NEWS.d/next/Library/2021-04-29-00-48-00.bpo-28528.JLAVWj.rst new file mode 100644 index 0000000..97731ad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-29-00-48-00.bpo-28528.JLAVWj.rst @@ -0,0 +1,2 @@ +Fix a bug in :mod:`pdb` where :meth:`~pdb.Pdb.checkline` raises +:exc:`AttributeError` if it is called after :meth:`~pdb.Pdb.reset`. -- cgit v0.12