Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit d3792b0

Browse files
authored
Merge pull request #32 from dimaqq/incoming
Dep update and cleanup after PR merge
2 parents 4125478 + 460b1fc commit d3792b0

File tree

13 files changed

+530
-354
lines changed

13 files changed

+530
-354
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ __pycache__/
77
/awaitwhat/*.so
88
graph.dot
99
graph.svg
10+
.vscode/

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
2-
- repo: https://github.com/ambv/black
3-
rev: stable
2+
- repo: https://github.com/psf/black
3+
rev: 21.6b0
44
hooks:
55
- id: black
6-
python_version: python3.8
6+
python_version: python3.9

awaitwhat/blocker.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import random
33
from . import sleep
44
from .stack import task_get_stack
5+
from . import wait_for
56

67

78
def blockers(task):
@@ -12,8 +13,12 @@ def blockers(task):
1213

1314
stack = task_get_stack(task, None)
1415

15-
if len(stack) > 2 and sleep.mine(stack[-2]):
16-
return [sleep.decode(stack[-2])]
16+
if len(stack) > 2:
17+
if sleep.mine(stack[-2]):
18+
return [sleep.decode(stack[-2])]
19+
elif wait_for.mine(stack[-2]):
20+
status, awaitable = wait_for.decode(stack[-2])
21+
return [status, awaitable]
1722

1823
# asyncio.gather()
1924
try:

awaitwhat/dot.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55

66
def label(vertex):
7-
""" Graph vertex label in dot format """
7+
"""Graph vertex label in dot format"""
88
label = f"{vertex.name} {vertex.state or ''}\n{vertex.traceback or ''}"
9+
if not label.endswith("\n"):
10+
label += "\n"
911
label = json.dumps(label).replace("\\n", r"\l")
1012
return f"[label={label}]"
1113

awaitwhat/graph.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ def new(tasks) -> Tuple[Set[Vertex], List[Edge]]:
1717
edges = list()
1818

1919
for who in tasks:
20-
src = Vertex.new(who, current)
20+
children = blockers(who)
21+
src = Vertex.new(
22+
who, current, extra_text=[c for c in children if isinstance(c, str)]
23+
)
2124
vertices.add(src)
22-
for what in blockers(who):
25+
for what in children:
2326
dst = Vertex.new(what, current)
2427
vertices.add(dst)
2528
edges.append(Edge(src, dst))
@@ -41,7 +44,8 @@ def __eq__(self, other):
4144
return isinstance(other, Vertex) and self.task == other.task
4245

4346
@classmethod
44-
def new(cls, task, current):
47+
def new(cls, task, current, *, extra_text=()):
48+
extra = "\n".join(extra_text)
4549
if isinstance(task, asyncio.Task):
4650
buf = io.StringIO()
4751
task_print_stack(task, None, buf)
@@ -53,11 +57,14 @@ def new(cls, task, current):
5357
state = "done"
5458
else:
5559
state = "current" if task is current else "pending"
56-
return cls(name, state, concise_stack_trace(buf.getvalue()), task)
60+
traceback = "\n".join(
61+
filter(None, (concise_stack_trace(buf.getvalue()), extra))
62+
)
63+
return cls(name, state, traceback, task)
5764
elif isinstance(task, asyncio.Future):
58-
return cls("Future", None, None, task)
65+
return cls("Future", None, extra, task)
5966
else:
60-
return cls(str(task), None, None, task)
67+
return cls(str(task), None, extra, task)
6168

6269

6370
@dataclass(frozen=True)

awaitwhat/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ def clean(line):
1313
line = re.sub('[^"]*/lib/python[0-9][.][0-9]/', "", line)
1414
return line
1515

16-
return '\n'.join(filter(None, (clean(line) for line in trace.split('\n'))))
16+
return "\n".join(filter(None, (clean(line) for line in trace.split("\n"))))

awaitwhat/wait_for.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import asyncio
2+
3+
4+
def mine(frame):
5+
return asyncio.wait_for.__code__ == frame.f_code
6+
7+
8+
def decode(frame):
9+
try:
10+
timeout = frame.f_locals["timeout"]
11+
except Exception:
12+
timeout = "?"
13+
try:
14+
timeout_handle_deadline = frame.f_locals["timeout_handle"].when()
15+
now = frame.f_locals["waiter"].get_loop().time()
16+
timeout_remaining = timeout_handle_deadline - now
17+
except Exception:
18+
timeout_remaining = "?"
19+
try:
20+
awaitable = frame.f_locals["fut"]
21+
except Exception:
22+
awaitable = None
23+
return [
24+
f"asyncio.wait_for: timeout {timeout} remaining {timeout_remaining}",
25+
awaitable,
26+
]

build.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from distutils.core import Extension
22

3+
34
def build(setup_kwargs):
45
setup_kwargs["ext_modules"] = [Extension("awaitwhat._what", ["awaitwhat/what.c"])]

examples/test_same_future.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import awaitwhat
33

44

5-
global_futures = list() # Structure to hold a global future
5+
global_futures = list() # Structure to hold a global future
6+
67

78
async def main():
89
# generate a global future

examples/test_wait_for.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import asyncio
2+
from examples.test_shield import frob_a_branch
3+
import awaitwhat
4+
5+
6+
FUTURES = []
7+
8+
9+
async def main():
10+
t = asyncio.create_task(test())
11+
await do_work()
12+
await t
13+
14+
15+
async def do_work():
16+
loop = asyncio.get_running_loop()
17+
f = loop.create_future()
18+
FUTURES.append(f)
19+
branch = frob_a_branch(f)
20+
await asyncio.wait_for(branch, 15)
21+
22+
23+
async def frob_a_branch(f):
24+
await f
25+
26+
27+
def name(t):
28+
try:
29+
# Python3.8
30+
return t.get_name()
31+
except AttributeError:
32+
return f"Task-{id(t)}"
33+
34+
35+
async def test():
36+
import sys
37+
38+
await asyncio.sleep(1)
39+
try:
40+
tt = asyncio.all_tasks()
41+
print(awaitwhat.dot.dumps(tt))
42+
finally:
43+
for f in FUTURES:
44+
f.set_result(None)
45+
46+
47+
if __name__ == "__main__":
48+
asyncio.run(main())

0 commit comments

Comments
 (0)