Skip to content

Getting Started

Set up a development environment, register providers, and run your first calls with FastDI.

Prerequisites: Python 3.9+ and a stable Rust toolchain.

1. Install Dependencies

pip install fastdi-core
# or set up a local dev environment:
uv sync --dev
uv run maturin develop -r -q

2. Minimal Sync Flow

from typing import Annotated, Protocol
from fastdi import Container, Depends, provide, inject


container = Container()

class Service(Protocol):
    def ping(self) -> dict: ...

@provide(container, singleton=True)
def get_db() -> dict:
    return {"db": "connection"}

@provide(container)
def get_service(db: Annotated[dict, Depends(get_db)]) -> Service:
    class Impl:
        def __init__(self, db):
            self._db = db
        def ping(self) -> dict:
            return {"ok": True, "via": self._db["db"]}
    return Impl(db)

@inject(container)
def handler(service: Annotated[Service, Depends(get_service)]):
    return service.ping()

print(handler())

3. Minimal Async Flow

import asyncio
from typing import Annotated
from fastdi import Container, Depends, provide, ainject


container = Container()

@provide(container)
async def get_number() -> int:
    return 41

@ainject(container)
async def handler(value: Annotated[int, Depends(get_number)]) -> int:
    return value + 1

print(asyncio.run(handler()))

4. Request Scope (per async task)

import asyncio
from typing import Annotated
from fastdi import Container, Depends, provide, ainject


container = Container()

@provide(container, scope="request")
async def request_id() -> object:
    return object()

@ainject(container)
async def within_task(
    first: Annotated[object, Depends(request_id)],
    second: Annotated[object, Depends(request_id)],
) -> bool:
    return first is second

print(asyncio.run(within_task()))  # True

Next Steps