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.0.tar.gz (12.8 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.0-py3-none-any.whl (7.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: async_typer-0.2.0.tar.gz
  • Upload date:
  • Size: 12.8 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.0.tar.gz
Algorithm Hash digest
SHA256 a04aae9bcff6b7da3fe4ae7c07e09e1a0aa39ad338e8ee93bd72cedf3c3f2754
MD5 fe4c6812719efc1a98a1d66900422863
BLAKE2b-256 1b6cffab26e1173bea9ee2178833fb7e639e07c5a3d52f695fc086da19944e67

See more details on using hashes here.

File details

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

File metadata

  • Download URL: async_typer-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 7.5 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c9f490336206520715180567eb8d26b8050969002bc9a339b9948f023c2e8bd5
MD5 aaef03ebb7fecefa4d9601c4f2ebebcb
BLAKE2b-256 943544b843f038b61596223cb89295e5edd8dad29797e59947c54fcee585a534

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