Lightweight asyncio task tracking as call tree and DAG
Project description
aionode
Lightweight asyncio task tracking as call tree and DAG.
Installation
pip install aionode
Quick Start
import asyncio
import aionode
async def fetch_data() -> list[int]:
await asyncio.sleep(1)
return list(range(100))
async def process(data: list[int]) -> int:
await asyncio.sleep(0.5)
return sum(data)
async def pipeline() -> None:
async with asyncio.TaskGroup() as tg:
fetch = tg.create_task(aionode.node(fetch_data)(), name="fetch")
tg.create_task(aionode.node(process)(aionode.resolve(fetch)), name="process")
async def main() -> None:
root = asyncio.create_task(aionode.node(pipeline)(), name="pipeline")
await root
for info in aionode.walk_dag():
print(f"{info.name}: {info.status} ({info.duration():.2f}s)")
asyncio.run(main())
Core Concepts
node(func, wait_for=[], track=True, auto_progress=True)
Wraps an async function as a DAG node. Use resolve() to pass awaitables as arguments — they are gathered concurrently before the function is called. Sync functions must be wrapped with make_async first.
# Async function — pass upstream tasks with resolve()
fetch = tg.create_task(aionode.node(fetch_data)(), name="fetch")
process_task = tg.create_task(aionode.node(process)(aionode.resolve(fetch)), name="process")
# Sync function — wrap with make_async first
summarize = tg.create_task(
aionode.node(aionode.make_async(my_sync_fn))(aionode.resolve(process_task)),
name="summarize",
)
# Side-only dependency (no value passed): use wait_for
task_b = tg.create_task(aionode.node(cleanup, wait_for=[fetch])(), name="cleanup")
resolve(awaitable)
Marks an awaitable to be resolved before being passed as an argument to node(). This preserves type information — the type checker sees resolve(task: Task[T]) as returning T.
result = await aionode.node(process)(aionode.resolve(upstream_task))
walk_tree / walk_dag
Iterate over tracked tasks after they have been created.
# DFS pre-order through the call tree (parent → children)
for info in aionode.walk_tree():
print(info.name, info.status)
# Topological order over the DAG (deps → dependents)
for info in aionode.walk_dag():
print(info.name, info.status)
Both accept an optional root argument (an asyncio.Task or task id). Passing None (the default) includes all tasks in the current event loop.
sync_node(name, auto_progress=True)
Track sync code blocks as child nodes in the task tree — without spawning extra threads. Use inside functions running in a make_async thread.
@aionode.make_async
def compute_pipeline(state):
with aionode.sync_node("extract"):
extract(state)
with aionode.sync_node("transform"):
transform(state)
with aionode.sync_node("load"):
load(state)
# Each block appears as a named child in walk_tree() with its own timing.
sync_node can also be used directly inside async node-wrapped code for lightweight sync blocks. Be aware that the wrapped code runs on the event loop thread and blocks other coroutines — keep it short, or use make_async to offload to a thread.
Also works as a decorator:
@aionode.sync_node
def extract(state):
...
# Or with a custom/parameterized name:
@aionode.sync_node(name="compute_{table}")
def process(table: str, state):
...
Task Inspection
task_id = await aionode.get_task_id(asyncio_task)
info = aionode.get_task_info(task_id)
info.status # TaskStatus: WAITING, RUNNING, DONE, FAILED, CANCELLED
info.duration() # Elapsed seconds
info.name # Task name
info.deps # Upstream dependency IDs
info.dependents # Downstream dependent IDs
info.logs # Accumulated log output
await aionode.log("processing record 42") # Append to current task's logs
# Get TaskInfo for the currently running tracked task
info = aionode.current_task_info()
API Reference
| Function | Description |
|---|---|
node(func, wait_for, track, auto_progress) |
Wrap an async function as a DAG node |
resolve(awaitable) |
Mark an awaitable to be resolved as a node argument |
get_task_id(task, timeout) |
Get the task ID for an asyncio.Task |
get_task_info(task_id) |
Get TaskInfo by ID |
current_task_info() |
Get TaskInfo for the currently running tracked task |
remove_task(task_id) |
Remove a task and its descendants |
log(value, end) |
Append to the current task's logs |
sync_node(name, auto_progress) |
Track a sync block or function as a child node |
make_async(func) |
Run a sync function in a thread |
make_async_generator(gen) |
Async iterate a sync iterator via threads |
walk_tree(root) |
DFS pre-order through the call tree |
walk_dag(root) |
Topological order over the DAG |
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aionode-0.3.0.tar.gz.
File metadata
- Download URL: aionode-0.3.0.tar.gz
- Upload date:
- Size: 9.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d688eca31e256ac6ae7fe6a70df022809e022df533e36461c7601c05c874270
|
|
| MD5 |
eda06e12b6e4b122447f4db3c918da3d
|
|
| BLAKE2b-256 |
4b4ec908cda16b24d8481dc572e360f881edf1393437721fb3fdb4640c0aa7e0
|
Provenance
The following attestation bundles were made for aionode-0.3.0.tar.gz:
Publisher:
publish.yml on MatteoDep/aionode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aionode-0.3.0.tar.gz -
Subject digest:
2d688eca31e256ac6ae7fe6a70df022809e022df533e36461c7601c05c874270 - Sigstore transparency entry: 1342720998
- Sigstore integration time:
-
Permalink:
MatteoDep/aionode@76449184e81395859155156215ff35fa782e0c05 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/MatteoDep
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76449184e81395859155156215ff35fa782e0c05 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aionode-0.3.0-py3-none-any.whl.
File metadata
- Download URL: aionode-0.3.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c77298cdf670ed3f507b236e40e8f01dfec45f4c68e2d1ef79b10f442c8caacf
|
|
| MD5 |
0dbc2ae9c4919968efc0d8962e227ddc
|
|
| BLAKE2b-256 |
94f98cda08b53f334f86e4e41e3f2bf0a08351362920e880eab912fc17d20c03
|
Provenance
The following attestation bundles were made for aionode-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on MatteoDep/aionode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aionode-0.3.0-py3-none-any.whl -
Subject digest:
c77298cdf670ed3f507b236e40e8f01dfec45f4c68e2d1ef79b10f442c8caacf - Sigstore transparency entry: 1342721001
- Sigstore integration time:
-
Permalink:
MatteoDep/aionode@76449184e81395859155156215ff35fa782e0c05 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/MatteoDep
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76449184e81395859155156215ff35fa782e0c05 -
Trigger Event:
push
-
Statement type: