Type-based dependency-injection
Project description
enterprython
Python library providing type-based dependency-injection
Table of contents
Introduction
If you plan to develop SOLID/domain-driven (i.e., enterprisey) software, you probably want to apply dependency injection on your class constructors, and use a library doing the lookup for you based on static type annotations, instead of configuring the object graph manually.
enterprython
provides exactly that.
from enterprython import assemble, component
@component()
class Service:
def __init__(self) -> None:
self._greeting: str = "Hello"
def greet(self, name: str) -> str:
return f"{self._greeting}, {name}!"
class Client:
def __init__(self, service: Service) -> None:
self._service = service
def run(self) -> None:
print(self._service.greet("World"))
assemble(Client).run()
Output:
Hello, World!
Features
Abstract base classes
A client may depend on an abstract base class. Enterprython will inject the matching implementation.
from abc import ABC
from enterprython import assemble, component
class ServiceInterface(ABC):
...
@component()
class ServiceImpl(ServiceInterface):
...
class Client:
def __init__(self, services: ServiceInterface) -> None:
...
assemble(Client)
One singleton instance of ServiceImpl
is created and injected into Client
.
Factories
Annotating a function with @component()
is registered as a factory for its return type.
from enterprython import assemble, component
class Service:
...
@component()
def service_factory() -> Service:
return Service()
class Client:
def __init__(self, service: Service) -> None:
...
assemble(Client)
service_factory
is used to create the Service
instance for calling the constructor of Client
.
Non-singleton services
If a service is annotated with @component(singleton=False)
a new instance of it is created with every injection.
@component(singleton=False)
class Service:
...
class Client:
def __init__(self, service: Service) -> None:
...
Service lists
A client may depend on a list of implementations of a service interface.
from abc import ABC
from typing import List
from enterprython import assemble, component
class ServiceInterface(ABC):
pass
@component()
class ServiceA(ServiceInterface):
...
@component()
class ServiceB(ServiceInterface):
...
class Client:
def __init__(self, services: List[ServiceInterface]) -> None:
...
assemble(Client)
[ServiceA(), ServiceB()]
is injected into Client
.
Mixing managed and manual injection
One part of a client's dependencies might be injected manually, the rest automatically.
from enterprython import assemble, component
@component()
class ServiceA:
...
class ServiceB:
...
class Client:
def __init__(self, service_a: ServiceA, service_b: ServiceB) -> None:
...
assemble(Client, service_b=ServiceB())
service_a
comes from the DI container, service_b
from user code.
If ServiceB
also has a @component()
annotation, the manually provided object is preferred.
Free functions as clients
Since class constructors are fundamentally just normal functions, we can inject dependencies into free functions too.
from enterprython import assemble, component
@component()
class Service:
...
def client(service: Service) -> None:
...
assemble(client)
A singleton instance of Service
is created and used to call client
.
Requirements and Installation
You need Python 3.6.5 or higher.
python3 -m pip install enterprython
Or, if you like to use latest version from this repository:
git clone https://github.com/Dobiasd/enterprython
cd enterprython
python3 -m pip install .
License
Distributed under the MIT License.
(See accompanying file LICENSE
or at
https://opensource.org/licenses/MIT)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file enterprython-0.4.3.tar.gz
.
File metadata
- Download URL: enterprython-0.4.3.tar.gz
- Upload date:
- Size: 8.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.4 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3728d10e7b04a18c962debef76e4fefff49b4a0898e229fc78a7daa47fca6fe0 |
|
MD5 | 3c4c109284911028cd532f0acb4ab207 |
|
BLAKE2b-256 | c9d402b8a7020f94d4f766e7245e08b09f34b0ff2d5b07550e4c493637fce9c0 |
File details
Details for the file enterprython-0.4.3-py3-none-any.whl
.
File metadata
- Download URL: enterprython-0.4.3-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.4 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.6.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 43036c2a13a828693167264956410c3420a0e208a6191aa1a523efbd1d9a7de1 |
|
MD5 | e0367ad20255fbe1f2f1e5753bcc0d81 |
|
BLAKE2b-256 | af742956ec69794a6db70ff9c97139879f9b3c07680798e8267fb486c5b5d288 |