Skip to main content

tripack-container

PyPI Python CI License: MIT

High-level IoC container API of the Tripack framework: declarations, wiring, modules and bootstrap helpers used by application code.

tripack-container is the ergonomic surface most consumers import. It is built on top of the resolver in tripack-runtime and the protocols defined in tripack-contracts.

Install

uv add tripack-container
# or
pip install tripack-container

Optional extras:

# YAML configuration loader (PyYAML)
pip install 'tripack-container[yaml]'

# FastAPI integration (TripackAPI + Inject)
pip install 'tripack-container[fastapi]'

FastAPI integration

tripack_container.fastapi ships a drop-in FastAPI subclass that owns the container lifecycle and rewrites Annotated[T, Inject] parameters to FastAPI Depends at route registration time.

from pathlib import Path
from typing import Annotated, Protocol
from tripack_container import Inject
from tripack_container.fastapi import TripackAPI
from tripack_container.loaders import load_json


class Clock(Protocol):
    def now(self) -> float: ...


app = TripackAPI(
    container_factory=lambda: load_json(Path("container.json")),
)


@app.get("/now")
def now(clock: Annotated[Clock, Inject]) -> dict[str, float]:
    return {"now": clock.now()}

Three things happen behind the scenes:

  1. The container is built (sync or async factory both work) at lifespan startup and aclosed at shutdown. A user-supplied lifespan= keyword still runs, layered inside the container's lifecycle.
  2. Every HTTP request runs inside container.ascope() so SCOPED bindings cache per-request and their teardown fires at request end.
  3. Each Annotated[T, Inject] parameter is rewritten to Annotated[T, Depends(...)] at route construction time; FastAPI's own dependency system then resolves T from app.state.container per request. app.dependency_overrides continues to work for tests.

The Inject marker

Form Meaning
Annotated[T, Inject] Resolve T from the container; raise on miss.
Annotated[T | None, Inject] Resolve T; return None if unbound (implicit optional from the union).
Annotated[T, Inject(optional=True)] Same as the union form, explicit flag.
Annotated[T, Inject(token="named")] Override the resolution token (named bindings).

Sub-routers: TripackRouter

Sub-routers built with the default APIRouter analyse their routes at decoration time, before app.include_router runs, and crash on the bare Inject marker. Use TripackRouter instead - it defaults its route_class to the inject-aware variant:

from tripack_container.fastapi import TripackRouter

sub = TripackRouter(prefix="/v2")


@sub.get("/now")
def v2_now(clock: Annotated[Clock, Inject]) -> dict[str, float]:
    return {"now": clock.now()}


app.include_router(sub)

Architecture: three layers, one marker

Layer 3 (per-framework adapter)  tripack_container.fastapi   - TripackAPI subclass
Layer 2 (ASGI-agnostic)          tripack_container.asgi      - container_lifespan
                                                              + ContainerScopeMiddleware
Layer 1 (framework-agnostic)     tripack_container._inject   - Inject marker
  • Layer 1 - Inject marker. A pure data class. No ASGI, no FastAPI, no Starlette. Every adapter reads it the same way through parse_inject(annotation).
  • Layer 2 - ASGI primitives. container_lifespan is an @asynccontextmanager you can plug into any framework that accepts a lifespan (Starlette, FastAPI, Litestar, raw ASGI). ContainerScopeMiddleware is a pure ASGI middleware that opens container.ascope() per HTTP/WebSocket request. Test coverage includes a Starlette-only path that wires both primitives without importing FastAPI.
  • Layer 3 - FastAPI adapter. TripackAPI composes the ASGI layer and adds the FastAPI-specific concern (rewriting Annotated[T, Inject] to Depends). A Starlette adapter would be a similar L3 module that re-uses L1 + L2 verbatim and adds its own route-level resolution mechanism.

The subclass choice for TripackAPI (rather than composite) is documented in the module docstring; the headline is that subclassing keeps isinstance(app, FastAPI) truthy so every FastAPI tool (TestClient, deployment runners, app.dependency_overrides) keeps working untouched while the constructor surface mirrors FastAPI(...).

Other ASGI frameworks (Starlette, Litestar, raw ASGI)

The L2 primitives - container_lifespan + ContainerScopeMiddleware - work without FastAPI. The ASGI integration guide ships the Starlette and raw-ASGI wiring templates plus the custom-accessor recipe for frameworks that keep app state outside app.state. Handlers there resolve from request.app.state.container manually - the Annotated[T, Inject] rewriting in L3 is the only piece that is FastAPI-specific.

Documentation

Project site: https://goabonga.github.io/tripack/.

License

MIT - see LICENSE.

Metadata

Release files for tripack-container 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tripack-container 0.3.0
File Size Uploaded Provenance
tripack_container-0.3.0.tar.gz 51.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tripack-container 0.3.0
File Interpreter ABI Platform
tripack_container-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 85.2 kB

Release files / tripack_container-0.3.0.tar.gz

Download URL tripack_container-0.3.0.tar.gz
Size 51.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ef017f236c3de2bd1eccc57bf4b676752036898e63523379d775ddef39c619b5
BLAKE2b-256 checksum
How to use checksums
2fba000b715d0a7f0a7c9ea9369f4e482534d8638c19eec4b115c2aee9cbdc65
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 19, 2026.

Transparency log

Release files / tripack_container-0.3.0-py3-none-any.whl

Download URL tripack_container-0.3.0-py3-none-any.whl
Size 33.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e9cc8c81e5916235e6ba6c852b26b6709abda6181ac109bba1d8f366fc65646d
BLAKE2b-256 checksum
How to use checksums
ca1c5e9246e0c3018efc0ad174528ce83830c847273bf34ed641bf58bd740828
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 19, 2026.

Transparency log

Security for tripack-container 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for tripack_container-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page