Skip to main content

oapi-gen-dishka

Inject Dishka dependencies into the async methods called by an oapi-gen router. Generated code stays unchanged. The integration reuses Dishka's native Starlette request container, so operation handlers, security handlers, and ordinary Starlette endpoints share the same Scope.REQUEST instances.

Use the same version of oapi-gen-dishka as the oapi-gen generator that produced your application code. Both packages are published together; see the release instructions.

uv add oapi-gen-dishka

This directory is also independently buildable. To install from a local checkout:

uv add /path/to/oapi-gen/packages/oapi-gen-dishka

Usage

The example uses the repository's complete Cats specification. Generate it into your application's package:

oapi-gen generate packages/oapi-gen/tests/fixtures/cats.openapi.yaml --output app/http/generated
from contextlib import asynccontextmanager
from uuid import UUID, uuid4

from dishka import FromDishka, Provider, Scope, make_async_container, provide
from starlette.applications import Starlette
from oapi_gen_dishka import inject, setup_dishka

from app.http.generated import Handlers, contracts, create_router, models


class CatsRepository:
    def __init__(self):
        self.cats: dict[UUID, models.Cat] = {}


class CatsController:
    @inject
    async def list_cats(
        self,
        request: contracts.ListCats.Request,
        *,
        repository: FromDishka[CatsRepository],
    ) -> contracts.ListCats.Response:
        cats = list(repository.cats.values())
        return contracts.ListCats.Ok(body=cats[: request.limit])

    @inject
    async def create_cat(
        self,
        request: contracts.CreateCat.Request,
        *,
        repository: FromDishka[CatsRepository],
    ) -> contracts.CreateCat.Response:
        cat = models.Cat(id=uuid4(), name=request.body.name)
        repository.cats[cat.id] = cat
        return contracts.CreateCat.Created()

    @inject
    async def show_cat_by_id(
        self,
        request: contracts.ShowCatById.Request,
        *,
        repository: FromDishka[CatsRepository],
    ) -> contracts.ShowCatById.Response:
        cat = repository.cats.get(request.cat_id)
        if cat is None:
            raise contracts.ShowCatById.NotFound(
                body=models.HttpError(message="Cat not found"),
            )
        return contracts.ShowCatById.Ok(body=cat)


class AppProvider(Provider):
    # This in-memory example keeps cats between requests in one process.
    repository = provide(CatsRepository, scope=Scope.APP)


container = make_async_container(AppProvider())


@asynccontextmanager
async def lifespan(app: Starlette):
    try:
        yield
    finally:
        await container.close()


router = create_router(Handlers(cats=CatsController()), prefix="/api")
app = Starlette(lifespan=lifespan, routes=router.routes)
setup_dishka(container, app)

Use Scope.REQUEST for services or database sessions that must be recreated for each request. Dishka resolves dependencies from the normal provider graph and finalizes generator providers at the end of the request, including on exceptions. Add Dishka's StarletteProvider() from dishka.integrations.starlette when a provider needs starlette.requests.Request.

@inject also works on generated security handler methods. Use dishka.integrations.starlette.inject on ordinary Starlette endpoints; both decorators resolve from the same container after the single setup call above.

Boundaries

  • Async HTTP handlers only. WebSockets, sync containers, and background work outside the request lifetime are not supported by this decorator.

  • Call this package's setup_dishka once, before startup, instead of calling dishka.integrations.starlette.setup_dishka separately.

  • The controller instance passed to Handlers is shared. Keep request-specific state in local variables and injected dependencies, not on self.

  • Providers must register dependencies; FromDishka[T] selects the registered type and does not register it automatically. Dishka components are supported.

  • Runtime signatures omit injected parameters and retain the remaining annotations. The decorator preserves the static response type but uses Callable[..., ...] for arguments, since Python typing cannot remove arbitrary FromDishka parameters. Annotate controller references with the generated protocol when calling them directly to check request argument types:

    controller: contracts.CatsHandler = CatsController()
    

Development

uv sync --all-packages
uv run --all-packages --directory packages/oapi-gen-dishka pytest
uv run --all-packages --directory packages/oapi-gen-dishka ruff check .
uv run --all-packages --directory packages/oapi-gen-dishka basedpyright
uv build --package oapi-gen-dishka --out-dir dist

Run these commands from the repository root; the workspace uses one root lockfile. The workspace dependency on oapi-gen is used only for integration tests; the published wheel does not depend on the generator at runtime.

Metadata

Release files for oapi-gen-dishka 0.1.10

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

Source distribution (sdist)

Source distribution for oapi-gen-dishka 0.1.10
File Size Uploaded Provenance Actions
oapi_gen_dishka-0.1.10.tar.gz 9.2 kB With provenance Details for oapi_gen_dishka-0.1.10.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for oapi-gen-dishka 0.1.10
File Interpreter ABI Platform Actions
oapi_gen_dishka-0.1.10-py3-none-any.whl Python 3 none any Details for oapi_gen_dishka-0.1.10-py3-none-any.whl

Total release size: 14.2 kB

Release files / oapi_gen_dishka-0.1.10.tar.gz

Download URL oapi_gen_dishka-0.1.10.tar.gz
Size 9.2 kB
Tags Source
SHA-256 checksum
How to use checksums
973a4e92be0a3f1cdcead7d42b2a1450f3d81f88b58858d211c1dd70c97cb67e
BLAKE2b-256 checksum
How to use checksums
6870c0f1a02c5b2d86c5cd39f1bc5d11282fdcef04349a2e95d79d4e44cbef2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 22, 2026.

Transparency log

Release files / oapi_gen_dishka-0.1.10-py3-none-any.whl

Download URL oapi_gen_dishka-0.1.10-py3-none-any.whl
Size 5.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
afdf693f5f522008a810f123cdd133c75b85d2c836d86e2ac7591a96363f5375
BLAKE2b-256 checksum
How to use checksums
11f579e135792107f34de0fc904cd35930a90b5a4b9f4d3cdad67e4f01d531eb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 22, 2026.

Transparency log

Security for oapi-gen-dishka 0.1.10

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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for oapi_gen_dishka-0.1.10.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 Sep 22, 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