Skip to main content

Dependency injection helper for FastAPI

Project description

dipin

dipin provides a dependency injection container, that primarily aims to work well with FastAPI.

[!IMPORTANT]
dipin is in very early stages - the API will change, and functionality is surprisingly missing.

Motivation

FastAPI's dependency container works well, but can be messy to scale. Out of the box, you can end up with many Annotated[X, Depends()]. Some projects I've worked on have a sprawling di.py, and references to Depends in non-FastAPI code.

dipin aims to:

  1. Remove the need to annotate types in non-FastAPI code with Depends,
  2. Provide a simple API to access dependencies in route-handlers, e.g.:
    from dipin import DI
    
    @app.get("/")
    async def homepage(request: Request, user: DI[AuthenticatedUser]):
        ...
    
    vs
    from .auth import get_authenticated_user
    
    @app.get("/")
    async def homepage(request: Request, user: Annotated[User, Depends(get_authenticated_user)]):
        ...
    

Architecture

TODO

Usage (alpha, buggy, will change)

# di.py

from dipin import DI

# Register a singleton across all requests
from .settings import Settings  # e.g. a pydantic-settings model
DI.register_instance(Settings())

# Register a factory (lazy singleton), called once across all requests
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.ext.asyncio.engine import AsyncEngine

def create_engine(settings: DI[Settings]) -> AsyncEngine:
    return create_async_engine(str(settings.database_dsn))

DI.register_factory(AsyncEngine, get_db_engine, create_once=True)

# Register a factory called per-request
from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.ext.asyncio import async_sessionmaker

async def create_session(engine: DI[AsyncEngine]) -> AsyncSession:
    sessionmaker = async_sessionmaker(
        bind=engine, class_=AsyncSession, expire_on_commit=False
    )
    async with sessionmaker() as session:
        yield session

DI.register_factory(AsyncSession, create_session)
# app.py

from fastapi import FastAPI
from sqlmodel.ext.asyncio.session import AsyncSession

from dipin import DI

app = FastAPI()

@app.get("/")
async def list_orders(session: DI[AsyncSession]):
    qry = "SELECT * FROM orders"
    res = await session.exec(qry)
    orders = res.all()

    return {"orders": orders}

Roadmap

  • Support default arguments in factories
    • e.g. class A: def __init__(self, foo: str = "bar") should be instantiable.
  • Named dependencies
    • e.g. DI["PrivateOpenAIClient"]
    • Out of the box, it seems to lookup the class name (as a deferred annotation), but typing.Literal supports this.
  • Full typing support
    • Currently DI[Class] does not resolve to an instance of Class.
  • Support many types of dependencies
    • Including named (but we won't be able to use DI[...]), and some of those described in python-dependency-injector.
    • Providing our own fastapi.Depends is likely needed.

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

dipin-0.0.3.tar.gz (9.8 kB view details)

Uploaded Source

Built Distribution

dipin-0.0.3-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

File details

Details for the file dipin-0.0.3.tar.gz.

File metadata

  • Download URL: dipin-0.0.3.tar.gz
  • Upload date:
  • Size: 9.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for dipin-0.0.3.tar.gz
Algorithm Hash digest
SHA256 85e0bc8ec7b509aa43ad53457543fb056e524d26fd290ade633f9067d7741578
MD5 9de0aaff09961109262a627b5ca20029
BLAKE2b-256 99d1e939eef6dd59033073191320c3cfed6a8b41da83ea359d579d1e56d1f802

See more details on using hashes here.

File details

Details for the file dipin-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: dipin-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 7.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for dipin-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 97c23d7b4cdd5eb2fcb34ee29313dfe9006018bc2a9a42b3ddb17136ed9f7236
MD5 dfd4112f3b7678909624782bc4a82ee8
BLAKE2b-256 78eaee76432367d9432bcb997f26da1fcd07aa6f2bdb9d7a0619133c2350c087

See more details on using hashes here.

Supported by

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