# -*- coding: utf-8 -*-
from distutils.core import setup

packages = \
['awaitwhat']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'awaitwhat',
    'version': '19.1a2',
    'description': 'async/await introspection',
    'long_description': '# Await, What?\n\nTell you what waits for what in an `async/await` program.\n\n### TL;DR\n\nSay you have this code:\n```py\n\nasync def job():\n    await foo()\n\n\nasync def foo():\n    await bar()\n\n\nasync def bar():\n    await baz()\n\n\nasync def baz():\n    await leaf()\n\n\nasync def leaf():\n    await asyncio.sleep(1)  # imagine you don\'t know this\n\n\nasync def work():\n    await asyncio.gather(..., job())\n```\n\nNow that code is stuck and and you want to know why.\n\n#### Python built-in\n```py\nStack for <Task pending coro=<job() …> wait_for=<Future pending cb=[<TaskWakeupMethWrapper …>()]> cb=[…]> (most recent call last):\n  File "test/test_stack.py", line 34, in job\n    await foo()\n```\n\n#### This library\n```py\nStack for <Task pending coro=<job() …> wait_for=<Future pending cb=[<TaskWakeupMethWrapper …>()]> cb=[…]> (most recent call last):\n  File "test/test_stack.py", line 34, in job\n    await foo()\n  File "test/test_stack.py", line 38, in foo\n    await bar()\n  File "test/test_stack.py", line 42, in bar\n    await baz()\n  File "test/test_stack.py", line 46, in baz\n    await leaf()\n  File "test/test_stack.py", line 50, in leaf\n    await asyncio.sleep(1)\n  File "/…/asyncio/tasks.py", line 568, in sleep\n    return await future\n  File "<Sentinel>", line 0, in <_asyncio.FutureIter object at 0x7fb6981690d8>: …\n```\n\n### Dependency Graph\n\n<img src="https://raw.github.com/dimaqq/awaitwhat/master/doc/test_future.svg?sanitize=true">\n\n### References\n\nhttps://mail.python.org/archives/list/async-sig@python.org/thread/6E2LRVLKYSMGEAZ7OYOYR3PMZUUYSS3K/\n\n> Hi group,\n>\n> I\'m recently debugging a long-running asyncio program that appears to get stuck about once a week.\n>\n> The tools I\'ve discovered so far are:\n> * high level: `asyncio.all_tasks()` + `asyncio.Task.get_stack()`\n> * low level: `loop._selector._fd_to_key`\n>\n> What\'s missing is the middle level, i.e. stack-like linkage of what is waiting for what. For a practical example, consider:\n>\n> ```py\n> async def leaf(): await somesocket.recv()\n> async def baz(): await leaf()\n> async def bar(): await baz()\n> async def foo(): await bar()\n> async def job(): await foo()\n> async def work(): await asyncio.gather(..., job())\n> async def main(): asyncio.run(work())\n> ```\n>\n> The task stack will contain:\n> * main and body of work with line number\n> * job task with line number pointing to foo\n>\n> The file descriptor mapping, socket fd, `loop._recv()` and a `Future`.\n>\n> What\'s missing are connections `foo->bar->baz->leaf`.\n> That is, I can\'t tell which task is waiting for what terminal `Future`.\n>\n> Is this problem solved in some way that I\'m not aware of?\n> Is there a library or external tool for this already?\n>\n> Perhaps, if I could get a list of all pending coroutines, I could figure out what\'s wrong.\n>\n> If no such API exists, I\'m thinking of the following:\n>\n> ```py\n> async def foo():\n>     await bar()\n>\n> In [37]: dis.dis(foo)\n>   1           0 LOAD_GLOBAL              0 (bar)\n>               2 CALL_FUNCTION            0\n>               4 GET_AWAITABLE\n>               6 LOAD_CONST               0 (None)\n>               8 YIELD_FROM\n>              10 POP_TOP\n>              12 LOAD_CONST               0 (None)\n>              14 RETURN_VALUE\n> ```\n>\n> Starting from a pending task, I\'d get it\'s coroutine and:\n>\n> Get the coroutine frame, and if current instruction is `YIELD_FROM`, then the reference to the awaitable should be on the top of the stack.\n> If that reference points to a pending coroutine, I\'d add that to the "forward trace" and repeat.\n>\n> At some point I\'d reach an awaitable that\'s not a pending coroutine, which may be: another `Task` (I already got those), a low-level `Future` (can be looked up in event loop), an `Event` (tough luck, shoulda logged all `Event`\'s on creation) or a dozen other corner cases.\n>\n> What do y\'all think of this approach?\n>\n> Thanks,\n> D.\n',
    'author': 'Dima Tisnek',
    'author_email': 'dimaqq@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/dimaqq/awaitwhat',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.7',
}
from build import *
build(setup_kwargs)

setup(**setup_kwargs)
