https://github.com/dlski/python-di
Fully automatic dependency injection for Python using annotations / type hints.
https://github.com/dlski/python-di
annotations ddd dependency-injection domain-driven-design enterprise enterprise-architecture python-di python3 type-hints
Last synced: 3 months ago
JSON representation
Fully automatic dependency injection for Python using annotations / type hints.
- Host: GitHub
- URL: https://github.com/dlski/python-di
- Owner: dlski
- License: mit
- Created: 2021-02-03T20:00:41.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-04-07T19:57:38.000Z (almost 5 years ago)
- Last Synced: 2025-08-23T05:37:32.508Z (5 months ago)
- Topics: annotations, ddd, dependency-injection, domain-driven-design, enterprise, enterprise-architecture, python-di, python3, type-hints
- Language: Python
- Homepage:
- Size: 111 KB
- Stars: 9
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# python-di
[](https://github.com/dlski/python-di/actions/workflows/ci.yml)
[](https://codecov.io/gh/dlski/python-di)
[](https://pypi.python.org/pypi/python-di)
[](https://pypistats.org/packages/python-di)
[](https://github.com/dlski/python-di)
[](https://github.com/dlski/python-di/blob/master/LICENSE)
Fully automatic dependency injection for python 3.7, 3.8, 3.9, pypy3 using (not only) argument annotations / type hints.
Corresponds to clean architecture patterns and ideal for business applications created in DDD / Hexagonal architecture flavour.
No external dependencies - uses only standard libraries.
Key features:
- automatic type matching based on type hints / type annotations -
no manual configuration is needed, it just works out of the box
- configurable object aggregation injection -
DI can join `SomeClass` objects and inject into argument annotated as `Collection[SomeClass]`
- not harm existing codebase -
no decorators, no extra metadata are needed in existing codebase to make app construction possible
- no singletons or global DI process state -
app or any app components can be instantiated independently as many times as needed
- transparency of DI process -
static dependency graph and injection plan is built, informative exceptions on error cases
(like cyclic dependency or missing elements)
## Help
Coming soon...
## An Example
Application domain located in `mod_simple.py`:
```py
from typing import List
class Repo:
def read(self) -> List[str]:
raise NotImplementedError
class DomainAction:
def __init__(self, repo: Repo):
self.repo = repo
def present(self) -> str:
joined = ", ".join(self.repo.read())
return f"Data found: {joined}"
```
Application concretes located in `mod_simple_impl.py`:
```py
from typing import List
from mod_simple import Repo
class MockupRepo(Repo):
def read(self) -> List[str]:
return ["di", "test"]
```
Automatic application construction:
```py
from di.declarative import DeclarativeApp, DeclarativeModule, scan_factories
import mod_simple, mod_simple_impl
def main():
# create app definition
app_def = DeclarativeApp(
DeclarativeModule(
# automatically add factories from `mod_simple` and `mod_simple_impl`
scan_factories(mod_simple, mod_simple_impl),
)
)
# build app
instance = app_def.build_instance()
# get initialized `DomainAction` object
action, = instance.values_by_type(mod_simple.DomainAction)
# check app works
assert action.present() == "Data found: di, test"
```
## More examples
More working examples are available in `tests/di/declarative/`.
Please see [tests/di/declarative/test_build.py](tests/di/declarative/test_build.py) for reference.