Skip to main content

Lightweight asyncio task tracking as call tree and DAG

Project description

aionode

Lightweight asyncio task tracking with dependency graphs and progress rendering.

Installation

pip install aionode

For Rich table rendering:

pip install aionode[viz]

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.track(pipeline)(), name="pipeline")
    root_id = await aionode.get_task_id(root)
    graph = aionode.TaskGraph(root_id=root_id)

    await aionode.watch(graph, interval=0.3)
    await root

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))

track(func, start=True)

Tracks a coroutine by registering it in the task graph. Use this for the root task or tasks that don't need node()'s dependency resolution.

root = asyncio.create_task(aionode.track(my_coro)(), name="root")

TaskGraph

Query the dependency graph:

graph = aionode.TaskGraph(root_id=root_id)

graph.nodes()            # All tasks in topological order
graph.roots()            # Tasks with no upstream deps
graph.leaves()           # Tasks with no downstream dependents
graph.upstream(task_id)  # Transitive upstream deps
graph.downstream(task_id)  # Transitive downstream dependents
graph.summary()          # {TaskStatus: count}
graph.critical_path()    # Longest-duration path

Rendering

# Auto-detect Rich or fall back to ANSI text
renderer = aionode.get_render()

# Force plain text
renderer = aionode.get_render(rich=False)

# Live-updating display
await aionode.watch(graph, interval=0.5, renderer=renderer)

Task Inspection

task_id = await aionode.get_task_id(asyncio_task)
info = aionode.get_task(task_id)

info.status        # TaskStatus: WAITING, RUNNING, DONE, FAILED, CANCELLED
info.duration()    # Elapsed seconds
info.description   # 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

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
track(func, start) Track a coroutine in the task graph
get_task_id(task, timeout) Get the task ID for an asyncio.Task
get_task(task_id) Get TaskInfo by ID
remove_task(task_id) Remove a task and its descendants
log(value, end) Append to the current task's logs
make_async(func) Run a sync function in a thread
make_async_generator(gen) Async iterate a sync iterator via threads
TaskGraph(root_id) Create a graph view rooted at a task
TaskGraph.from_task(task) Create a graph from an asyncio.Task
TaskGraph.current() Graph over all tasks in the current loop
get_render(rich, bar_width, ...) Get a configured render function
watch(graph, interval, renderer) Live-render until all tasks finish

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

aionode-0.1.0.tar.gz (7.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aionode-0.1.0-py3-none-any.whl (8.2 kB view details)

Uploaded Python 3

File details

Details for the file aionode-0.1.0.tar.gz.

File metadata

  • Download URL: aionode-0.1.0.tar.gz
  • Upload date:
  • Size: 7.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for aionode-0.1.0.tar.gz
Algorithm Hash digest
SHA256 61f2f812c5384de2857726fc4c6c2071212de9dca25b792adfbf621d5040b1ff
MD5 d2c1c24efddf5c8aabbc963a4e77417a
BLAKE2b-256 230739c76f369e2c16bcf01d6d6b3872fc4bf63e3dc0c3215203e82aa869ce18

See more details on using hashes here.

Provenance

The following attestation bundles were made for aionode-0.1.0.tar.gz:

Publisher: publish.yml on MatteoDep/aionode

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aionode-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: aionode-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for aionode-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d69524a5c22571fbda28c5dc463642cb29fc9d2b54c854931b6e24b24675ddf0
MD5 82963167b9cee9514b478dbe9c187845
BLAKE2b-256 8dcc8a6d08b9437ed22127484cfd86fe73598417e4138fa683e0eaea2750f1d8

See more details on using hashes here.

Provenance

The following attestation bundles were made for aionode-0.1.0-py3-none-any.whl:

Publisher: publish.yml on MatteoDep/aionode

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page