DInjections
This project implements a dependency injection framework in Python, based on uber's fx package.
It works as a modular dependency injection framework, where you can define provision of dependencies, using options pattern and hints to define which dependencies should be provided.
It also implements lifecycle management, where you can define hooks to be executed on start and stop.
Dependencies are only initialized when they are needed, even if provided.
Installation
pip install dinjections
Usage
from dinjections import App, Provide, Invoke, Hook, Lifecycle, Provider, Annotated, Annotations
# Define a class that will be injected
class Dependency0:
pass
# Define a class that will be injected and has dependencies of the same type
class Dependency1:
def __init__(self, d0_1: Annotated[Dependency0, Annotations(name="d0_1")], d0_2: Annotated[Dependency0, Annotations(name="d0_2")]):
self.d0_1 = d0_1
self.d0_2 = d0_2
def run(self):
print("Dependency1 running")
# Define another class that will be injected
class Dependency2:
def __init__(self, d1: Dependency1):
self.d1 = d1
def run(self):
self.d1.run()
# Function that returns a dependency
def new_dep_2(d1: Dependency1) -> Dependency2:
return Dependency2()
# function that will be invoked
def register_hooks(l: Lifecycle, d: Dependency2):
l.append_hook(Hook(
on_start=lambda: {
d.run()
},
))
app = App(
Provide(
# dependency can be initiliazed passing it's class
Dependency1,
# and also with a function that returns the object
new_dep_2,
# you can also define a name for the dependency, in case there is more than one dependency of the same type
Provider(Dependency0, name="d0_1"),
Provider(Dependency0, name="d0_2"),
),
Invoke(
register_hooks,
))
app.run()
Dependencies of the same type
If you have dependencies of the same type, you can use the Provider class to define a name for the dependency with the name argument, and then use it to inject the dependency (as shown above).
If this is not done, a dependency will override the previous.
Dependency inheritance
If you have a dependency that inherits from another, you can use the Provider class to define the dependency with a name argument, and then use it to inject the dependency (as shown below).
# Define a class that will be injected
class TestClass4(TestClass3):
pass
# expects a dependency of type TestClass3, but will accept TestClass4 named "t1"
def register_hooks(l: Lifecycle, t: TestClass3):
l.append_hook(Hook(
on_start=lambda: {
t.run()
},
))
app = App(
Provide(
# provides names dependency that inherites from expected class TestClass3
Provider(TestClass4, name=TestClass3),
),
Invoke(
register_hooks,
))
app.run()
Grouped dependencies
You can group dependencies setting the group parameters to True in a Provider. This will make the dependency be injected as a list of dependencies, with all the dependencies that were provided with the same name.
class MyDependency:
def __init__(self):
def run(self):
print("MyDependency running")
def register_hooks(l: Lifecycle, d: Annotated[MyDependency, Annotations(group=True)]):
# d is now a list of MyDependency, with all the dependencies named "md" that were provided
for t in d:
l.append_hook(Hook(
on_start=lambda: {
t.run()
},
))
app = App(
Provide(
Provider(MyDependency, group=True),
Provider(MyDependency, group=True),
),
Invoke(
register_hooks,
))
app.run()
Lifecycle
You can define hooks to be executed on start and stop of the application.
Currently hooks are executed in the order they are defined, with no support for concurrency.
from dinjections import App, Hook, Lifecycle
def register_hooks(l: Lifecycle):
l.append_hook(Hook(
on_start=lambda: {
print("Invoking 1")
},
on_stop=lambda: {
print("Stopping 1")
},
))
l.append_hook(Hook(
on_start=lambda: {
print("Invoking 2")
},
on_stop=lambda: {
print("Stopping 2")
},
))
app = App(
Invoke(
register_hooks,
)
)
app.run()
Release files for dinjections 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dinjections-1.1.1.tar.gz | 9.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dinjections-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.3 kB
Release files / dinjections-1.1.1.tar.gz
| Download URL | dinjections-1.1.1.tar.gz |
|---|---|
| Size | 9.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cfc8d6826c8fe1530acdda44fd378eca57f957c0ce88f8d1e0b745dab572fa42
|
|
BLAKE2b-256 checksum How to use checksums |
0565657b16a7fc0a60ba8f5f877bd5383507a4b1d2c9ce7539dd19770488fa87
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.6
|
Release files / dinjections-1.1.1-py3-none-any.whl
| Download URL | dinjections-1.1.1-py3-none-any.whl |
|---|---|
| Size | 8.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e78ece1093a129114a35b543fe6abd5b3e0422f7c8c7f6fc5335160fcd246181
|
|
BLAKE2b-256 checksum How to use checksums |
5a9606238abf1e6a8ffd110942cf3a981fbf3c9fa3e1ba0308a4cee4f1582a32
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.6
|