### FastStream Application Setup with Modern-DI Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/faststream.md Example of setting up a FastStream application with Modern-DI, including an application-scoped singleton provider and a subscriber that resolves dependencies by type. ```python import datetime import typing import faststream from faststream.nats import NatsBroker import modern_di_faststream from modern_di import Container, Group, Scope, providers broker = NatsBroker() app = faststream.FastStream(broker=broker) def create_singleton() -> datetime.datetime: return datetime.datetime.now(tz=datetime.timezone.utc) class AppGroup(Group): singleton = providers.Factory( scope=Scope.APP, creator=create_singleton, cache_settings=providers.CacheSettings() ) # Register your groups ALL_GROUPS = [AppGroup] # Setup DI with your groups modern_di_faststream.setup_di(app, Container(groups=ALL_GROUPS)) @broker.subscriber("in") async def read_root( instance: typing.Annotated[ datetime.datetime, modern_di_faststream.FromDI(datetime.datetime), # Resolve by type instead of provider ], ) -> datetime.datetime: return instance ``` -------------------------------- ### Install modern-di-litestar with poetry Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/litestar.md Install the modern-di-litestar package using poetry. ```bash poetry add modern-di-litestar ``` -------------------------------- ### Install modern-di with poetry Source: https://github.com/modern-python/modern-di/blob/main/docs/index.md Install the modern-di package using poetry. ```bash poetry add modern-di ``` -------------------------------- ### Install modern-di with uv Source: https://github.com/modern-python/modern-di/blob/main/docs/index.md Install the modern-di package using the uv package manager. ```bash uv add modern-di ``` -------------------------------- ### Install Dependencies Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Installs project dependencies using uv, ensuring a consistent environment. ```bash just install # uv lock --upgrade && uv sync --all-extras --frozen --group lint ``` -------------------------------- ### Install modern-di-typer with uv Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/typer.md Use 'uv add' to install the modern-di-typer package. ```bash uv add modern-di-typer ``` -------------------------------- ### Install modern-di-typer with pip Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/typer.md Use 'pip install' to install the modern-di-typer package. ```bash pip install modern-di-typer ``` -------------------------------- ### Install modern-di-pytest with uv Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/pytest.md Install the modern-di-pytest package using uv. ```bash uv add --dev modern-di-pytest ``` -------------------------------- ### Basic FastAPI App Setup with modern-di Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/fastapi.md Set up a FastAPI application with modern-di, registering an application-scoped singleton and resolving it in a route. ```python import datetime import contextlib import typing import fastapi import modern_di_fastapi from modern_di import Container, Group, Scope, providers app = fastapi.FastAPI() def create_singleton() -> datetime.datetime: return datetime.datetime.now(tz=datetime.timezone.utc) class AppGroup(Group): singleton = providers.Factory( scope=Scope.APP, creator=create_singleton, cache_settings=providers.CacheSettings() ) # Register your groups ALL_GROUPS = [AppGroup] # Setup DI with your groups modern_di_fastapi.setup_di(app, Container(groups=ALL_GROUPS)) @app.get("/") async def read_root( instance: typing.Annotated[ datetime.datetime, modern_di_fastapi.FromDI(datetime.datetime), # Resolve by type instead of provider ], ) -> datetime.datetime: return instance ``` -------------------------------- ### Install modern-di-litestar with pip Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/litestar.md Install the modern-di-litestar package using pip. ```bash pip install modern-di-litestar ``` -------------------------------- ### Manual Dependency Wiring Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This example demonstrates manual dependency wiring, highlighting its potential to become unwieldy and scattered at scale. ```python config = AppConfig() db = DatabaseConnection(config) email = EmailService(config) user_service = UserService(db, email) ``` -------------------------------- ### Install modern-di with pip Source: https://github.com/modern-python/modern-di/blob/main/docs/index.md Install the modern-di package using pip. ```bash pip install modern-di ``` -------------------------------- ### Swapping Implementations with DI Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This example illustrates how DI allows for easy swapping of dependency implementations, such as using different cache backends for production, development, or testing. ```python class UserService: def __init__(self, cache: CacheBackend) -> None: self.cache = cache # Swap implementations easily service = UserService(cache=RedisCache()) # Production service = UserService(cache=DictCache()) # Development service = UserService(cache=MockCache()) # Testing ``` -------------------------------- ### Install modern-di-faststream with uv Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/faststream.md Use this command to add the modern-di-faststream package to your project when using uv. ```bash uv add modern-di-faststream ``` -------------------------------- ### Install modern-di-litestar with uv Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/litestar.md Install the modern-di-litestar package using the uv package manager. ```bash uv add modern-di-litestar ``` -------------------------------- ### Install modern-di-fastapi Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/fastapi.md Install the modern-di-fastapi package using your preferred package manager. ```bash uv add modern-di-fastapi ``` ```bash pip install modern-di-fastapi ``` ```bash poetry add modern-di-fastapi ``` -------------------------------- ### Singleton Provider (1.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Example of defining a Singleton provider in version 1.x. ```python from modern_di import Scope, providers singleton = providers.Singleton(Scope.APP, create_singleton) ``` -------------------------------- ### Install modern-di-typer with poetry Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/typer.md Use 'poetry add' to install the modern-di-typer package. ```bash poetry add modern-di-typer ``` -------------------------------- ### Install modern-di-pytest with poetry Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/pytest.md Install the modern-di-pytest package using poetry. ```bash poetry add --group dev modern-di-pytest ``` -------------------------------- ### FastAPI Application Setup with modern-di Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/fastapi.md Sets up a FastAPI application with a modern-di container. The `setup_di` function registers the container and context providers. ```python import fastapi import modern_di import modern_di_fastapi from app import ioc def build_app() -> fastapi.FastAPI: app = fastapi.FastAPI() di_container = modern_di.Container(groups=[ioc.Dependencies]) modern_di_fastapi.setup_di(app, di_container) return app ``` -------------------------------- ### Resource Provider (1.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Example of defining a Resource provider in version 1.x. ```python from modern_di import Scope, providers resource = providers.Resource(Scope.REQUEST, create_resource) ``` -------------------------------- ### Install modern-di-faststream with poetry Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/faststream.md Use this command to add the modern-di-faststream package to your project when using poetry. ```bash poetry add modern-di-faststream ``` -------------------------------- ### Install modern-di-pytest with pip Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/pytest.md Install the modern-di-pytest package using pip. ```bash pip install modern-di-pytest ``` -------------------------------- ### Basic Litestar Application with Modern DI Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/litestar.md Demonstrates a basic Litestar application setup with Modern DI, resolving a datetime singleton dependency by type. ```python import datetime import typing from litestar import Litestar, get import modern_di_litestar from modern_di import Container, Group, Scope, providers def create_singleton() -> datetime.datetime: return datetime.datetime.now(tz=datetime.timezone.utc) class AppGroup(Group): singleton = providers.Factory( scope=Scope.APP, creator=create_singleton, cache_settings=providers.CacheSettings() ) # Register your groups ALL_GROUPS = [AppGroup] @get("/", dependencies={"injected": modern_di_litestar.FromDI(datetime.datetime)}) # Resolve by type async def index(injected: datetime.datetime) -> str: return injected.isoformat() app = Litestar( route_handlers=[index], plugins=[modern_di_litestar.ModernDIPlugin(Container(groups=ALL_GROUPS))], ) ``` -------------------------------- ### Install modern-di-faststream with pip Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/faststream.md Use this command to add the modern-di-faststream package to your project when using pip. ```bash pip install modern-di-faststream ``` -------------------------------- ### Automatic Sub-Dependency Resolution Example Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/resolving.md Demonstrates how Modern-DI automatically resolves sub-dependencies based on type annotations. This example shows a `DatabaseConnection` being created, which requires a `DatabaseConfig`. The `DatabaseConfig` is automatically resolved and injected because its type matches a registered provider. ```python import dataclasses from modern_di import Group, Container, Scope, providers @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class DatabaseConfig: host: str port: int @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class DatabaseConnection: config: DatabaseConfig # Automatically resolved by type timeout: int = 30 # Uses default value class Dependencies(Group): db_config = providers.Factory( creator=DatabaseConfig, kwargs={"host": "localhost", "port": 5432} ) db_connection = providers.Factory( creator=DatabaseConnection ) container = Container(groups=[Dependencies]) connection = container.resolve(DatabaseConnection) assert isinstance(connection.config, DatabaseConfig) assert connection.config.host == "localhost" assert connection.timeout == 30 ``` -------------------------------- ### Basic Typer App with Modern-DI Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/typer.md Set up a Typer application with an app-scoped container and inject dependencies using modern-di-typer. This example demonstrates resolving a singleton datetime instance. ```python import datetime import typing import modern_di import modern_di_typer import typer from modern_di import Container, Group, Scope, providers app = typer.Typer() def create_singleton() -> datetime.datetime: return datetime.datetime.now(tz=datetime.timezone.utc) class AppGroup(Group): singleton = providers.Factory( scope=Scope.APP, creator=create_singleton, cache_settings=providers.CacheSettings() ) ALL_GROUPS = [AppGroup] container = Container(groups=ALL_GROUPS) modern_di_typer.setup_di(app, container) @app.command() @modern_di_typer.inject def my_command( instance: typing.Annotated[ datetime.datetime, modern_di_typer.FromDI(datetime.datetime), # Resolve by type instead of provider ], ) -> None: typer.echo(instance) if __name__ == "__main__": with container: app() ``` -------------------------------- ### Resolving Providers by Reference or Type Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Use container.resolve_provider to get a provider by its reference, or container.resolve to get an instance by its type. ```python from modern_di import Container, Provider class MyService: pass my_provider: Provider[MyService] = Provider(MyService) container = Container(providers=[my_provider]) # Resolve by reference resolved_provider = container.resolve_provider(my_provider) # Resolve by type resolved_instance = container.resolve(MyService) ``` -------------------------------- ### Loose Coupling With DI Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This example demonstrates dependency injection, where dependencies are provided from outside the class. This promotes loose coupling and explicit dependencies. ```python class UserService: def __init__(self, email: EmailSender) -> None: # ✅ Injected self.email = email def register_user(self, email: str) -> None: self.email.send_email(email, "Welcome!") ``` -------------------------------- ### Clone Modern-DI Project Source: https://github.com/modern-python/modern-di/blob/main/docs/dev/contributing.md Clone the project repository using Git. Ensure you have Git installed. ```bash git@github.com:modern-python/modern-di.git cd modern-di ``` -------------------------------- ### Create plain modern-di pytest fixtures Source: https://github.com/modern-python/modern-di/blob/main/docs/testing/fixtures.md Manually create pytest fixtures for modern-di containers when not using `modern-di-pytest`. This example shows how to set up session-scoped and request-scoped containers using `modern_di_fastapi` and handle dependency overrides. ```python @pytest.fixture async def di_container() -> typing.AsyncIterator[modern_di.Container]: async with modern_di_fastapi.fetch_di_container(application) as container: yield container @pytest.fixture async def request_di_container( di_container: modern_di.Container, ) -> typing.AsyncIterator[modern_di.Container]: async with di_container.build_child_container(scope=modern_di.Scope.REQUEST) as container: yield container @pytest.fixture def mock_dependencies(di_container: modern_di.Container) -> typing.Iterator[None]: di_container.override( provider=Dependencies.simple_factory, override_object=SimpleFactory(dep1="mock", dep2=777), ) yield di_container.reset_override(Dependencies.simple_factory) ``` -------------------------------- ### Tight Coupling Without DI Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This example shows a class creating its own dependency, leading to tight coupling. This makes testing and swapping implementations difficult. ```python class UserService: def __init__(self) -> None: self.email = EmailService() # ❌ Tight coupling def register_user(self, email: str) -> None: self.email.send_email(email, "Welcome!") ``` -------------------------------- ### Hierarchical Container Scopes Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This example demonstrates modern-di's hierarchical containers and automatic scope inheritance for resolving dependencies from the correct scope. ```python app_container = Container(groups=[AppModule], scope=Scope.APP) request_container = app_container.build_child_container(scope=Scope.REQUEST) # Resolves from correct scope automatically db_pool = request_container.resolve(DatabasePool) # APP scope db_session = request_container.resolve(DatabaseSession) # REQUEST scope ``` -------------------------------- ### Cached Factory with Function Creator Source: https://github.com/modern-python/modern-di/blob/main/docs/providers/factories.md Illustrates a cached factory provider that creates a dependency instance only once and caches it. This example uses a simple function as the creator. The cached instance is guaranteed to be the same across multiple resolutions within the same container. ```python import random from modern_di import Group, Container, Scope, providers def generate_random_number() -> float: return random.random() class Dependencies(Group): singleton = providers.Factory( scope=Scope.APP, creator=generate_random_number, cache_settings=providers.CacheSettings() ) container = Container(groups=[Dependencies]) singleton_instance1 = container.resolve_provider(Dependencies.singleton) singleton_instance2 = container.resolve_provider(Dependencies.singleton) # If resolved in the same container, the instance will be the same assert singleton_instance1 is singleton_instance2 ``` -------------------------------- ### Container Initialization and Resolution Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/common.md Demonstrates creating a root container, building child containers, and resolving dependencies by type or provider reference. ```python from modern_di import Container # Root container — create once at app startup app_container = Container(scope=Scope.APP, groups=[Dependencies]) # Per-request child container — own cache, shares providers and overrides with parent request_container = app_container.build_child_container(scope=Scope.REQUEST) # Resolve by type (any matching provider in registry) instance = request_container.resolve(UsersRepository) # Resolve by provider reference — preferred, unambiguous instance = request_container.resolve_provider(Dependencies.users_repo) # Cleanup — calls finalizers for all cached instances at this scope await request_container.close_async() # or .close_sync() for sync apps ``` -------------------------------- ### Container Initialization (1.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Shows how to initialize asynchronous and synchronous containers in version 1.x. ```python from modern_di import AsyncContainer, SyncContainer # Asynchronous container async_container = AsyncContainer(groups=ALL_GROUPS) async_container.enter() # Synchronous container sync_container = SyncContainer(groups=ALL_GROUPS) sync_container.enter() ``` -------------------------------- ### Container Initialization (2.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Demonstrates the unified container initialization in version 2.x, supporting both sync and async operations without explicit entry. ```python from modern_di import Container # Single container for both sync and async operations container = Container(groups=ALL_GROUPS) # No need to explicitly enter the container # For async cleanup await container.close_async() # For sync cleanup container.close_sync() ``` -------------------------------- ### Set up FastAPI application with modern-di Source: https://github.com/modern-python/modern-di/blob/main/docs/testing/fixtures.md Initialize a FastAPI application and set up modern-di integration using `modern_di_fastapi`. This prepares the application to manage dependencies. ```python import typing import modern_di import modern_di_fastapi import pytest from fastapi import FastAPI from app import ioc from app.ioc import Dependencies, SimpleFactory application = FastAPI() modern_di_fastapi.setup_di(application, modern_di.Container(groups=ioc.ALL_GROUPS)) ``` -------------------------------- ### Container Initialization in 0.x vs 1.x Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-1.x.md Compares the initialization and entry methods for synchronous and asynchronous containers between modern-di 0.x and 1.x. ```python # Before (0.x): Synchronous container container = Container() container.sync_enter() # Before (0.x): Asynchronous container container = Container() container.async_enter() # After (1.x): Synchronous container sync_container = SyncContainer(groups=ALL_GROUPS) sync_container.enter() # After (1.x): Asynchronous container (can still resolve providers synchronously) async_container = AsyncContainer(groups=ALL_GROUPS) async_container.enter() # Synchronously resolve a provider with AsyncContainer instance = async_container.sync_resolve_provider(provider) # Asynchronously resolve a provider with AsyncContainer instance = await async_container.resolve_provider(provider) ``` -------------------------------- ### Dict and List Providers (2.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Demonstrates how to create dictionary and list structures in version 2.x using Factory providers with creator functions. ```python from dataclasses import dataclass from typing import List @dataclass(kw_only=True, slots=True, frozen=True) class UserService: name: str age: int @dataclass(kw_only=True, slots=True, frozen=True) class AuthService: token: str expiry: int # Define providers for UserService and AuthService first user_service_provider = providers.Factory(creator=UserService) auth_service_provider = providers.Factory(creator=AuthService) # For dictionaries def create_services_dict(user_service: UserService, auth_service: AuthService) -> dict[str, object]: return { "user": user_service, "auth": auth_service } my_dict = providers.Factory(creator=create_services_dict) # For lists def create_service_list(user_service: UserService, auth_service: AuthService) -> List[object]: return [user_service, auth_service] my_list = providers.Factory(creator=create_service_list) ``` -------------------------------- ### Container Building with Context Managers Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Demonstrates the continued use of context managers for building child containers in both async and sync scenarios after migration to 2.x. ```python # Async container async with container.build_child_container(context=context, scope=Scope.REQUEST) as request_container: # Use request_container # Sync container with container.build_child_container(context=context, scope=Scope.REQUEST) as request_container: # Use request_container ``` ```python # Same context-manager form continues to work with container.build_child_container(context=context, scope=Scope.REQUEST) as request_container: # Use request_container async with container.build_child_container(context=context, scope=Scope.REQUEST) as request_container: # Use request_container # If you need manual lifecycle control, call close_sync() or await close_async() yourself request_container = container.build_child_container(context=context, scope=Scope.REQUEST) # Use request_container request_container.close_sync() # or: await request_container.close_async() ``` -------------------------------- ### Replace Selector with ContextProvider and Factory Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-1.x.md Demonstrates replacing the 'Selector' provider from 0.x with 'ContextProvider' and 'Factory' in 1.x to dynamically choose a database engine based on context. ```python # Before (0.x) - Using Selector def fetch_db_mode() -> str: # Some logic to determine which database to use return "write" if some_condition else "read" dynamic_engine = providers.Selector( Scope.REQUEST, fetch_db_mode, write=database_engine, read=database_replica_engine, ) # After (1.x) - Using ContextProvider with Factory for Selector replacement # First, define a ContextProvider for any context you need some_context = providers.ContextProvider(Scope.REQUEST, SomeContextType) # Then use a Factory that takes the context and makes decisions dynamic_engine = providers.Factory( Scope.REQUEST, choose_database_engine, # A function that decides which engine to use context=some_context.cast, # Pass the context to the factory function database_engine=database_engine.cast, database_replica_engine=database_replica_engine.cast, ) # The factory function would look like: def choose_database_engine( context: SomeContextType, database_engine: DatabaseEngine, database_replica_engine: DatabaseReplicaEngine, ) -> DatabaseEngine: # Replicate the selector logic here return database_engine if should_use_write_db(context) else database_replica_engine ``` -------------------------------- ### Dict and List Providers (1.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Illustrates the usage of Dict and List providers in version 1.x. ```python my_dict = providers.Dict(Scope.REQUEST, key1=provider1, key2=provider2) my_list = providers.List(Scope.REQUEST, provider1, provider2, provider3) ``` -------------------------------- ### Resource Provider (2.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Shows how to emulate Resource provider functionality in version 2.x using Factory with cache settings and a finalizer. ```python # Resources can be replaced with Factory with cache_settings with finalizer defined resource = providers.Factory( scope=Scope.REQUEST, creator=create_resource, cache_settings=providers.CacheSettings( finalizer=lambda resource: resource.close(), clear_cache=False ) ) ``` -------------------------------- ### Singleton Provider (2.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Demonstrates replacing the Singleton provider in version 2.x using Factory with cache settings. ```python # Use Factory with cache settings singleton = providers.Factory( scope=Scope.APP, creator=create_singleton, cache_settings=providers.CacheSettings() ) ``` -------------------------------- ### Migrate dependency graph from that-depends Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Example of migrating a dependency graph from `that-depends` to `modern-di`, including changes in container type, provider scopes, and resource management. ```python from that_depends import BaseContainer, providers from app import repositories from app.resources.db import create_sa_engine, create_session class Dependencies(BaseContainer): database_engine = providers.Resource(create_sa_engine, settings=settings.cast) session = providers.ContextResource(create_session, engine=database_engine.cast) decks_service = providers.Factory(repositories.DecksService, session=session) cards_service = providers.Factory(repositories.CardsService, session=session) ``` ```python from modern_di import Group, Scope, providers from app.repositories import CardsRepository, DecksRepository from app.resources.db import close_sa_engine, close_session, create_sa_engine, create_session class Dependencies(Group): database_engine = providers.Factory( creator=create_sa_engine, cache_settings=providers.CacheSettings(finalizer=close_sa_engine) ) session = providers.Factory( scope=Scope.REQUEST, creator=create_session, cache_settings=providers.CacheSettings(finalizer=close_session) ) decks_repository = providers.Factory( scope=Scope.REQUEST, creator=DecksRepository, kwargs={"auto_commit": True, "session": session}, ) cards_repository = providers.Factory( scope=Scope.REQUEST, creator=CardsRepository, kwargs={"auto_commit": True, "session": session}, ) ``` -------------------------------- ### Factory with Cache Settings and Finalizer Source: https://github.com/modern-python/modern-di/blob/main/docs/providers/factories.md Demonstrates how to use a factory provider with custom cache settings, including a finalizer for resource cleanup. The `clear_cache=True` (default) ensures that a closed resource is removed from the cache. ```python import contextlib from modern_di import Group, Scope, providers class SomeResource: def close(self) -> None: ... def create_resource() -> SomeResource: # Create and return resource return SomeResource() class Dependencies(Group): # Cache with cleanup — clear_cache=True (the default) ensures the closed # resource is evicted from cache so it cannot be returned again after close resource = providers.Factory( scope=Scope.APP, creator=create_resource, cache_settings=providers.CacheSettings( finalizer=lambda res: res.close(), # Cleanup function ) ) ``` -------------------------------- ### Caching Changes (2.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Illustrates explicit cache settings using CacheSettings with Factory providers in version 2.x. ```python # Explicit cache settings singleton = providers.Factory( creator=create_singleton, cache_settings=providers.CacheSettings() ) # Cache settings with finalizer cached_with_cleanup = providers.Factory( creator=create_resource, cache_settings=providers.CacheSettings( finalizer=lambda resource: resource.close(), clear_cache=False ) ) ``` -------------------------------- ### Test different requests get different instances Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/testing.md Ensure that separate request scopes generate distinct instances of dependencies. This confirms that request-scoped dependencies are isolated between different requests. ```python async def test_different_requests_get_different_instances(): app = Container(scope=Scope.APP, groups=[Dependencies]) req1 = app.build_child_container(scope=Scope.REQUEST) req2 = app.build_child_container(scope=Scope.REQUEST) repo1 = req1.resolve_provider(Dependencies.users_repository) repo2 = req2.resolve_provider(Dependencies.users_repository) assert repo1 is not repo2 await req1.close_async() await req2.close_async() await app.close_async() ``` -------------------------------- ### Replace Singleton with Factory in modern-di Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Demonstrates replacing a `that-depends` `Singleton` provider with a `modern-di` `Factory` provider that uses `CacheSettings`. ```python # that-depends some_singleton = providers.Singleton(SomeClass) # modern-di some_factory = providers.Factory( creator=SomeClass, cache_settings=providers.CacheSettings() ) ``` -------------------------------- ### Resolving Duplicate Type Error with bound_type=None and kwargs Source: https://github.com/modern-python/modern-di/blob/main/docs/troubleshooting/duplicate-type-error.md This example demonstrates how to resolve duplicate type errors in Modern-DI. It shows setting `bound_type=None` on a secondary provider to make it unresolvable by type and explicitly passing dependencies using `kwargs` for another provider. ```python from modern_di import Group, Scope, providers class DatabaseConfig: def __init__(self, connection_string: str) -> None: self.connection_string = connection_string class Repository: def __init__(self, db_config: DatabaseConfig) -> None: self.db_config = db_config class MyGroup(Group): # Step 1: Set bound_type=None on the secondary provider or for both providers # This provider can be resolved by type: container.resolve(DatabaseConfig) primary_db_config = providers.Factory( scope=Scope.APP, creator=DatabaseConfig, kwargs={"connection_string": "postgresql://primary"} ) # This provider cannot be resolved by type # Must use: container.resolve_provider(MyGroup.secondary_db_config) secondary_db_config = providers.Factory( scope=Scope.APP, creator=DatabaseConfig, bound_type=None, # <-- Step 1: Makes it unresolvable by type kwargs={"connection_string": "postgresql://secondary"} ) # Step 2: Explicitly pass dependencies via kwargs for second repository or for both primary_repository = providers.Factory( scope=Scope.APP, creator=Repository, # <-- Implicit dependency, no kwargs ) secondary_repository = providers.Factory( scope=Scope.APP, creator=Repository, kwargs={"db_config": secondary_db_config} # <-- Step 2: Explicit dependency ) ``` -------------------------------- ### Validate dependency wiring without instantiation Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/testing.md Use `container.validate()` to check the dependency graph for issues like missing dependencies, circular dependencies, or incorrect aliases without creating actual objects. This is a quick way to ensure the DI setup is correct. ```python def test_wiring(): container = Container(scope=Scope.APP, groups=[Dependencies]) container.validate() # Raises if any provider has missing dependencies, missing alias sources, or circular deps ``` -------------------------------- ### Regular Factory with Dataclass Creator Source: https://github.com/modern-python/modern-di/blob/main/docs/providers/factories.md Demonstrates creating a regular factory provider that instantiates a dataclass. Dependencies are provided via kwargs. The instance can be resolved by provider reference or by the creator's return type. ```python import dataclasses from modern_di import Group, Container, Scope, providers @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class IndependentFactory: dep1: str dep2: int class Dependencies(Group): independent_factory = providers.Factory( scope=Scope.APP, creator=IndependentFactory, kwargs={"dep1": "text", "dep2": 123} ) container = Container(groups=[Dependencies]) # Resolve by provider reference instance = container.resolve_provider(Dependencies.independent_factory) assert isinstance(instance, IndependentFactory) # Resolve by type (uses the return type of the creator function/class) instance2 = container.resolve(IndependentFactory) assert isinstance(instance2, IndependentFactory) ``` -------------------------------- ### Format, Lint, and Check Code without Just Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Manually runs code formatting, linting, and type checking using uv. ```bash uv run ruff format . && uv run ruff check . --fix && uv run ty check ``` -------------------------------- ### Replace Resource with Factory in modern-di Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Illustrates replacing a `that-depends` `Resource` provider with a `modern-di` `Factory` provider, including cache settings and a finalizer. ```python # that-depends some_resource = providers.Resource(create_resource, settings=settings) # modern-di some_factory = providers.Factory( creator=create_resource, cache_settings=providers.CacheSettings(finalizer=close_resource) ) ``` -------------------------------- ### Define resources and classes Source: https://github.com/modern-python/modern-di/blob/main/docs/index.md Define a singleton string creator, a simple factory dataclass, and a dependent factory dataclass using type annotations. ```python import dataclasses import logging import typing logger = logging.getLogger(__name__) def create_singleton() -> str: return "some string" @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class SimpleFactory: dep1: str dep2: int @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class DependentFactory: simple_factory: SimpleFactory singleton: str ``` -------------------------------- ### Provider API - Factory Arguments (1.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Illustrates the provider API usage in version 1.x, where arguments were passed directly. ```python from modern_di import Scope, providers factory = providers.Factory(Scope.REQUEST, MyClass, arg1="value1", arg2="value2") ``` -------------------------------- ### Manual ContextProvider for Custom Context Source: https://github.com/modern-python/modern-di/blob/main/docs/providers/context.md Shows how to manually define and use a `ContextProvider` for custom context objects. This is useful when injecting non-standard context data, like user or tenant IDs, into factories. ```python from modern_di import Group, Container, Scope, providers # Custom context type class CustomContext: def __init__(self, user_id: str, tenant_id: str) -> None: self.user_id = user_id self.tenant_id = tenant_id def create_user_info(custom_context: CustomContext) -> dict[str, str]: return { "user_id": custom_context.user_id, "tenant_id": custom_context.tenant_id, } class Dependencies(Group): # Manually defined ContextProvider for custom context custom_context = providers.ContextProvider(scope=Scope.REQUEST, context_type=CustomContext) # Factory uses the custom context user_info = providers.Factory( scope=Scope.REQUEST, creator=create_user_info, ) # Provide custom context when building container container = Container(groups=[Dependencies]) custom_context = CustomContext(user_id="123", tenant_id="abc") request_container = container.build_child_container( scope=Scope.REQUEST, context={CustomContext: custom_context} ) # Now resolve the factory — it will receive the custom context automatically user_info = request_container.resolve_provider(Dependencies.user_info) # {"user_id": "123", "tenant_id": "abc"} ``` -------------------------------- ### Container Creation with Validation Source: https://github.com/modern-python/modern-di/blob/main/docs/troubleshooting/circular-dependency.md Create a container and enable validation for circular dependencies at creation time. ```python from modern_di import Container # Option 1: validate at creation container = Container(groups=[MyGroup], validate=True) ``` -------------------------------- ### Create Root Container Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Initializes a root Container with a specified scope and groups. ```python Container(scope=Scope.APP, groups=[MyGroup]) ``` -------------------------------- ### Migrate Litestar route to use FromDI Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Replace `litestar.di.Provide` with `modern_di_litestar.FromDI` for dependency injection in Litestar routes. ```python import litestar from modern_di_litestar import FromDI from app import ioc, schemas from app.repositories import DecksService @litestar.get("/decks/", dependencies={ "decks_service": FromDI(DecksService), }) async def list_decks(decks_service: DecksService) -> schemas.Decks: objects = await decks_service.list() return schemas.Decks(items=objects) ``` -------------------------------- ### Integrate modern-di with FastAPI Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Set up `modern-di` with a FastAPI application using `modern_di_fastapi`. ```python import fastapi from modern_di import Container import modern_di_fastapi from app.ioc import Dependencies container = Container(groups=[Dependencies]) app = fastapi.FastAPI() modern_di_fastapi.setup_di(app, container) ``` -------------------------------- ### Define Dependencies with modern-di Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/SKILL.md Define application-wide and request-scoped dependencies using providers.Factory and CacheSettings. This snippet shows how to set up an async database engine and session with their respective finalizers. ```python from modern_di import Container, Group, Scope, providers class Dependencies(Group): db_engine = providers.Factory( scope=Scope.APP, creator=create_async_engine, cache_settings=providers.CacheSettings(finalizer=close_engine), ) session = providers.Factory( scope=Scope.REQUEST, creator=create_session, cache_settings=providers.CacheSettings(finalizer=close_session), ) container = Container(scope=Scope.APP, groups=[Dependencies]) ``` -------------------------------- ### Integrate modern-di with Litestar Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Set up `modern-di` with a Litestar application using `modern_di_litestar`. ```python from litestar import Litestar from modern_di import Container import modern_di_litestar from app.ioc import Dependencies container = Container(groups=[Dependencies]) app = Litestar( route_handlers=[...], plugins=[modern_di_litestar.ModernDIPlugin(container)], ) ``` -------------------------------- ### Using `FromDI` with Provider Reference Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/litestar.md Illustrates how `modern_di_litestar.FromDI` can resolve dependencies not only by type but also by a direct provider reference, such as `Dependencies.users_repo`. ```python modern_di_litestar.FromDI(dependency) ``` -------------------------------- ### Use plain modern-di fixtures in tests Source: https://github.com/modern-python/modern-di/blob/main/docs/testing/fixtures.md Write tests using manually created modern-di fixtures. This demonstrates resolving dependencies from session-scoped and request-scoped containers, and using mocked dependencies. ```python import pytest from app.ioc import Dependencies def test_with_app_scope(di_container: modern_di.Container) -> None: resource_instance = di_container.resolve_provider(Dependencies.sync_resource) # Do something with the dependency def test_with_request_scope(request_di_container: modern_di.Container) -> None: simple_factory_instance = request_di_container.resolve_provider(Dependencies.simple_factory) # Do something with the dependency @pytest.mark.usefixtures("mock_dependencies") def test_with_request_scope_mocked(request_di_container: modern_di.Container) -> None: simple_factory_instance = request_di_container.resolve_provider(Dependencies.simple_factory) # The dependency is mocked here ``` -------------------------------- ### Use modern-di without integrations Source: https://github.com/modern-python/modern-di/blob/main/docs/index.md Initialize a container, resolve dependencies by provider and type, and build child containers for request scopes. Supports validation for circular dependencies. ```python from modern_di import Container, Scope ALL_GROUPS = [Dependencies] # Initialize container of app scope # Pass validate=True to detect circular dependencies at startup container = Container(groups=ALL_GROUPS, validate=True) # Resolve provider instance1 = container.resolve_provider(Dependencies.singleton) # You can also resolve by type if you've registered groups instance2 = container.resolve(str) # resolves the singleton # Create container of request scope with container.build_child_container(scope=Scope.REQUEST) as request_container: # Resolve factories of request scope instance3 = request_container.resolve_provider(Dependencies.simple_factory) instance4 = request_container.resolve_provider(Dependencies.dependent_factory) # Use your instances... # Finalizers run automatically on `with` exit. In async code, use # `async with container.build_child_container(...) as request_container:` instead. ``` -------------------------------- ### FastAPI Integration with Modern DI Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md Demonstrates how to use modern-di's `FromDI` to inject dependencies into FastAPI route handlers. Ensure `UserService` is registered with the DI container. ```python from modern_di_fastapi import FromDI @app.get("/users/{user_id}") async def get_user( user_id: int, user_service: UserService = FromDI(UserService), ) -> dict: return {"user": user_service.get_user(user_id)} ``` -------------------------------- ### Provider Resolution in Modern-DI 2.x Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Illustrates the simplified, synchronous-only provider resolution syntax introduced in version 2.x. ```python # now resolving is sync only instance = container.resolve_provider(provider) instance = container.resolve(SomeType) ``` -------------------------------- ### Running Benchmark Suite Source: https://github.com/modern-python/modern-di/blob/main/benchmarks/RESULTS.md Execute the benchmark suite for Modern-DI using uv and pytest-benchmark. This command runs specific benchmark files, focuses only on benchmarks, disables coverage reporting, and enables verbose output. ```bash uv run pytest benchmarks/bench_override_fastpath.py benchmarks/bench_kwargs_split.py benchmarks/bench_scope_map.py \ --benchmark-only --no-cov -v ``` -------------------------------- ### Update Import Paths and Class Names Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-1.x.md Before (0.x) and after (1.x) import statements for BaseGraph, Container, AsyncContainer, and SyncContainer. ```python # Before (0.x) from modern_di import BaseGraph, Container # After (1.x) from modern_di import Group, AsyncContainer, SyncContainer ``` -------------------------------- ### Action Scope with Typer and Modern-DI Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/typer.md Demonstrates how to use Scope.ACTION dependencies in a Typer command by injecting the container and building a child container. This allows for request-specific scopes. ```python import modern_di import modern_di_typer import typing from modern_di import Group, Scope, providers class AppGroup(Group): job = providers.Factory(scope=Scope.ACTION, creator=..., bound_type=None) @app.command() @modern_di_typer.inject def run_job( container: typing.Annotated[modern_di.Container, modern_di_typer.FromDI(modern_di.Container)], ) -> None: with container.build_child_container() as action_container: job = action_container.resolve_provider(AppGroup.job) job.run() ``` -------------------------------- ### Migrating Resource to Factory Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Migrate 'that-depends' Resource to 'modern-di' Factory. Use 'providers.Resource' for async or sync generators. 'modern-di' uses 'providers.Factory' with 'creator' and optional 'cache_settings' for finalizers. ```python some_resource = providers.Resource(create_resource) # async or sync generator ``` ```python some_factory = providers.Factory( scope=Scope.APP, creator=create_resource, # sync function cache_settings=providers.CacheSettings(finalizer=close_resource), # async or sync function ) ``` -------------------------------- ### Building Deeper Scope Chains with ACTION Scope Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/fastapi.md Illustrates how to inject the request container and build a child container with `Scope.ACTION` to resolve providers within a more granular scope. Remember to close the child container after use. ```python from modern_di import Container from modern_di_fastapi import build_di_container @app.get("/") async def endpoint( request_container: typing.Annotated[Container, fastapi.Depends(build_di_container)], ) -> dict: action_container = request_container.build_child_container(scope=Scope.ACTION) result = action_container.resolve_provider(Dependencies.action_factory) await action_container.close_async() return {"result": result} ``` -------------------------------- ### Run Tests without Just Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Manually runs project tests using uv and pytest. ```bash uv run pytest ``` -------------------------------- ### Provider API - Factory Arguments (2.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Shows the updated provider API in version 2.x, requiring keyword-only arguments and a 'kwargs' dictionary for creator arguments. ```python from modern_di import Scope, providers factory = providers.Factory(scope=Scope.REQUEST, creator=MyClass, kwargs={"arg1": "value1", "arg2": "value2"}) ``` -------------------------------- ### Caching Changes (1.x) Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Shows the implicit caching behavior of Singleton providers in version 1.x. ```python # Singleton was automatically cached singleton = providers.Singleton(Scope.APP, create_singleton) ``` -------------------------------- ### Basic Alias Usage Source: https://github.com/modern-python/modern-di/blob/main/docs/providers/alias.md Register an abstract type (Repository) to resolve to a concrete implementation (PostgresRepository) that is already provided by a Factory. Both concrete and abstract types resolve to the same instance when the source is a cached Factory. ```python import dataclasses from typing import Protocol from modern_di import Container, Group, Scope, providers class Repository(Protocol): def fetch(self) -> list[str]: ... @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class PostgresRepository: dsn: str = "postgres://localhost" def fetch(self) -> list[str]: return ["row-1", "row-2"] class Dependencies(Group): repo = providers.Factory( creator=PostgresRepository, cache_settings=providers.CacheSettings(), ) abstract_repo = providers.Alias( source_type=PostgresRepository, bound_type=Repository, ) container = Container(groups=[Dependencies]) concrete = container.resolve(PostgresRepository) abstract = container.resolve(Repository) # Both resolve to the same instance — the alias delegates to the # cached source factory. assert concrete is abstract ``` -------------------------------- ### Provider Resolution in Modern-DI 1.x Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-2.x.md Shows the syntax for resolving providers in version 1.x, distinguishing between asynchronous and synchronous resolution methods. ```python # Async resolution instance = await container.resolve_provider(provider) instance = await container.resolve(SomeType) # Sync resolution instance = container.sync_resolve_provider(provider) instance = container.sync_resolve(SomeType) ``` -------------------------------- ### Manual `FromDI` Wiring for Litestar App Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/litestar.md Manually wire dependencies using `modern_di_litestar.FromDI` in the Litestar application's dependency dictionary. This approach requires explicitly defining each dependency. ```python import modern_di import modern_di_litestar from litestar import Litestar from app import ioc, repositories def build_app() -> Litestar: di_container = modern_di.Container(groups=[ioc.Dependencies]) return Litestar( plugins=[modern_di_litestar.ModernDIPlugin(di_container)], dependencies={ "decks_repository": modern_di_litestar.FromDI(repositories.DecksRepository), "cards_repository": modern_di_litestar.FromDI(repositories.CardsRepository), }, route_handlers=[ROUTER], ) ``` -------------------------------- ### Using modern-di for Dependency Management Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This snippet shows how to use modern-di to automatically wire dependencies using type annotations and define them within a Group. ```python import dataclasses from modern_di import Container, Group, Scope, providers @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class AppConfig: db_host: str = "localhost" db_port: int = 5432 @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class DatabaseConnection: config: AppConfig # ✅ Auto-injected from type hint @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class UserService: db: DatabaseConnection # ✅ Auto-injected # Declare dependencies class AppModule(Group): config = providers.Factory( scope=Scope.APP, creator=AppConfig, cache_settings=providers.CacheSettings() ) db = providers.Factory(scope=Scope.REQUEST, creator=DatabaseConnection) user_service = providers.Factory(scope=Scope.REQUEST, creator=UserService) # Resolve entire dependency graph container = Container(groups=[AppModule]) user_service = container.resolve(UserService) ``` -------------------------------- ### Websocket Scope Handling in Litestar Source: https://github.com/modern-python/modern-di/blob/main/docs/integrations/litestar.md Illustrates how to manage APP, SESSION, and REQUEST scopes within a Litestar websocket handler using Modern DI. ```python import litestar from modern_di import Container, Scope import modern_di_litestar app = litestar.Litestar(plugins=[modern_di_litestar.ModernDIPlugin(Container(groups=ALL_GROUPS))]) @litestar.websocket_listener("/ws") async def websocket_handler( data: str, di_container: Container ) -> None: async with di_container.build_child_container(scope=Scope.REQUEST) as request_container: # REQUEST scope is entered here # You can resolve dependencies here app.register(websocket_handler) ``` -------------------------------- ### Initializing Container for Type-Based Resolution Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/to-1.x.md To enable type-based dependency resolution in 1.x, initialize the container with the `groups` parameter. This allows the container to look up providers by their registered return types. ```python # Initialize container with groups to enable type-based resolution container = AsyncContainer(groups=ALL_GROUPS) container.enter() # Now you can resolve dependencies by type instance = container.sync_resolve(SomeType) instance = await container.resolve(SomeType) # You can still resolve by provider reference if needed instance = container.sync_resolve_provider(some_provider) instance = await container.resolve_provider(some_provider) ``` -------------------------------- ### Run Tests Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Executes project tests using pytest, with coverage enabled by default. ```bash just test # uv run pytest (with coverage by default) ``` -------------------------------- ### Enable Cycle Detection Source: https://github.com/modern-python/modern-di/blob/main/CLAUDE.md Enables cycle detection in the provider graph during container creation. ```python Container(scope=Scope.APP, groups=[MyGroup], validate=True) ``` -------------------------------- ### FastAPI Route Handlers with Annotated FromDI Source: https://github.com/modern-python/modern-di/blob/main/skills/modern-di/fastapi.md Demonstrates using `typing.Annotated` with `FromDI` for dependency injection in FastAPI route handlers, offering an alternative syntax. ```python async def list_decks( decks_repository: typing.Annotated[DecksRepository, FromDI(DecksRepository)], ) -> schemas.Decks: ... ``` -------------------------------- ### Migrate FastAPI route to use FromDI Source: https://github.com/modern-python/modern-di/blob/main/docs/migration/from-that-depends.md Replace `fastapi.Depends` with `modern_di_fastapi.FromDI` for dependency injection in FastAPI routes. ```python import fastapi from modern_di_fastapi import FromDI from app import ioc, schemas from app.repositories import DecksService ROUTER: typing.Final = fastapi.APIRouter() @ROUTER.get("/decks/") async def list_decks( decks_service: DecksService = FromDI(DecksService), ) -> schemas.Decks: objects = await decks_service.list() return schemas.Decks(items=objects) ``` -------------------------------- ### Correct Context Propagation Source: https://github.com/modern-python/modern-di/blob/main/docs/providers/container.md Shows the correct ways to ensure context is available to child containers: either set context on the parent before building the child, or pass context directly during child container construction. ```python # Option A: set on the parent first app_container = Container() app_container.set_context(MyContext, value) request_container = app_container.build_child_container(scope=Scope.REQUEST) ``` ```python # Option B: pass context directly to the child request_container = app_container.build_child_container( scope=Scope.REQUEST, context={MyContext: value} ) ``` -------------------------------- ### Testing with Mocked Dependencies Source: https://github.com/modern-python/modern-di/blob/main/docs/introduction/about-di.md This test function shows how to inject a mock object for a dependency, enabling effective unit testing of the UserService. ```python def test_user_service() -> None: mock_email = Mock(spec=EmailSender) service = UserService(email=mock_email) service.register_user("test@example.com") mock_email.send_email.assert_called_once() ```