Skip to main content

Typer with first-class async support: unified sync/async commands, callbacks, and lifecycle event handlers.

Project description

async-typer

Typer with first-class async support: async def commands and callbacks work alongside regular sync ones via the same @app.command() decorator — no second API to remember — plus lifecycle event handlers for setting up and tearing down async resources.

Features

  • One decorator, sync or async@app.command() and @app.callback() accept both regular and async def functions. The wrapper is transparent; Typer's --help, option parsing, and type conversion all work as normal.
  • Shared event loop across the command lifecycle — startup handlers, the command body, and shutdown handlers all run on the same asyncio.Runner, so async resources created on startup (connection pools, HTTP sessions, etc.) remain usable by the command and by shutdown.
  • Fully typed — ships with a py.typed marker and strict type hints.
  • Drop-in replacement — re-exports Typer's public API, so from async_typer import Option, Argument, echo, ... works without a second import line.

Installation

pip install async-typer
# or
uv add async-typer

Requires Python 3.11+.

Quick start

from async_typer import AsyncTyper

app = AsyncTyper()


@app.command()
def sync_hello(name: str = "world") -> None:
    print(f"hi {name}")


@app.command()
async def async_hello(name: str = "world") -> None:
    # await anything you need here
    print(f"hello {name}")


if __name__ == "__main__":
    app()

Async callbacks

@app.callback()
async def main(verbose: bool = False) -> None:
    if verbose:
        print("verbose mode")

Lifecycle event handlers

Register startup and shutdown hooks, sync or async. They run on the same event loop as the command body, so shared async resources stay alive across the whole invocation:

import httpx

app = AsyncTyper()
state: dict[str, httpx.AsyncClient] = {}


async def open_client() -> None:
    state["client"] = httpx.AsyncClient()


async def close_client() -> None:
    await state["client"].aclose()


app.add_event_handler("startup", open_client)
app.add_event_handler("shutdown", close_client)


@app.command()
async def fetch(url: str) -> None:
    response = await state["client"].get(url)
    print(response.status_code)

The shutdown handler runs even if the command raises — use it to release resources unconditionally.

Migrating from 0.1.x

The separate async_command / async_callback decorators still work but emit DeprecationWarning. Replace them with the unified command / callback, which auto-detect async def:

# before
@app.async_command()
async def foo(): ...

# after
@app.command()
async def foo(): ...

Development

This repo uses uv, ruff, and ty.

uv sync --dev
uv run pytest
uv run ruff check .
uv run ty check

License

MIT — see LICENSE.txt.

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

async_typer-0.2.1.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

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

async_typer-0.2.1-py3-none-any.whl (7.7 kB view details)

Uploaded Python 3

File details

Details for the file async_typer-0.2.1.tar.gz.

File metadata

  • Download URL: async_typer-0.2.1.tar.gz
  • Upload date:
  • Size: 13.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for async_typer-0.2.1.tar.gz
Algorithm Hash digest
SHA256 d8fecae239cc16186055252f3d64f9aba04788985c5bd4ed9f9b743fd4d78bde
MD5 02d5647175db3021099c275f2790932b
BLAKE2b-256 43ea9e328f928389846ad2296a8acacb87cf0a9d6f05be88f04865c29c15ce26

See more details on using hashes here.

File details

Details for the file async_typer-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: async_typer-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 7.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for async_typer-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7d6feaa38da063f276f5d761ffac5774b49f51233c707038e953260bf5abf755
MD5 f3d7711470cd1bf8f7b17b292f8af3ee
BLAKE2b-256 90ba460be3d859eee666881c2d09a9567d9f9d99e90b4d38415fd7bf03f9926d

See more details on using hashes here.

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