https://github.com/python/cpython/commit/e4f1fed5f6bb788d6d5a86bdbb770d25066636d1 commit: e4f1fed5f6bb788d6d5a86bdbb770d25066636d1 branch: 3.12 author: Tian Gao <[email protected]> committer: gaogaotiantian <[email protected]> date: 2024-06-17T10:40:49-07:00 summary:
[3.12] gh-119824: Print stack entry when user input is needed … (#120594) Co-authored-by: Irit Katriel <[email protected]> files: A Misc/NEWS.d/next/Library/2024-05-31-21-17-43.gh-issue-119824.CQlxWV.rst M Lib/pdb.py M Lib/test/test_pdb.py diff --git a/Lib/pdb.py b/Lib/pdb.py index 225c9f253ef310..2ad5a321a43c46 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -419,10 +419,18 @@ def interaction(self, frame, traceback): else: Pdb._previous_sigint_handler = None self.setup(frame, traceback) - # if we have more commands to process, do not show the stack entry - if not self.cmdqueue: + # We should print the stack entry if and only if the user input + # is expected, and we should print it right before the user input. + # If self.cmdqueue is not empty, we append a "w 0" command to the + # queue, which is equivalent to print_stack_entry + if self.cmdqueue: + self.cmdqueue.append('w 0') + else: self.print_stack_entry(self.stack[self.curindex]) self._cmdloop() + # If "w 0" is not used, pop it out + if self.cmdqueue and self.cmdqueue[-1] == 'w 0': + self.cmdqueue.pop() self.forget() def displayhook(self, obj): @@ -1045,13 +1053,24 @@ def do_clear(self, arg): complete_cl = _complete_location def do_where(self, arg): - """w(here) + """w(here) [count] - Print a stack trace, with the most recent frame at the bottom. + Print a stack trace. If count is not specified, print the full stack. + If count is 0, print the current frame entry. If count is positive, + print count entries from the most recent frame. If count is negative, + print -count entries from the least recent frame. An arrow indicates the "current frame", which determines the context of most commands. 'bt' is an alias for this command. """ - self.print_stack_trace() + if not arg: + count = None + else: + try: + count = int(arg) + except ValueError: + self.error('Invalid count (%s)' % arg) + return + self.print_stack_trace(count) do_w = do_where do_bt = do_where @@ -1623,10 +1642,22 @@ def complete_unalias(self, text, line, begidx, endidx): # It is also consistent with the up/down commands (which are # compatible with dbx and gdb: up moves towards 'main()' # and down moves towards the most recent stack frame). - - def print_stack_trace(self): + # * if count is None, prints the full stack + # * if count = 0, prints the current frame entry + # * if count < 0, prints -count least recent frame entries + # * if count > 0, prints count most recent frame entries + + def print_stack_trace(self, count=None): + if count is None: + stack_to_print = self.stack + elif count == 0: + stack_to_print = [self.stack[self.curindex]] + elif count < 0: + stack_to_print = self.stack[:-count] + else: + stack_to_print = self.stack[-count:] try: - for frame_lineno in self.stack: + for frame_lineno in stack_to_print: self.print_stack_entry(frame_lineno) except KeyboardInterrupt: pass diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 24324a37804ca0..15c50ba01fdf39 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -703,7 +703,7 @@ def test_pdb_where_command(): ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() >>> def f(): - ... g(); + ... g() >>> def test_function(): ... f() @@ -711,8 +711,13 @@ def test_pdb_where_command(): >>> with PdbTestInput([ # doctest: +ELLIPSIS ... 'w', ... 'where', + ... 'w 1', + ... 'w invalid', ... 'u', ... 'w', + ... 'w 0', + ... 'w 100', + ... 'w -100', ... 'continue', ... ]): ... test_function() @@ -721,35 +726,63 @@ def test_pdb_where_command(): -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() (Pdb) w ... - <doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>() + <doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>() -> test_function() <doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function() -> f() <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() - -> g(); + -> g() > <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() (Pdb) where ... - <doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>() + <doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>() -> test_function() <doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function() -> f() <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() - -> g(); + -> g() > <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) w 1 + > <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) w invalid + *** Invalid count (invalid) (Pdb) u > <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() - -> g(); + -> g() (Pdb) w ... - <doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>() + <doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>() + -> test_function() + <doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function() + -> f() + > <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() + -> g() + <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) w 0 + > <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() + -> g() + (Pdb) w 100 + ... + <doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>() -> test_function() <doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function() -> f() > <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() - -> g(); + -> g() + <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) w -100 + ... + <doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>() + -> test_function() + <doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function() + -> f() + > <doctest test.test_pdb.test_pdb_where_command[1]>(2)f() + -> g() <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() (Pdb) continue @@ -2266,6 +2299,7 @@ def test_pdbrc_basic(self): stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True) self.assertNotIn("SyntaxError", stdout) self.assertIn("a+8=9", stdout) + self.assertIn("-> b = 2", stdout) def test_pdbrc_empty_line(self): """Test that empty lines in .pdbrc are ignored.""" diff --git a/Misc/NEWS.d/next/Library/2024-05-31-21-17-43.gh-issue-119824.CQlxWV.rst b/Misc/NEWS.d/next/Library/2024-05-31-21-17-43.gh-issue-119824.CQlxWV.rst new file mode 100644 index 00000000000000..fd6d8d79a9d157 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-05-31-21-17-43.gh-issue-119824.CQlxWV.rst @@ -0,0 +1 @@ +Print stack entry in :mod:`pdb` when and only when user input is needed. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
