From 2b1ff97c8c9bbcb3ee22a2a5f4e38004b71abed0 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Tue, 18 Feb 2025 20:22:57 -0500 Subject: [PATCH 1/4] Support breakpoints for zipimport modules on pdb --- Lib/pdb.py | 12 ++++++++---- Lib/test/test_pdb.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Lib/pdb.py b/Lib/pdb.py index 4abf216b773780..f97c1b3019475b 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -1134,6 +1134,7 @@ def do_break(self, arg, temporary=False): filename = None lineno = None cond = None + module_globals = None comma = arg.find(',') if comma > 0: # parse stuff after comma: "condition" @@ -1179,6 +1180,7 @@ def do_break(self, arg, temporary=False): funcname = code.co_name lineno = find_first_executable_line(code) filename = code.co_filename + module_globals = func.__globals__ except: # last thing to try (ok, filename, ln) = self.lineinfo(arg) @@ -1190,8 +1192,9 @@ def do_break(self, arg, temporary=False): lineno = int(ln) if not filename: filename = self.defaultFile() + filename = self.canonic(filename) # Check for reasonable breakpoint - line = self.checkline(filename, lineno) + line = self.checkline(filename, lineno, module_globals) if line: # now set the break point err = self.set_break(filename, line, temporary, cond, funcname) @@ -1258,7 +1261,7 @@ def lineinfo(self, identifier): answer = find_function(item, self.canonic(fname)) return answer or failed - def checkline(self, filename, lineno): + def checkline(self, filename, lineno, module_globals=None): """Check whether specified line seems to be executable. Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank @@ -1267,8 +1270,9 @@ def checkline(self, filename, lineno): # this method should be callable before starting debugging, so default # to "no globals" if there is no current frame frame = getattr(self, 'curframe', None) - globs = frame.f_globals if frame else None - line = linecache.getline(filename, lineno, globs) + if module_globals is None: + module_globals = frame.f_globals if frame else None + line = linecache.getline(filename, lineno, module_globals) if not line: self.message('End of file') return 0 diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 4d371a6e754b96..678f6b2270f08e 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -11,6 +11,7 @@ import textwrap import linecache import zipapp +import zipfile from contextlib import ExitStack, redirect_stdout from io import StringIO @@ -4199,6 +4200,38 @@ def f(x): self.assertIn('42', stdout) self.assertIn('return x + 1', stdout) + def test_zipimport(self): + with os_helper.temp_dir() as temp_dir: + os.mkdir(os.path.join(temp_dir, 'source')) + zipmodule = textwrap.dedent( + """ + def bar(x): + return x + 1 + """ + ) + script = textwrap.dedent( + f""" + import sys; sys.path.insert(0, '{os.path.join(temp_dir, 'zipmodule.zip')}') + import foo + foo.bar(41) + """ + ) + + with zipfile.ZipFile(os.path.join(temp_dir, 'zipmodule.zip'), 'w') as zf: + zf.writestr('foo.py', zipmodule) + with open(os.path.join(temp_dir, 'script.py'), 'w') as f: + f.write(script) + + stdout, _ = self._run_pdb([os.path.join(temp_dir, 'script.py')], '\n'.join([ + 'n', + 'n', + 'b foo.bar', + 'c', + 'p x + x', + 'q' + ])) + self.assertIn('82', stdout) + class ChecklineTests(unittest.TestCase): def setUp(self): From e2b0d89108a8ba88a8f3426f6e1f47cb8e34a3b8 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 19 Feb 2025 01:29:18 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-02-19-01-29-16.gh-issue-57537.4tdVuK.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-02-19-01-29-16.gh-issue-57537.4tdVuK.rst diff --git a/Misc/NEWS.d/next/Library/2025-02-19-01-29-16.gh-issue-57537.4tdVuK.rst b/Misc/NEWS.d/next/Library/2025-02-19-01-29-16.gh-issue-57537.4tdVuK.rst new file mode 100644 index 00000000000000..40e4094cc5fccf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-19-01-29-16.gh-issue-57537.4tdVuK.rst @@ -0,0 +1 @@ +Support breakpoints for :mod:`zipimport` modules on :mod:`pdb` From 07ee8a22313d22d8cd241030db92e16eb5807f5c Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Tue, 18 Feb 2025 20:53:46 -0500 Subject: [PATCH 3/4] Fix test --- Lib/test/test_pdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 678f6b2270f08e..9439fc1c4a22f8 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4211,7 +4211,7 @@ def bar(x): ) script = textwrap.dedent( f""" - import sys; sys.path.insert(0, '{os.path.join(temp_dir, 'zipmodule.zip')}') + import sys; sys.path.insert(0, {repr(os.path.join(temp_dir, 'zipmodule.zip'))}) import foo foo.bar(41) """ From 6f2c415d34e54b3694701eb207ed62e8f7930a2c Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Wed, 19 Feb 2025 16:12:12 -0500 Subject: [PATCH 4/4] Clarify the target test result --- Lib/test/test_pdb.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 9439fc1c4a22f8..d253d7fe1e8109 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4205,15 +4205,15 @@ def test_zipimport(self): os.mkdir(os.path.join(temp_dir, 'source')) zipmodule = textwrap.dedent( """ - def bar(x): - return x + 1 + def bar(): + pass """ ) script = textwrap.dedent( f""" import sys; sys.path.insert(0, {repr(os.path.join(temp_dir, 'zipmodule.zip'))}) import foo - foo.bar(41) + foo.bar() """ ) @@ -4227,10 +4227,10 @@ def bar(x): 'n', 'b foo.bar', 'c', - 'p x + x', + 'p f"break in {$_frame.f_code.co_name}"', 'q' ])) - self.assertIn('82', stdout) + self.assertIn('break in bar', stdout) class ChecklineTests(unittest.TestCase):