Skip to main content

Simple Dependency Injection framework

Project description

"That Depends"

PyPI version Supported versions downloads GitHub license GitHub Actions Workflow Status Doc GitHub stars

This package is dependency injection framework for Python and allows to transfer projects from dependency-injector with minimal costs and gain additional capabilities.

It is production-ready and gives you the following:

  • Simple async-first DI framework with IOC-container.
  • Python 3.10-3.12 support.
  • Full coverage by types annotations (mypy in strict mode).
  • FastAPI and LiteStar compatibility.
  • Overriding dependencies for tests.
  • Injecting dependencies in functions and coroutines without wiring.
  • Package with zero dependencies.

📚 Documentation

Projects with That Depends:



pip install that-depends

Describe resources and classes:

import dataclasses
import logging
import typing

logger = logging.getLogger(__name__)

# singleton provider with finalization
def create_sync_resource() -> typing.Iterator[str]:
    logger.debug("Resource initiated")
        yield "sync resource"
        logger.debug("Resource destructed")

# same, but async
async def create_async_resource() -> typing.AsyncIterator[str]:
    logger.debug("Async resource initiated")
        yield "async resource"
        logger.debug("Async resource destructed")

@dataclasses.dataclass(kw_only=True, slots=True)
class DependentFactory:
    sync_resource: str
    async_resource: str

Describe IoC-container

from that_depends import BaseContainer, providers

class DIContainer(BaseContainer):
    sync_resource = providers.Resource(create_sync_resource)
    async_resource = providers.AsyncResource(create_async_resource)

    simple_factory = providers.Factory(SimpleFactory, dep1="text", dep2=123)
    dependent_factory = providers.Factory(

Resolve dependencies in your code

# async resolving by default:
await DIContainer.simple_factory()

# sync resolving is also allowed if there is no uninitialized async resources in dependencies

# otherwise you can initialize async resources beforehand one by one or in one call:
await DIContainer.init_async_resources()

Resolve dependencies not described in container

@dataclasses.dataclass(kw_only=True, slots=True)
class FreeFactory:
    dependent_factory: DependentFactory
    sync_resource: str

# this way container will try to find providers by names and resolve them to build FreeFactory instance
free_factory_instance = await DIContainer.resolve(FreeFactory)

Inject providers in function arguments

import datetime

from that_depends import inject, Provide

from tests import container

async def some_coroutine(
    simple_factory: container.SimpleFactory = Provide[container.DIContainer.simple_factory],
    dependent_factory: container.DependentFactory = Provide[container.DIContainer.dependent_factory],
    default_zero: int = 0,
) -> None:
    assert simple_factory.dep1
    assert isinstance(dependent_factory.async_resource, datetime.datetime)
    assert default_zero == 0

def some_function(
    simple_factory: container.SimpleFactory = Provide[container.DIContainer.simple_factory],
    default_zero: int = 0,
) -> None:
    assert simple_factory.dep1
    assert default_zero == 0

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

that_depends-1.14.1.tar.gz (9.7 kB view hashes)

Uploaded Source

Built Distribution

that_depends-1.14.1-py3-none-any.whl (13.0 kB view hashes)

Uploaded Python 3

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