From 7d275611f62c9008c2d90b08c9f21462f80a8328 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Sun, 26 Jan 2025 22:29:16 -0500 Subject: gh-124703: Do not raise an exception when quitting pdb (#124704) --- Lib/pdb.py | 17 +++++-- Lib/test/test_pdb.py | 56 ++++++++++++++++++++++ .../2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst | 1 + 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst diff --git a/Lib/pdb.py b/Lib/pdb.py index 10d1923..beef74d 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -1725,6 +1725,19 @@ class Pdb(bdb.Bdb, cmd.Cmd): Quit from the debugger. The program being executed is aborted. """ + if self.mode == 'inline': + while True: + try: + reply = input('Quitting pdb will kill the process. Quit anyway? [y/n] ') + reply = reply.lower().strip() + except EOFError: + reply = 'y' + self.message('') + if reply == 'y' or reply == '': + sys.exit(0) + elif reply.lower() == 'n': + return + self._user_requested_quit = True self.set_quit() return 1 @@ -1738,9 +1751,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): Handles the receipt of EOF as a command. """ self.message('') - self._user_requested_quit = True - self.set_quit() - return 1 + return self.do_quit(arg) def do_args(self, arg): """a(rgs) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 0960162..4d371a6 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4238,6 +4238,62 @@ class ChecklineTests(unittest.TestCase): @support.requires_subprocess() +class PdbTestInline(unittest.TestCase): + @unittest.skipIf(sys.flags.safe_path, + 'PYTHONSAFEPATH changes default sys.path') + def _run_script(self, script, commands, + expected_returncode=0, + extra_env=None): + self.addCleanup(os_helper.rmtree, '__pycache__') + filename = 'main.py' + with open(filename, 'w') as f: + f.write(textwrap.dedent(script)) + self.addCleanup(os_helper.unlink, filename) + + commands = textwrap.dedent(commands) + + cmd = [sys.executable, 'main.py'] + if extra_env is not None: + env = os.environ | extra_env + else: + env = os.environ + with subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.PIPE, + env = {**env, 'PYTHONIOENCODING': 'utf-8'} + ) as proc: + stdout, stderr = proc.communicate(str.encode(commands)) + stdout = bytes.decode(stdout) if isinstance(stdout, bytes) else stdout + stderr = bytes.decode(stderr) if isinstance(stderr, bytes) else stderr + self.assertEqual( + proc.returncode, + expected_returncode, + f"Unexpected return code\nstdout: {stdout}\nstderr: {stderr}" + ) + return stdout, stderr + + def test_quit(self): + script = """ + x = 1 + breakpoint() + """ + + commands = """ + quit + n + p x + 1 + quit + y + """ + + stdout, stderr = self._run_script(script, commands) + self.assertIn("2", stdout) + self.assertIn("Quit anyway", stdout) + + +@support.requires_subprocess() class PdbTestReadline(unittest.TestCase): def setUpClass(): # Ensure that the readline module is loaded diff --git a/Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst b/Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst new file mode 100644 index 0000000..e55d353 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst @@ -0,0 +1 @@ +Quitting :mod:`pdb` in ``inline`` mode will emit a confirmation prompt and exit gracefully now, instead of printing an exception traceback. -- cgit v0.12