that-depends


Namethat-depends JSON
Version 1.21.1 PyPI version JSON
download
home_pageNone
SummarySimple Dependency Injection framework
upload_time2024-10-11 11:56:16
maintainerNone
docs_urlNone
authorNone
requires_python<4,>=3.10
licenseNone
keywords dependency injector di ioc-container mocks python
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            "That Depends"
==
[![Test Coverage](https://codecov.io/gh/modern-python/that-depends/branch/main/graph/badge.svg)](https://codecov.io/gh/modern-python/that-depends)
[![MyPy Strict](https://img.shields.io/badge/mypy-strict-blue)](https://mypy.readthedocs.io/en/stable/getting_started.html#strict-mode-and-configuration)
[![Supported versions](https://img.shields.io/pypi/pyversions/that-depends.svg)](https://pypi.python.org/pypi/that-depends)
[![downloads](https://img.shields.io/pypi/dm/that-depends.svg)](https://pypistats.org/packages/that-depends)
[![GitHub stars](https://img.shields.io/github/stars/modern-python/that-depends)](https://github.com/modern-python/that-depends/stargazers)

Dependency injection framework for Python inspired by `dependency-injector`.

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](https://that-depends.readthedocs.io)

# Projects with `That Depends`:
- [fastapi-sqlalchemy-template](https://github.com/modern-python/fastapi-sqlalchemy-template) - FastAPI template with sqlalchemy2 and PostgreSQL
- [litestar-sqlalchemy-template](https://github.com/modern-python/litestar-sqlalchemy-template) - LiteStar template with sqlalchemy2 and PostgreSQL

# Quickstart
## Install
```bash
pip install that-depends
```

## Describe resources and classes:
```python
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")
    try:
        yield "sync resource"
    finally:
        logger.debug("Resource destructed")


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


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

## Describe IoC-container
```python
from that_depends import BaseContainer, providers


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

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

## Resolve dependencies in your code
```python
# async resolving by default:
await DIContainer.simple_factory()

# sync resolving is also allowed if there is no uninitialized async resources in dependencies
DIContainer.simple_factory.sync_resolve()

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

## Resolve dependencies not described in container
```python
@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
```python
import datetime

from that_depends import inject, Provide

from tests import container


@inject
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

@inject
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
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "that-depends",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4,>=3.10",
    "maintainer_email": null,
    "keywords": "dependency injector, di, ioc-container, mocks, python",
    "author": null,
    "author_email": "Artur Shiriev <me@shiriev.ru>",
    "download_url": "https://files.pythonhosted.org/packages/f2/c5/7e9a07a3f1e5fbc1962adf9f1ccef5202b2bf3f10c3d7a2f080c2a86e72f/that_depends-1.21.1.tar.gz",
    "platform": null,
    "description": "\"That Depends\"\n==\n[![Test Coverage](https://codecov.io/gh/modern-python/that-depends/branch/main/graph/badge.svg)](https://codecov.io/gh/modern-python/that-depends)\n[![MyPy Strict](https://img.shields.io/badge/mypy-strict-blue)](https://mypy.readthedocs.io/en/stable/getting_started.html#strict-mode-and-configuration)\n[![Supported versions](https://img.shields.io/pypi/pyversions/that-depends.svg)](https://pypi.python.org/pypi/that-depends)\n[![downloads](https://img.shields.io/pypi/dm/that-depends.svg)](https://pypistats.org/packages/that-depends)\n[![GitHub stars](https://img.shields.io/github/stars/modern-python/that-depends)](https://github.com/modern-python/that-depends/stargazers)\n\nDependency injection framework for Python inspired by `dependency-injector`.\n\nIt is production-ready and gives you the following:\n- Simple async-first DI framework with IOC-container.\n- Python 3.10-3.12 support.\n- Full coverage by types annotations (mypy in strict mode).\n- FastAPI and LiteStar compatibility.\n- Overriding dependencies for tests.\n- Injecting dependencies in functions and coroutines without wiring.\n- Package with zero dependencies.\n\n\ud83d\udcda [Documentation](https://that-depends.readthedocs.io)\n\n# Projects with `That Depends`:\n- [fastapi-sqlalchemy-template](https://github.com/modern-python/fastapi-sqlalchemy-template) - FastAPI template with sqlalchemy2 and PostgreSQL\n- [litestar-sqlalchemy-template](https://github.com/modern-python/litestar-sqlalchemy-template) - LiteStar template with sqlalchemy2 and PostgreSQL\n\n# Quickstart\n## Install\n```bash\npip install that-depends\n```\n\n## Describe resources and classes:\n```python\nimport dataclasses\nimport logging\nimport typing\n\n\nlogger = logging.getLogger(__name__)\n\n\n# singleton provider with finalization\ndef create_sync_resource() -> typing.Iterator[str]:\n    logger.debug(\"Resource initiated\")\n    try:\n        yield \"sync resource\"\n    finally:\n        logger.debug(\"Resource destructed\")\n\n\n# same, but async\nasync def create_async_resource() -> typing.AsyncIterator[str]:\n    logger.debug(\"Async resource initiated\")\n    try:\n        yield \"async resource\"\n    finally:\n        logger.debug(\"Async resource destructed\")\n\n\n@dataclasses.dataclass(kw_only=True, slots=True)\nclass DependentFactory:\n    sync_resource: str\n    async_resource: str\n```\n\n## Describe IoC-container\n```python\nfrom that_depends import BaseContainer, providers\n\n\nclass DIContainer(BaseContainer):\n    sync_resource = providers.Resource(create_sync_resource)\n    async_resource = providers.Resource(create_async_resource)\n\n    simple_factory = providers.Factory(SimpleFactory, dep1=\"text\", dep2=123)\n    dependent_factory = providers.Factory(\n        sync_resource=sync_resource,\n        async_resource=async_resource,\n    )\n```\n\n## Resolve dependencies in your code\n```python\n# async resolving by default:\nawait DIContainer.simple_factory()\n\n# sync resolving is also allowed if there is no uninitialized async resources in dependencies\nDIContainer.simple_factory.sync_resolve()\n\n# otherwise you can initialize resources beforehand one by one or in one call:\nawait DIContainer.init_resources()\n```\n\n## Resolve dependencies not described in container\n```python\n@dataclasses.dataclass(kw_only=True, slots=True)\nclass FreeFactory:\n    dependent_factory: DependentFactory\n    sync_resource: str\n\n# this way container will try to find providers by names and resolve them to build FreeFactory instance\nfree_factory_instance = await DIContainer.resolve(FreeFactory)\n```\n\n## Inject providers in function arguments\n```python\nimport datetime\n\nfrom that_depends import inject, Provide\n\nfrom tests import container\n\n\n@inject\nasync def some_coroutine(\n    simple_factory: container.SimpleFactory = Provide[container.DIContainer.simple_factory],\n    dependent_factory: container.DependentFactory = Provide[container.DIContainer.dependent_factory],\n    default_zero: int = 0,\n) -> None:\n    assert simple_factory.dep1\n    assert isinstance(dependent_factory.async_resource, datetime.datetime)\n    assert default_zero == 0\n\n@inject\ndef some_function(\n    simple_factory: container.SimpleFactory = Provide[container.DIContainer.simple_factory],\n    default_zero: int = 0,\n) -> None:\n    assert simple_factory.dep1\n    assert default_zero == 0\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Simple Dependency Injection framework",
    "version": "1.21.1",
    "project_urls": {
        "docs": "https://that-depends.readthedocs.io",
        "repository": "https://github.com/modern-python/that-depends"
    },
    "split_keywords": [
        "dependency injector",
        " di",
        " ioc-container",
        " mocks",
        " python"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "aebe9c63f9af7f61f746bb12fc7859a9e55418fba2540d7dce1d2de054086755",
                "md5": "efa954b7d09fc4defeab02df2eacce8c",
                "sha256": "fa7c8696d0efd527f9259416e37494282d353763cb9d67adb7535e09cdf437af"
            },
            "downloads": -1,
            "filename": "that_depends-1.21.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "efa954b7d09fc4defeab02df2eacce8c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4,>=3.10",
            "size": 14569,
            "upload_time": "2024-10-11T11:56:15",
            "upload_time_iso_8601": "2024-10-11T11:56:15.394655Z",
            "url": "https://files.pythonhosted.org/packages/ae/be/9c63f9af7f61f746bb12fc7859a9e55418fba2540d7dce1d2de054086755/that_depends-1.21.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f2c57e9a07a3f1e5fbc1962adf9f1ccef5202b2bf3f10c3d7a2f080c2a86e72f",
                "md5": "a272e045f3a4bfe444a43a450e91e081",
                "sha256": "1017b6f627147746d8c24135e9f7b856f31d3c563979c76e7de02b9c09631244"
            },
            "downloads": -1,
            "filename": "that_depends-1.21.1.tar.gz",
            "has_sig": false,
            "md5_digest": "a272e045f3a4bfe444a43a450e91e081",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4,>=3.10",
            "size": 23659,
            "upload_time": "2024-10-11T11:56:16",
            "upload_time_iso_8601": "2024-10-11T11:56:16.809582Z",
            "url": "https://files.pythonhosted.org/packages/f2/c5/7e9a07a3f1e5fbc1962adf9f1ccef5202b2bf3f10c3d7a2f080c2a86e72f/that_depends-1.21.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-11 11:56:16",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "modern-python",
    "github_project": "that-depends",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "that-depends"
}
        
Elapsed time: 0.70737s