Skip to content
This repository has been archived by the owner on May 9, 2023. It is now read-only.

Commit

Permalink
wip: ungather; to do overview
Browse files Browse the repository at this point in the history
  • Loading branch information
dimaqq committed Aug 28, 2019
1 parent c7680bf commit 74d5e76
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 4 deletions.
27 changes: 27 additions & 0 deletions awaitwhat/__init__.py
@@ -1,6 +1,7 @@
from asyncio.base_tasks import _task_print_stack, _task_get_stack
import types
from . import _what
from . import gather


class FakeCode:
Expand All @@ -19,6 +20,7 @@ def __init__(self, name):
self.f_code = FakeCode(name)


# FIXME: what order is the stack in, as in, is it reversed?
def extend_stack(s, limit=None):
stack = s[:]
while isinstance(stack[-1], types.FrameType):
Expand Down Expand Up @@ -66,3 +68,28 @@ def get_stack(self, limit=None):

def task_print_stack(task, limit, file):
return _task_print_stack(Wrapper(task), limit, file)


# FIXME: what can be awaited:
#
# - coro (done)
# - Task (enumerated, but needs a bridge)
# - Future (naked, unclear who ought to resolve it)
# - Event (e.wait() is a coro, but needs a bridge?)
# - gather (via callback)
# - shield (via callback)
# - asyncio.run (via callback)
#
# - TaskWakeupMethWrapper (via callback)
# - bridge FutureIter to Future (or just rely on Task wait_for=<...>

# FIXME: callbacks:
#
# top-level event loop thing:
# cb=[_run_until_complete_cb() at /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py:158
#
# gather:
# cb=[gather.<locals>._done_callback() at /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/tasks.py:664
#
# shield:
# ...
29 changes: 29 additions & 0 deletions awaitwhat/gather.py
@@ -0,0 +1,29 @@
import inspect

# work in progress:

# when a task is ultimately waiting on gather(), _done_callback is visible.


def decipher_done_callback(done_callback):
closure = inspect.getclosurevars(done_callback).nonlocals
state = f"progress: {closure['nfinished']}/{closure['nfuts']}"
future = closure["outer"]
print(future, state)
children = closure["children"]
for child in children:
if child.done():
# resolved, exception, cancelled
if child.cancelled():
print(child, "cancelled")
elif child.exception():
print(child, child.exception())
else:
print(child, child.result())
else:
print(child, "pending")


def task_callback(t):
# FIXME: there may be several; py 3.8 vs py 3.7
return t._callbacks[0][0]
17 changes: 13 additions & 4 deletions test/test.py
@@ -1,20 +1,29 @@
import asyncio
import linecache
from awaitwhat import extend_stack, _task_print_stack, task_print_stack
import awaitwhat
import sys


def trace_all_tasks():
print("### Python native task stack traces")
for t in asyncio.Task.all_tasks():
_task_print_stack(t, None, sys.stdout)
asyncio.base_tasks._task_print_stack(t, None, sys.stdout)
print()

print("### Extended task stack traces")
for t in asyncio.Task.all_tasks():
task_print_stack(t, None, sys.stdout)
awaitwhat.task_print_stack(t, None, sys.stdout)
print()

tt = asyncio.Task.all_tasks()
t = list(tt)[0]
print(t)
cb = awaitwhat.gather.task_callback(t)
try:
awaitwhat.gather.decipher_done_callback(cb)
except Exception as e:
print("failed to decipher", e)
__import__("pdb").set_trace()


async def tester():
await asyncio.sleep(0.1)
Expand Down

0 comments on commit 74d5e76

Please sign in to comment.