mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-91048: Add filename:line_no information to asyncio pstree
(#133478)
This commit is contained in:
parent
cae660d6dc
commit
60cdd800d9
3 changed files with 36 additions and 20 deletions
|
@ -146,6 +146,7 @@ if __name__ == '__main__':
|
|||
parser = argparse.ArgumentParser(
|
||||
prog="python3 -m asyncio",
|
||||
description="Interactive asyncio shell and CLI tools",
|
||||
color=True,
|
||||
)
|
||||
subparsers = parser.add_subparsers(help="sub-commands", dest="command")
|
||||
ps = subparsers.add_parser(
|
||||
|
|
|
@ -21,13 +21,21 @@ class CycleFoundException(Exception):
|
|||
|
||||
|
||||
# ─── indexing helpers ───────────────────────────────────────────
|
||||
def _format_stack_entry(elem: tuple[str, str, int] | str) -> str:
|
||||
if isinstance(elem, tuple):
|
||||
fqname, path, line_no = elem
|
||||
return f"{fqname} {path}:{line_no}"
|
||||
|
||||
return elem
|
||||
|
||||
|
||||
def _index(result):
|
||||
id2name, awaits = {}, []
|
||||
for _thr_id, tasks in result:
|
||||
for tid, tname, awaited in tasks:
|
||||
id2name[tid] = tname
|
||||
for stack, parent_id in awaited:
|
||||
stack = [elem[0] if isinstance(elem, tuple) else elem for elem in stack]
|
||||
stack = [_format_stack_entry(elem) for elem in stack]
|
||||
awaits.append((parent_id, stack, tid))
|
||||
return id2name, awaits
|
||||
|
||||
|
@ -106,7 +114,7 @@ def _find_cycles(graph):
|
|||
# ─── PRINT TREE FUNCTION ───────────────────────────────────────
|
||||
def build_async_tree(result, task_emoji="(T)", cor_emoji=""):
|
||||
"""
|
||||
Build a list of strings for pretty-print a async call tree.
|
||||
Build a list of strings for pretty-print an async call tree.
|
||||
|
||||
The call tree is produced by `get_all_async_stacks()`, prefixing tasks
|
||||
with `task_emoji` and coroutine frames with `cor_emoji`.
|
||||
|
@ -169,7 +177,7 @@ def build_task_table(result):
|
|||
return table
|
||||
|
||||
def _print_cycle_exception(exception: CycleFoundException):
|
||||
print("ERROR: await-graph contains cycles – cannot print a tree!", file=sys.stderr)
|
||||
print("ERROR: await-graph contains cycles - cannot print a tree!", file=sys.stderr)
|
||||
print("", file=sys.stderr)
|
||||
for c in exception.cycles:
|
||||
inames = " → ".join(exception.id2name.get(tid, hex(tid)) for tid in c)
|
||||
|
|
|
@ -18,10 +18,18 @@ TEST_INPUTS_TREE = [
|
|||
3,
|
||||
"timer",
|
||||
[
|
||||
[["awaiter3", "awaiter2", "awaiter"], 4],
|
||||
[["awaiter1_3", "awaiter1_2", "awaiter1"], 5],
|
||||
[["awaiter1_3", "awaiter1_2", "awaiter1"], 6],
|
||||
[["awaiter3", "awaiter2", "awaiter"], 7],
|
||||
[[("awaiter3", "/path/to/app.py", 130),
|
||||
("awaiter2", "/path/to/app.py", 120),
|
||||
("awaiter", "/path/to/app.py", 110)], 4],
|
||||
[[("awaiterB3", "/path/to/app.py", 190),
|
||||
("awaiterB2", "/path/to/app.py", 180),
|
||||
("awaiterB", "/path/to/app.py", 170)], 5],
|
||||
[[("awaiterB3", "/path/to/app.py", 190),
|
||||
("awaiterB2", "/path/to/app.py", 180),
|
||||
("awaiterB", "/path/to/app.py", 170)], 6],
|
||||
[[("awaiter3", "/path/to/app.py", 130),
|
||||
("awaiter2", "/path/to/app.py", 120),
|
||||
("awaiter", "/path/to/app.py", 110)], 7],
|
||||
],
|
||||
),
|
||||
(
|
||||
|
@ -91,14 +99,14 @@ TEST_INPUTS_TREE = [
|
|||
" │ └── __aexit__",
|
||||
" │ └── _aexit",
|
||||
" │ ├── (T) child1_1",
|
||||
" │ │ └── awaiter",
|
||||
" │ │ └── awaiter2",
|
||||
" │ │ └── awaiter3",
|
||||
" │ │ └── awaiter /path/to/app.py:110",
|
||||
" │ │ └── awaiter2 /path/to/app.py:120",
|
||||
" │ │ └── awaiter3 /path/to/app.py:130",
|
||||
" │ │ └── (T) timer",
|
||||
" │ └── (T) child2_1",
|
||||
" │ └── awaiter1",
|
||||
" │ └── awaiter1_2",
|
||||
" │ └── awaiter1_3",
|
||||
" │ └── awaiterB /path/to/app.py:170",
|
||||
" │ └── awaiterB2 /path/to/app.py:180",
|
||||
" │ └── awaiterB3 /path/to/app.py:190",
|
||||
" │ └── (T) timer",
|
||||
" └── (T) root2",
|
||||
" └── bloch",
|
||||
|
@ -106,14 +114,14 @@ TEST_INPUTS_TREE = [
|
|||
" └── __aexit__",
|
||||
" └── _aexit",
|
||||
" ├── (T) child1_2",
|
||||
" │ └── awaiter",
|
||||
" │ └── awaiter2",
|
||||
" │ └── awaiter3",
|
||||
" │ └── awaiter /path/to/app.py:110",
|
||||
" │ └── awaiter2 /path/to/app.py:120",
|
||||
" │ └── awaiter3 /path/to/app.py:130",
|
||||
" │ └── (T) timer",
|
||||
" └── (T) child2_2",
|
||||
" └── awaiter1",
|
||||
" └── awaiter1_2",
|
||||
" └── awaiter1_3",
|
||||
" └── awaiterB /path/to/app.py:170",
|
||||
" └── awaiterB2 /path/to/app.py:180",
|
||||
" └── awaiterB3 /path/to/app.py:190",
|
||||
" └── (T) timer",
|
||||
]
|
||||
]
|
||||
|
@ -589,7 +597,6 @@ TEST_INPUTS_TABLE = [
|
|||
|
||||
|
||||
class TestAsyncioToolsTree(unittest.TestCase):
|
||||
|
||||
def test_asyncio_utils(self):
|
||||
for input_, tree in TEST_INPUTS_TREE:
|
||||
with self.subTest(input_):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue