mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-121468: Add current asyncio task as a convenience variable in pdb (#124367)
This commit is contained in:
parent
c107b15ab8
commit
27fc62cf4f
5 changed files with 49 additions and 3 deletions
|
@ -313,16 +313,20 @@ sets a global variable ``$foo`` which you can use in the debugger session. The
|
||||||
less likely to interfere with your program compared to using normal variables
|
less likely to interfere with your program compared to using normal variables
|
||||||
like ``foo = 1``.
|
like ``foo = 1``.
|
||||||
|
|
||||||
There are three preset *convenience variables*:
|
There are four preset *convenience variables*:
|
||||||
|
|
||||||
* ``$_frame``: the current frame you are debugging
|
* ``$_frame``: the current frame you are debugging
|
||||||
* ``$_retval``: the return value if the frame is returning
|
* ``$_retval``: the return value if the frame is returning
|
||||||
* ``$_exception``: the exception if the frame is raising an exception
|
* ``$_exception``: the exception if the frame is raising an exception
|
||||||
|
* ``$_asynctask``: the asyncio task if pdb stops in an async function
|
||||||
|
|
||||||
.. versionadded:: 3.12
|
.. versionadded:: 3.12
|
||||||
|
|
||||||
Added the *convenience variable* feature.
|
Added the *convenience variable* feature.
|
||||||
|
|
||||||
|
.. versionadded:: 3.14
|
||||||
|
Added the ``$_asynctask`` convenience variable.
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
pair: .pdbrc; file
|
pair: .pdbrc; file
|
||||||
triple: debugger; configuration; file
|
triple: debugger; configuration; file
|
||||||
|
|
|
@ -830,6 +830,9 @@ pdb
|
||||||
fill in a 4-space indentation now, instead of inserting a ``\t`` character.
|
fill in a 4-space indentation now, instead of inserting a ``\t`` character.
|
||||||
(Contributed by Tian Gao in :gh:`130471`.)
|
(Contributed by Tian Gao in :gh:`130471`.)
|
||||||
|
|
||||||
|
* ``$_asynctask`` is added to access the current asyncio task if applicable.
|
||||||
|
(Contributed by Tian Gao in :gh:`124367`.)
|
||||||
|
|
||||||
|
|
||||||
pickle
|
pickle
|
||||||
------
|
------
|
||||||
|
|
15
Lib/pdb.py
15
Lib/pdb.py
|
@ -79,6 +79,7 @@ import types
|
||||||
import codeop
|
import codeop
|
||||||
import pprint
|
import pprint
|
||||||
import signal
|
import signal
|
||||||
|
import asyncio
|
||||||
import inspect
|
import inspect
|
||||||
import textwrap
|
import textwrap
|
||||||
import tokenize
|
import tokenize
|
||||||
|
@ -363,6 +364,8 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
self._chained_exceptions = tuple()
|
self._chained_exceptions = tuple()
|
||||||
self._chained_exception_index = 0
|
self._chained_exception_index = 0
|
||||||
|
|
||||||
|
self._current_task = None
|
||||||
|
|
||||||
def set_trace(self, frame=None, *, commands=None):
|
def set_trace(self, frame=None, *, commands=None):
|
||||||
Pdb._last_pdb_instance = self
|
Pdb._last_pdb_instance = self
|
||||||
if frame is None:
|
if frame is None:
|
||||||
|
@ -405,7 +408,8 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
tb = tb.tb_next
|
tb = tb.tb_next
|
||||||
self.curframe = self.stack[self.curindex][0]
|
self.curframe = self.stack[self.curindex][0]
|
||||||
self.set_convenience_variable(self.curframe, '_frame', self.curframe)
|
self.set_convenience_variable(self.curframe, '_frame', self.curframe)
|
||||||
|
if self._current_task:
|
||||||
|
self.set_convenience_variable(self.curframe, '_asynctask', self._current_task)
|
||||||
self._save_initial_file_mtime(self.curframe)
|
self._save_initial_file_mtime(self.curframe)
|
||||||
|
|
||||||
if self._chained_exceptions:
|
if self._chained_exceptions:
|
||||||
|
@ -616,6 +620,13 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
self._chained_exceptions = tuple()
|
self._chained_exceptions = tuple()
|
||||||
self._chained_exception_index = 0
|
self._chained_exception_index = 0
|
||||||
|
|
||||||
|
def _get_asyncio_task(self):
|
||||||
|
try:
|
||||||
|
task = asyncio.current_task()
|
||||||
|
except RuntimeError:
|
||||||
|
task = None
|
||||||
|
return task
|
||||||
|
|
||||||
def interaction(self, frame, tb_or_exc):
|
def interaction(self, frame, tb_or_exc):
|
||||||
# Restore the previous signal handler at the Pdb prompt.
|
# Restore the previous signal handler at the Pdb prompt.
|
||||||
if Pdb._previous_sigint_handler:
|
if Pdb._previous_sigint_handler:
|
||||||
|
@ -626,6 +637,8 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
else:
|
else:
|
||||||
Pdb._previous_sigint_handler = None
|
Pdb._previous_sigint_handler = None
|
||||||
|
|
||||||
|
self._current_task = self._get_asyncio_task()
|
||||||
|
|
||||||
_chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc)
|
_chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc)
|
||||||
if isinstance(tb_or_exc, BaseException):
|
if isinstance(tb_or_exc, BaseException):
|
||||||
assert tb is not None, "main exception must have a traceback"
|
assert tb is not None, "main exception must have a traceback"
|
||||||
|
|
|
@ -16,7 +16,7 @@ import zipfile
|
||||||
from contextlib import ExitStack, redirect_stdout
|
from contextlib import ExitStack, redirect_stdout
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import force_not_colorized, os_helper
|
from test.support import force_not_colorized, has_socket_support, os_helper
|
||||||
from test.support.import_helper import import_module
|
from test.support.import_helper import import_module
|
||||||
from test.support.pty_helper import run_pty, FakeInput
|
from test.support.pty_helper import run_pty, FakeInput
|
||||||
from test.support.script_helper import kill_python
|
from test.support.script_helper import kill_python
|
||||||
|
@ -2059,6 +2059,30 @@ def test_pdb_next_command_for_generator():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not SKIP_CORO_TESTS:
|
if not SKIP_CORO_TESTS:
|
||||||
|
if has_socket_support:
|
||||||
|
def test_pdb_asynctask():
|
||||||
|
"""Testing $_asynctask is accessible in async context
|
||||||
|
|
||||||
|
>>> import asyncio
|
||||||
|
|
||||||
|
>>> async def test():
|
||||||
|
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
|
|
||||||
|
>>> def test_function():
|
||||||
|
... asyncio.run(test())
|
||||||
|
|
||||||
|
>>> with PdbTestInput([ # doctest: +ELLIPSIS
|
||||||
|
... '$_asynctask',
|
||||||
|
... 'continue',
|
||||||
|
... ]):
|
||||||
|
... test_function()
|
||||||
|
> <doctest test.test_pdb.test_pdb_asynctask[1]>(2)test()
|
||||||
|
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
|
(Pdb) $_asynctask
|
||||||
|
<Task pending name='Task-1' coro=<test() running at <doctest test.test_pdb.test_pdb_asynctask[1]>:2> ...
|
||||||
|
(Pdb) continue
|
||||||
|
"""
|
||||||
|
|
||||||
def test_pdb_next_command_for_coroutine():
|
def test_pdb_next_command_for_coroutine():
|
||||||
"""Testing skip unwinding stack on yield for coroutines for "next" command
|
"""Testing skip unwinding stack on yield for coroutines for "next" command
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
``$_asynctask`` is added as a :mod:`pdb` convenience variable to
|
||||||
|
access the current asyncio task if applicable.
|
Loading…
Add table
Add a link
Reference in a new issue