# `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"
}