From 1fbb2129eb1c199cd20e519c8f1ac4e554205658 Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Thu, 15 Jan 2026 23:56:31 +0800 Subject: [PATCH 1/4] pdb: fix expression result output stream in `_exec_in_closure()` Fixes an issue where results of expressions executed via `_exec_in_closure()` were written to `sys.stdout` instead of the debugger output stream. Adds a regression test to ensure expression results are consistently emitted via pdb.stdout. Signed-off-by: Yongtao Huang --- Lib/pdb.py | 2 +- Lib/test/test_pdb.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Lib/pdb.py b/Lib/pdb.py index 0464b288ef825a..b5d8f827827415 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -888,7 +888,7 @@ def _exec_in_closure(self, source, globals, locals): locals.update(pdb_eval["write_back"]) eval_result = pdb_eval["result"] if eval_result is not None: - print(repr(eval_result)) + self.message(repr(eval_result)) return True diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 0e23cd6604379c..8a2aaa6a134e27 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -3666,6 +3666,28 @@ def test_print_stack_entry_uses_dynamic_line_prefix(self): # Check if the custom prefix appeared in the output self.assertIn('CUSTOM_PREFIX> ', stdout.getvalue()) + def test_exec_in_closure_result_uses_pdb_stdout(self): + """ + Expression results executed via _exec_in_closure() should be written + to the debugger output stream (pdb stdout), not to sys.stdout. + """ + pdb_out = io.StringIO() + sys_out = io.StringIO() + + p = pdb.Pdb(nosigint=True, readrc=False, stdout=pdb_out) + + with redirect_stdout(sys_out): + self.assertTrue(p._exec_in_closure('(lambda: 123)()', {}, {})) + self.assertTrue(p._exec_in_closure('sum(i for i in (1, 2, 3))', {}, {})) + + pdb_lines = [line.strip() for line in pdb_out.getvalue().splitlines()] + sys_lines = [line.strip() for line in sys_out.getvalue().splitlines()] + + self.assertIn('123', pdb_lines) + self.assertIn('6', pdb_lines) + self.assertNotIn('123', sys_lines) + self.assertNotIn('6', sys_lines) + def test_find_function_found_with_encoding_cookie(self): self._assert_find_function( """\ From fb65bb179bb6ca0852da8d7c6f545951dfeabf2a Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:04:40 +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/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst diff --git a/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst b/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst new file mode 100644 index 00000000000000..d5aa9d72a3e1be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst @@ -0,0 +1 @@ +Fixed an issue in pdb where results of expressions evaluated via the closure execution path could be written to sys.stdout instead of the debugger output stream. From 0ba3b4e6a037c6919781bb2d76a0d5a2faf1f18a Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Fri, 16 Jan 2026 06:45:13 +0800 Subject: [PATCH 3/4] Address comments --- Lib/test/test_pdb.py | 22 ---------------------- Lib/test/test_remote_pdb.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 8a2aaa6a134e27..0e23cd6604379c 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -3666,28 +3666,6 @@ def test_print_stack_entry_uses_dynamic_line_prefix(self): # Check if the custom prefix appeared in the output self.assertIn('CUSTOM_PREFIX> ', stdout.getvalue()) - def test_exec_in_closure_result_uses_pdb_stdout(self): - """ - Expression results executed via _exec_in_closure() should be written - to the debugger output stream (pdb stdout), not to sys.stdout. - """ - pdb_out = io.StringIO() - sys_out = io.StringIO() - - p = pdb.Pdb(nosigint=True, readrc=False, stdout=pdb_out) - - with redirect_stdout(sys_out): - self.assertTrue(p._exec_in_closure('(lambda: 123)()', {}, {})) - self.assertTrue(p._exec_in_closure('sum(i for i in (1, 2, 3))', {}, {})) - - pdb_lines = [line.strip() for line in pdb_out.getvalue().splitlines()] - sys_lines = [line.strip() for line in sys_out.getvalue().splitlines()] - - self.assertIn('123', pdb_lines) - self.assertIn('6', pdb_lines) - self.assertNotIn('123', sys_lines) - self.assertNotIn('6', sys_lines) - def test_find_function_found_with_encoding_cookie(self): self._assert_find_function( """\ diff --git a/Lib/test/test_remote_pdb.py b/Lib/test/test_remote_pdb.py index ede99de981971a..d26d63faa61ddb 100644 --- a/Lib/test/test_remote_pdb.py +++ b/Lib/test/test_remote_pdb.py @@ -1441,6 +1441,34 @@ def test_multi_line_commands(self): self.assertIn("Function returned: 42", stdout) self.assertEqual(process.returncode, 0) + def test_exec_in_closure_result_uses_pdb_stdout(self): + """ + Expression results executed via _exec_in_closure() should be written + to the debugger output stream (pdb stdout), not to sys.stdout. + """ + self._create_script() + process, client_file = self._connect_and_get_client_file() + + with kill_on_error(process): + self._read_until_prompt(client_file) + + self._send_command(client_file, "(lambda: 123)()") + messages = self._read_until_prompt(client_file) + result_msg = "".join(msg.get("message", "") for msg in messages) + self.assertIn("123", result_msg) + + self._send_command(client_file, "sum(i for i in (1, 2, 3))") + messages = self._read_until_prompt(client_file) + result_msg = "".join(msg.get("message", "") for msg in messages) + self.assertIn("6", result_msg) + + self._send_command(client_file, "c") + stdout, _ = process.communicate(timeout=SHORT_TIMEOUT) + + self.assertNotIn("\n123\n", stdout) + self.assertNotIn("\n6\n", stdout) + self.assertEqual(process.returncode, 0) + def _supports_remote_attaching(): PROCESS_VM_READV_SUPPORTED = False From 5635c1f5b6f4b495f1500a4f45b140cee7221c15 Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Fri, 16 Jan 2026 14:36:08 +0800 Subject: [PATCH 4/4] Update NEWs --- .../next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst b/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst index d5aa9d72a3e1be..8f606525c73026 100644 --- a/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst +++ b/Misc/NEWS.d/next/Library/2026-01-15-16-04-39.gh-issue-143874.1qQgvo.rst @@ -1 +1 @@ -Fixed an issue in pdb where results of expressions evaluated via the closure execution path could be written to sys.stdout instead of the debugger output stream. +Fixed a bug in pdb where expression results were written to sys.stdout instead of pdb.stdout.