Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-103693: Add convenience variable feature topdb#103694

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletionsDoc/library/pdb.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,21 @@ the commands; the input is split at the first ``;;`` pair, even if it is in the
middle of a quoted string. A workaround for strings with double semicolons
is to use implicit string concatenation ``';'';'`` or ``";"";"``.

To set a temporary global variable, use a *convenience variable*. A *convenience
variable* is a variable whose name starts with ``$``. For example, ``$foo = 1``
sets a global variable ``$foo`` which you can use in the debugger session. The
*convenience variables* are cleared when the program resumes execution so it's
less likely to interfere with your program compared to using normal variables
like ``foo = 1``.

There are three preset *convenience variables*:

* ``$_frame``: the current frame you are debugging
* ``$_retval``: the return value if the frame is returning
* ``$_exception``: the exception if the frame is raising an exception

.. versionadded:: 3.12

.. index::
pair: .pdbrc; file
triple: debugger; configuration; file
Expand Down
8 changes: 8 additions & 0 deletionsDoc/whatsnew/3.12.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -356,6 +356,14 @@ os.path
* Add :func:`os.path.splitroot` to split a path into a triad
``(drive, root, tail)``. (Contributed by Barney Gale in :gh:`101000`.)

pdb
---

* Add convenience variables to hold values temporarily for debug session
and provide quick access to values like the current frame or the return
value.
(Contributed by Tian Gao in :gh:`103693`.)

shutil
------

Expand Down
17 changes: 17 additions & 0 deletionsLib/pdb.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,8 @@ def forget(self):
self.lineno = None
self.stack = []
self.curindex = 0
if hasattr(self, 'curframe') and self.curframe:
self.curframe.f_globals.pop('__pdb_convenience_variables', None)
self.curframe = None
self.tb_lineno.clear()

Expand All@@ -288,6 +290,7 @@ def setup(self, f, tb):
# locals whenever the .f_locals accessor is called, so we
# cache it here to ensure that modifications are not overwritten.
self.curframe_locals = self.curframe.f_locals
self.set_convenience_variable(self.curframe, '_frame', self.curframe)
return self.execRcLines()

# Can be executed earlier than 'setup' if desired
Expand DownExpand Up@@ -359,6 +362,7 @@ def user_return(self, frame, return_value):
if self._wait_for_mainpyfile:
return
frame.f_locals['__return__'] = return_value
self.set_convenience_variable(frame, '_retval', return_value)
self.message('--Return--')
self.interaction(frame, None)

Expand All@@ -369,6 +373,7 @@ def user_exception(self, frame, exc_info):
return
exc_type, exc_value, exc_traceback = exc_info
frame.f_locals['__exception__'] = exc_type, exc_value
self.set_convenience_variable(frame, '_exception', exc_value)

# An 'Internal StopIteration' exception is an exception debug event
# issued by the interpreter when handling a subgenerator run with
Expand All@@ -394,6 +399,7 @@ def _cmdloop(self):
self.message('--KeyboardInterrupt--')

# Called before loop, handles display expressions
# Set up convenience variable containers
def preloop(self):
displaying = self.displaying.get(self.curframe)
if displaying:
Expand DownExpand Up@@ -477,6 +483,9 @@ def precmd(self, line):
next = line[marker+2:].lstrip()
self.cmdqueue.append(next)
line = line[:marker].rstrip()

# Replace all the convenience variables
line = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'__pdb_convenience_variables["\1"]', line)
return line

def onecmd(self, line):
Expand DownExpand Up@@ -527,6 +536,13 @@ def message(self, msg):
def error(self, msg):
print('***', msg, file=self.stdout)

# convenience variables

def set_convenience_variable(self, frame, name, value):
if '__pdb_convenience_variables' not in frame.f_globals:
frame.f_globals['__pdb_convenience_variables'] = {}
frame.f_globals['__pdb_convenience_variables'][name] = value

# Generic completion functions. Individual complete_foo methods can be
# assigned below to one of these functions.

Expand DownExpand Up@@ -1018,6 +1034,7 @@ def _select_frame(self, number):
self.curindex = number
self.curframe = self.stack[self.curindex][0]
self.curframe_locals = self.curframe.f_locals
self.set_convenience_variable(self.curframe, '_frame', self.curframe)
self.print_stack_entry(self.stack[self.curindex])
self.lineno = None

Expand Down
78 changes: 78 additions & 0 deletionsLib/test/test_pdb.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -746,6 +746,84 @@ def test_pdb_where_command():
(Pdb) continue
"""

def test_convenience_variables():
"""Test convenience variables

>>> def util_function():
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... try:
... raise Exception('test')
... except:
... pass
... return 1

>>> def test_function():
... util_function()

>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
... '$_frame.f_lineno', # Check frame convenience variable
... '$a = 10', # Set a convenience variable
... '$a', # Print its value
... 'p $a + 2', # Do some calculation
... 'u', # Switch frame
... '$_frame.f_lineno', # Make sure the frame changed
... '$a', # Make sure the value persists
... 'd', # Go back to the original frame
... 'next',
... '$a', # The value should be gone
... 'next',
... '$_exception', # Check exception convenience variable
... 'next',
... '$_exception', # Exception should be gone
... 'return',
... '$_retval', # Check return convenience variable
... 'continue',
... ]):
... test_function()
> <doctest test.test_pdb.test_convenience_variables[0]>(3)util_function()
-> try:
(Pdb) $_frame.f_lineno
3
(Pdb) $a = 10
(Pdb) $a
10
(Pdb) p $a + 2
12
(Pdb) u
> <doctest test.test_pdb.test_convenience_variables[1]>(2)test_function()
-> util_function()
(Pdb) $_frame.f_lineno
2
(Pdb) $a
10
(Pdb) d
> <doctest test.test_pdb.test_convenience_variables[0]>(3)util_function()
-> try:
(Pdb) next
> <doctest test.test_pdb.test_convenience_variables[0]>(4)util_function()
-> raise Exception('test')
(Pdb) $a
*** KeyError: 'a'
(Pdb) next
Exception: test
> <doctest test.test_pdb.test_convenience_variables[0]>(4)util_function()
-> raise Exception('test')
(Pdb) $_exception
Exception('test')
(Pdb) next
> <doctest test.test_pdb.test_convenience_variables[0]>(5)util_function()
-> except:
(Pdb) $_exception
*** KeyError: '_exception'
(Pdb) return
--Return--
> <doctest test.test_pdb.test_convenience_variables[0]>(7)util_function()->1
-> return 1
(Pdb) $_retval
1
(Pdb) continue
"""

def test_post_mortem():
"""Test post mortem traceback debugging.

Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Add convenience variable feature to :mod:`pdb`

[8]ページ先頭

©2009-2025 Movatter.jp