Cute DI framework with scopes and agreeable API for Python dependency injection
npx @tessl/cli install tessl/pypi-dishka@1.6.0A comprehensive Python dependency injection framework designed for applications that need sophisticated object lifecycle management and clean dependency handling. Dishka provides advanced scoping capabilities, automatic finalization for resources, modular provider architecture, and seamless integration with popular Python frameworks.
pip install dishkaimport dishkaCommon usage imports:
from dishka import Container, Provider, Scope, make_container
from dishka import provide, alias, decorate, from_context
from dishka import FromDishka, FromComponentFramework integration imports:
from dishka.integrations.fastapi import setup_dishka, inject, FromDishka
from dishka.integrations.flask import setup_dishka, inject, FromDishka
from dishka.integrations.aiohttp import setup_dishka, inject, FromDishkafrom dishka import Provider, Scope, make_container, provide
from typing import Protocol
# Define your interfaces and classes
class Database(Protocol):
def execute(self, query: str) -> list: ...
class PostgreSQLDatabase:
def __init__(self, connection_string: str):
self.connection_string = connection_string
def execute(self, query: str) -> list:
# Implementation here
return []
class UserService:
def __init__(self, db: Database):
self.db = db
def get_users(self) -> list:
return self.db.execute("SELECT * FROM users")
# Create provider
provider = Provider()
provider.provide(PostgreSQLDatabase, provides=Database, scope=Scope.APP)
provider.provide(UserService, scope=Scope.REQUEST)
@provider.provide(scope=Scope.APP)
def get_connection_string() -> str:
return "postgresql://localhost/mydb"
# Create container
container = make_container(provider)
# Use dependencies
with container() as request_container:
user_service = request_container.get(UserService)
users = user_service.get_users()
container.close()Dishka's architecture is built around several key concepts:
This design enables complex applications to maintain clean dependency boundaries while providing high performance and comprehensive lifecycle management.
Core container functionality for creating, configuring, and managing dependency injection containers with lifecycle management and scope handling.
def make_container(*providers, scopes=Scope, context=None, skip_validation=False) -> Container: ...
def make_async_container(*providers, scopes=Scope, context=None, skip_validation=False) -> AsyncContainer: ...class Container:
def get(self, dependency_type: type[T], component: str = "") -> T: ...
def __call__(self, context=None, scope=None) -> ContextManager[Container]: ...
def close(self, exception=None) -> None: ...
class AsyncContainer:
async def get(self, dependency_type: type[T], component: str = "") -> T: ...
def __call__(self, context=None, scope=None) -> AsyncContextManager[AsyncContainer]: ...
async def close(self, exception=None) -> None: ...Modular provider classes and dependency registration functions for creating reusable dependency factories with flexible configuration options.
class Provider:
def __init__(self, scope: BaseScope = None, component: str = None): ...
def provide(self, source, *, scope=None, provides=None, cache=True) -> None: ...
def alias(self, source, *, provides=None, cache=True, component=None) -> None: ...
def provide(*, scope=None, provides=None, cache=True, recursive=False, override=False): ...
def alias(source, *, provides=None, cache=True, component=None, override=False): ...
def decorate(*, provides=None): ...
def from_context(provides, *, scope=None, override=False): ...Hierarchical scope system for managing dependency lifetimes from application-wide to per-request or custom granular levels.
class Scope(BaseScope):
RUNTIME: ClassVar[Scope]
APP: ClassVar[Scope]
SESSION: ClassVar[Scope]
REQUEST: ClassVar[Scope]
ACTION: ClassVar[Scope]
STEP: ClassVar[Scope]
class BaseScope:
name: str
skip: bool
def new_scope(value: str, *, skip: bool = False) -> BaseScope: ...Scope and Lifecycle Management
Type annotation markers and dependency key system for clean type-safe dependency injection without polluting business logic code.
class FromDishka[T]:
"""Type marker for dependency injection"""
pass
class FromComponent:
def __call__(self, component: str = "") -> FromComponent: ...
class AnyOf[*Args]:
"""Marker for multiple possible dependency types"""
pass
class WithParents[T]:
"""Automatically provide all parent classes/interfaces"""
pass
class DependencyKey:
type_hint: Any
component: str | None
def with_component(self, component: str) -> DependencyKey: ...Ready-to-use integrations for popular Python frameworks with automatic dependency injection setup and middleware configuration.
# Common pattern across integrations
def setup_dishka(container: Container, app: Any) -> None: ...
def inject(func: Callable) -> Callable: ...Available integrations: FastAPI, Flask, Starlette, AIOhttp, Sanic, Litestar, gRPCio, Celery, Aiogram, Click, TaskIQ, FastStream, Telebot, ARQ
Multi-component dependency isolation system allowing different implementations of the same interface to coexist within a single container.
Component = str
DEFAULT_COMPONENT: str = ""Comprehensive validation system for dependency graphs with configurable validation rules and error detection.
class ValidationSettings:
nothing_overridden: bool = False
implicit_override: bool = False
nothing_decorated: bool = True
STRICT_VALIDATION: ValidationSettingsT = TypeVar('T')
Component = str
DEFAULT_COMPONENT: str = ""
class DependencyKey(NamedTuple):
type_hint: Any
component: Component | None
def with_component(self, component: Component) -> DependencyKey: ...
def __str__(self) -> str: ...
class ValidationSettings:
nothing_overridden: bool
implicit_override: bool
nothing_decorated: bool
STRICT_VALIDATION: ValidationSettings
DEFAULT_VALIDATION: ValidationSettings
class BaseScope:
name: str
skip: bool