Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/im-cloud-spain-connectors/python-dicontainer
Provides the DIContainer interface along with a default implementation based in PInject Google Project.
https://github.com/im-cloud-spain-connectors/python-dicontainer
adapter component dependency-injection dependency-injection-container interface python
Last synced: 6 days ago
JSON representation
Provides the DIContainer interface along with a default implementation based in PInject Google Project.
- Host: GitHub
- URL: https://github.com/im-cloud-spain-connectors/python-dicontainer
- Owner: IM-Cloud-Spain-Connectors
- License: apache-2.0
- Created: 2022-11-23T15:50:42.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2023-10-31T20:48:13.000Z (about 1 year ago)
- Last Synced: 2023-10-31T21:32:13.080Z (about 1 year ago)
- Topics: adapter, component, dependency-injection, dependency-injection-container, interface, python
- Language: Python
- Homepage:
- Size: 22.5 KB
- Stars: 2
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Python DIContainer
[![Test](https://github.com/othercodes/python-dicontainer/actions/workflows/test.yml/badge.svg)](https://github.com/othercodes/python-dicontainer/actions/workflows/test.yml)
Provides the DIContainer interface along with a default implementation based in PInject Google Project.
## Installation
The easiest way to install DIContainer is to get the latest version from PyPI:
```bash
# using poetry
poetry add rndi-dicontainer
# using pip
pip install rndi-dicontainer
```## The Contracts
This package provides two contracts or interfaces: `DIContainer` and `ServiceProvider`.
### DIContainer
```python
class DIContainer(ABC):
@abstractmethod
def get(self, cls: Type) -> Any:
"""
Instantiate the given cls injecting the required dependencies.:param cls: Type The class name to instantiate.
:raise DependencyBuildingFailure: Raised if there are no available dependency to inject.
:raise InvalidClassType: Raised if the required class is not a valid Class Name.
:return: Any A valid instance of the given class type.
"""
```The DIContainer expose one single method `get` that will accept a class name as argument and will return the same class
properly instantiated.```python
container = Container()instance = container.get(SomeClass)
```### Service Provider
```python
class ServiceProvider(ABC):
@abstractmethod
def register(self):
"""
Place to execute the explicit binding of your service.def register(self):
self.bind_instance('foo', 'foo')
self.bind_class('cache', RedisCache)The available binding methods are:
self.bind_class(self, keyword, concretion)
Define a dependency binding between a key to a class.
> dependencies.to_class('request_builder', RequestBuilder)self.bind_instance(self, keyword, concretion)
Define a dependency binding the dependency key to a certain instance.
> dependencies.to_class('service_api_key', 'some_api_key'):return: None
"""@abstractmethod
def bind_class(self, keyword: str, concrete: Any) -> ServiceProvider:
"""
Binds the given keyword to the given class concretion. Each time someone
requires the bounded keyword a new instance of the provided class will be
injected.:param keyword: str The keyword to bind.
:param concrete: Any The concrete class to instantiate and inject on requesting the keyword.
:return: None
"""@abstractmethod
def bind_instance(self, keyword: str, concrete: Any) -> ServiceProvider:
"""
Binds the given keyword to the given instance concretion. Each time someone
requires the bounded keyword the same instance will be providede.:param keyword: str The keyword to bind.
:param concrete: Any The concrete instance to inject on requesting the keyword.
:return: None
"""```
A service provider allows you to register the dependencies into the dependency container as bindings. Each service
provider can provide multiple dependency definitions.The `register` method allows you to register any dependency using the `bind_instance` and `bind_class` methods. In
addition, you can declare any `provide_` method to compose complex dependencies.```python
from cache_interface.contracts import Cache
from cache_sqlite.adapter import SQLiteCacheAdapter
from rndi.dicontainer.adapter import Container, ServiceProvider
from service.shared.infrastructure import OAuthAutenticator, RESTAPIClientclass MainServiceProvider(ServiceProvider):
def register(self):
self.bind_instance('api_url', 'https://some.api.com/api/v1/')
self.bind_instance('config', {
'CACHE_DIR': '/tmp/cache',
'CACHE_TTL': '900',
'CACHE_SQLITE_NAME': 'cache',
})
# Requires OAuthAuthenticator and Cache implementation.
self.bind_class('api_client', RESTAPIClient)def provide_cache(self, config: dict) -> Cache:
return SQLiteCacheAdapter(
directory_path=config.get('CACHE_DIR', '/tmp/cache'),
ttl=config.get('CACHE_TTL', 900),
name=config.get('CACHE_SQLITE_NAME', 'cache'),
)container = Container([MainServiceProvider()])
```Once the container is instantiated with service provider you can request any class that requires the
configured dependencies.For more information please check https://github.com/google/pinject.