Skip to content

Instantly share code, notes, and snippets.

@melmi
Last active August 30, 2023 19:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melmi/4f2f98ef8d9b515a80d520e478d79989 to your computer and use it in GitHub Desktop.
Save melmi/4f2f98ef8d9b515a80d520e478d79989 to your computer and use it in GitHub Desktop.
This a demo on how we can use an IoC container with FastAPI. Checkout my full article here: https://medium.com/@mohammad.elmi/how-to-use-fastapi-with-an-ioc-framework-f32c67d8c59b
import functools
from typing import Annotated, Any, Callable, Protocol, Type, TypeVar
from fastapi import APIRouter, Depends, FastAPI, Request
import punq
# domain - no dependency to FastAPI or IoC
class Greeter(Protocol):
def greet(self) -> str: ...
class WorldGreeter(Greeter):
def greet(self) -> str:
return 'Hello World!'
# IoC
def get_container() -> punq.Container:
container = punq.Container()
container.register(Greeter, WorldGreeter)
return container
# Helper - No dependency to app or container
T = TypeVar('T')
def Service(t: Type[T]) -> Any: # noqa: N802
def resolver(t: Type[T], request: Request) -> Callable[[], T]:
return request.app.state.ioc_container.resolve(t)
return Depends(functools.partial(resolver, t))
# API - No dependency to app or container
router = APIRouter()
@router.get("/greet")
async def greet(greeter: Annotated[Greeter, Service(Greeter)]):
return {"message": greeter.greet()}
# app
app = FastAPI()
app.state.ioc_container = get_container()
app.include_router(router)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment