di


Namedi JSON
Version 0.79.2 PyPI version JSON
download
home_pagehttps://github.com/adriangb/di
SummaryDependency injection toolkit
upload_time2023-10-09 21:46:08
maintainer
docs_urlNone
authorAdrian Garcia Badaracco
requires_python>=3.8,<4
licenseMIT
keywords dependency-injection inversion-of-control solid ioc di
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # `di`: dependency injection toolkit

<p align="center">
<a href="https://github.com/adriangb/di/actions?query=workflow%3ACI%2FCD+event%3Apush+branch%3Amain" target="_blank">
    <img src="https://github.com/adriangb/di/actions/workflows/workflow.yaml/badge.svg?event=push&branch=main" alt="Test">
</a>
<a href="https://codecov.io/gh/adriangb/di" target="_blank">
    <img src="https://img.shields.io/codecov/c/github/adriangb/di?color=%2334D058" alt="Coverage">
</a>
<a href="https://pypi.org/project/di" target="_blank">
    <img src="https://img.shields.io/pypi/v/di?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/di" target="_blank">
    <img src="https://img.shields.io/pypi/pyversions/di.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>

`di` is a modern dependency injection toolkit, modeled around the simplicity of FastAPI's dependency injection.

Key features:

- **Intuitive**: simple API, inspired by [FastAPI].
- **Auto-wiring**: `di` supports auto-wiring using type annotations.
- **Scopes**: inspired by [pytest scopes], but defined by users (no fixed "request" or "session" scopes).
- **Composable**: decoupled internal APIs give you the flexibility to customize wiring, execution and binding.
- **Performant**: `di` can execute dependencies in parallel and cache results ins scopes. Performance critical parts are written in [🦀] via [graphlib2].

## Installation

```shell
pip install di[anyio]
```

⚠️ This project is a work in progress. Until there is 1.X.Y release, expect breaking changes. ⚠️

## Simple Example

Here is a simple example of how `di` works:

```python
from dataclasses import dataclass

from di import Container
from di.dependent import Dependent
from di.executors import SyncExecutor


class A:
    ...


class B:
    ...


@dataclass
class C:
    a: A
    b: B


def main():
    container = Container()
    executor = SyncExecutor()
    solved = container.solve(Dependent(C, scope="request"), scopes=["request"])
    with container.enter_scope("request") as state:
        c = solved.execute_sync(executor=executor, state=state)
    assert isinstance(c, C)
    assert isinstance(c.a, A)
    assert isinstance(c.b, B)
```

For more examples, see our [docs].

### Why do I need dependency injection in Python? Isn't that a Java thing?

Dependency injection is a software architecture technique that helps us achieve [inversion of control] and [dependency inversion] (one of the five [SOLID] design principles).

It is a common misconception that traditional software design principles do not apply to Python.
As a matter of fact, you are probably using a lot of these techniques already!

For example, the `transport` argument to httpx's Client ([docs](https://www.python-httpx.org/advanced/#custom-transports)) is an excellent example of dependency injection. Pytest, arguably the most popular Python test framework, uses dependency injection in the form of [pytest fixtures].

Most web frameworks employ inversion of control: when you define a view / controller, the web framework calls you! The same thing applies to CLIs (like [click]) or TUIs (like [Textual]). This is especially true for many newer web frameworks that not only use inversion of control but also dependency injection. Two great examples of this are [FastAPI] and [BlackSheep].

For a more comprehensive overview of Python projects related to dependency injection, see [Awesome Dependency Injection in Python].

## Project Aims

This project aims to be a dependency injection toolkit, with a focus on providing the underlying dependency injection functionality for other libraries.

In other words, while you could use this as a standalone dependency injection framework, you may find it to be a bit terse and verbose. There are also much more mature standalone dependency injection frameworks; I would recommend at least looking into [python-dependency-injector] since it is currently the most popular / widely used of the bunch.

For more background, see our [docs].

[🦀]: https://www.rust-lang.org
[graphlib2]: https://github.com/adriangb/graphlib2
[docs]: https://www.adriangb.com/di/
[binds]: binds.md
[dependency inversion]: https://en.wikipedia.org/wiki/Dependency_inversion_principle
[SOLID]: https://en.wikipedia.org/wiki/SOLID
[inversion of control]: https://en.wikipedia.org/wiki/Inversion_of_control
[click]: https://click.palletsprojects.com/en/8.0.x/
[Textual]: https://github.com/willmcgugan/textual
[FastAPI]: https://fastapi.tiangolo.com/tutorial/dependencies/
[BlackSheep]: https://www.neoteroi.dev/blacksheep/dependency-injection/
[Awesome Dependency Injection in Python]: https://github.com/sfermigier/awesome-dependency-injection-in-python
[python-dependency-injector]: https://github.com/ets-labs/python-dependency-injector
[pytest scopes]: https://docs.pytest.org/en/6.2.x/fixture.html#scope-sharing-fixtures-across-classes-modules-packages-or-session
[pytest fixtures]: https://docs.pytest.org/en/6.2.x/fixture.html

See this release on GitHub: [v0.79.2](https://github.com/adriangb/di/releases/tag/0.79.2)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/adriangb/di",
    "name": "di",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4",
    "maintainer_email": "",
    "keywords": "dependency-injection,inversion-of-control,SOLID,IoC,DI",
    "author": "Adrian Garcia Badaracco",
    "author_email": "adrian@adriangb.com",
    "download_url": "https://files.pythonhosted.org/packages/bf/d3/e5ead09a065ac394bf4b16fa4e654db757db25743b83b281c7791497b7c9/di-0.79.2.tar.gz",
    "platform": null,
    "description": "# `di`: dependency injection toolkit\n\n<p align=\"center\">\n<a href=\"https://github.com/adriangb/di/actions?query=workflow%3ACI%2FCD+event%3Apush+branch%3Amain\" target=\"_blank\">\n    <img src=\"https://github.com/adriangb/di/actions/workflows/workflow.yaml/badge.svg?event=push&branch=main\" alt=\"Test\">\n</a>\n<a href=\"https://codecov.io/gh/adriangb/di\" target=\"_blank\">\n    <img src=\"https://img.shields.io/codecov/c/github/adriangb/di?color=%2334D058\" alt=\"Coverage\">\n</a>\n<a href=\"https://pypi.org/project/di\" target=\"_blank\">\n    <img src=\"https://img.shields.io/pypi/v/di?color=%2334D058&label=pypi%20package\" alt=\"Package version\">\n</a>\n<a href=\"https://pypi.org/project/di\" target=\"_blank\">\n    <img src=\"https://img.shields.io/pypi/pyversions/di.svg?color=%2334D058\" alt=\"Supported Python versions\">\n</a>\n</p>\n\n`di` is a modern dependency injection toolkit, modeled around the simplicity of FastAPI's dependency injection.\n\nKey features:\n\n- **Intuitive**: simple API, inspired by [FastAPI].\n- **Auto-wiring**: `di` supports auto-wiring using type annotations.\n- **Scopes**: inspired by [pytest scopes], but defined by users (no fixed \"request\" or \"session\" scopes).\n- **Composable**: decoupled internal APIs give you the flexibility to customize wiring, execution and binding.\n- **Performant**: `di` can execute dependencies in parallel and cache results ins scopes. Performance critical parts are written in [\ud83e\udd80] via [graphlib2].\n\n## Installation\n\n```shell\npip install di[anyio]\n```\n\n\u26a0\ufe0f This project is a work in progress. Until there is 1.X.Y release, expect breaking changes. \u26a0\ufe0f\n\n## Simple Example\n\nHere is a simple example of how `di` works:\n\n```python\nfrom dataclasses import dataclass\n\nfrom di import Container\nfrom di.dependent import Dependent\nfrom di.executors import SyncExecutor\n\n\nclass A:\n    ...\n\n\nclass B:\n    ...\n\n\n@dataclass\nclass C:\n    a: A\n    b: B\n\n\ndef main():\n    container = Container()\n    executor = SyncExecutor()\n    solved = container.solve(Dependent(C, scope=\"request\"), scopes=[\"request\"])\n    with container.enter_scope(\"request\") as state:\n        c = solved.execute_sync(executor=executor, state=state)\n    assert isinstance(c, C)\n    assert isinstance(c.a, A)\n    assert isinstance(c.b, B)\n```\n\nFor more examples, see our [docs].\n\n### Why do I need dependency injection in Python? Isn't that a Java thing?\n\nDependency injection is a software architecture technique that helps us achieve [inversion of control] and [dependency inversion] (one of the five [SOLID] design principles).\n\nIt is a common misconception that traditional software design principles do not apply to Python.\nAs a matter of fact, you are probably using a lot of these techniques already!\n\nFor example, the `transport` argument to httpx's Client ([docs](https://www.python-httpx.org/advanced/#custom-transports)) is an excellent example of dependency injection. Pytest, arguably the most popular Python test framework, uses dependency injection in the form of [pytest fixtures].\n\nMost web frameworks employ inversion of control: when you define a view / controller, the web framework calls you! The same thing applies to CLIs (like [click]) or TUIs (like [Textual]). This is especially true for many newer web frameworks that not only use inversion of control but also dependency injection. Two great examples of this are [FastAPI] and [BlackSheep].\n\nFor a more comprehensive overview of Python projects related to dependency injection, see [Awesome Dependency Injection in Python].\n\n## Project Aims\n\nThis project aims to be a dependency injection toolkit, with a focus on providing the underlying dependency injection functionality for other libraries.\n\nIn other words, while you could use this as a standalone dependency injection framework, you may find it to be a bit terse and verbose. There are also much more mature standalone dependency injection frameworks; I would recommend at least looking into [python-dependency-injector] since it is currently the most popular / widely used of the bunch.\n\nFor more background, see our [docs].\n\n[\ud83e\udd80]: https://www.rust-lang.org\n[graphlib2]: https://github.com/adriangb/graphlib2\n[docs]: https://www.adriangb.com/di/\n[binds]: binds.md\n[dependency inversion]: https://en.wikipedia.org/wiki/Dependency_inversion_principle\n[SOLID]: https://en.wikipedia.org/wiki/SOLID\n[inversion of control]: https://en.wikipedia.org/wiki/Inversion_of_control\n[click]: https://click.palletsprojects.com/en/8.0.x/\n[Textual]: https://github.com/willmcgugan/textual\n[FastAPI]: https://fastapi.tiangolo.com/tutorial/dependencies/\n[BlackSheep]: https://www.neoteroi.dev/blacksheep/dependency-injection/\n[Awesome Dependency Injection in Python]: https://github.com/sfermigier/awesome-dependency-injection-in-python\n[python-dependency-injector]: https://github.com/ets-labs/python-dependency-injector\n[pytest scopes]: https://docs.pytest.org/en/6.2.x/fixture.html#scope-sharing-fixtures-across-classes-modules-packages-or-session\n[pytest fixtures]: https://docs.pytest.org/en/6.2.x/fixture.html\n\nSee this release on GitHub: [v0.79.2](https://github.com/adriangb/di/releases/tag/0.79.2)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Dependency injection toolkit",
    "version": "0.79.2",
    "project_urls": {
        "Documentation": "https://www.adriangb.com/di",
        "Homepage": "https://github.com/adriangb/di",
        "Repository": "https://github.com/adriangb/di"
    },
    "split_keywords": [
        "dependency-injection",
        "inversion-of-control",
        "solid",
        "ioc",
        "di"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ef529ab18ba80b87e998c19b4087fc65a5606e8b1adf883062903537c30868c3",
                "md5": "6d280e7f64f807c3b35f9e0f36cdea48",
                "sha256": "4b2ac7c46d4d9e941ca47d37c2029ba739c1f8a0e19e5288731224870f00d6e6"
            },
            "downloads": -1,
            "filename": "di-0.79.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "6d280e7f64f807c3b35f9e0f36cdea48",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4",
            "size": 24197,
            "upload_time": "2023-10-09T21:46:07",
            "upload_time_iso_8601": "2023-10-09T21:46:07.116434Z",
            "url": "https://files.pythonhosted.org/packages/ef/52/9ab18ba80b87e998c19b4087fc65a5606e8b1adf883062903537c30868c3/di-0.79.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bfd3e5ead09a065ac394bf4b16fa4e654db757db25743b83b281c7791497b7c9",
                "md5": "58ac022edfb1fd2d1425f27ba618faa7",
                "sha256": "0c65b9ccb984252dadbdcdb39743eeddef0c1f167f791c59fcd70e97bb0d3af8"
            },
            "downloads": -1,
            "filename": "di-0.79.2.tar.gz",
            "has_sig": false,
            "md5_digest": "58ac022edfb1fd2d1425f27ba618faa7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4",
            "size": 20495,
            "upload_time": "2023-10-09T21:46:08",
            "upload_time_iso_8601": "2023-10-09T21:46:08.584608Z",
            "url": "https://files.pythonhosted.org/packages/bf/d3/e5ead09a065ac394bf4b16fa4e654db757db25743b83b281c7791497b7c9/di-0.79.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-09 21:46:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "adriangb",
    "github_project": "di",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "di"
}
        
Elapsed time: 0.16077s