New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DeclarativeContainer need to be define in order ? #207
Comments
Ah I need to use DependenciesContainer, should put this in docs. |
Ok, it's quite problematic in my scenario. Is there a way to make it all late binding ? class Core(containers.DeclarativeContainer):
config = providers.Configuration('config')
logger = providers.Singleton(logging.Logger)
class Service(containers.DeclarativeContainer):
site = providers.Singleton(service.SiteService, site_repo=Repository.site)
queue = providers.Singleton(service.QueueService)
class Adapter(containers.DeclarativeContainer):
tinydb = providers.Singleton(adapter.TinyDBAdapter, db_path=Core.config.default.db_path)
class Repository(containers.DeclarativeContainer):
site = providers.Singleton(repository.SiteRepository, adapter=Adapter.tinydb, q=Service.queue) |
Hi @wiryonolau , Thanks for the question! It's really interesting, I will try to propose a solution from my side in next few days. It looks like something that could be handled by existing functionality, but I will need some time to brainstorm it from all sides and try to found out something elegant. PS: In general, it looks like the issue you're facing is that your architecture has circular dependencies in terms of component types: Thanks, |
Thanks, My understanding is that Service is kind of a default category, unless they can be further classified to specific category like Repository... I used to develop using PHP Zend Framework when most of the code is inside a service. |
This doesn't work, config not updated. In this scenario I need to update config from user input, too make it simple I substitute with dict directly. # container.py
import service
import storage
import adapter
import repository
class Core(containers.DeclarativeContainer):
config = providers.Configuration('config')
class Storage(containers.DeclarativeContainer):
queue = providers.Singleton(storage.QueueStorage)
class Adapter(containers.DeclarativeContainer):
######################################
### Not updated, value always None ###
print(Core.config.default.db_path())
######################################
tinydb = providers.Singleton(
adapter.TinyDBAdapter, db_path=Core.config.default.db_path)
class Repository(containers.DeclarativeContainer):
site = providers.Singleton(
repository.SiteRepository, adapter=Adapter.tinydb, _queue=Storage.queue)
class Service(containers.DeclarativeContainer):
config = providers.Singleton(
service.ConfigService, config=Core.config.provider)
# service.py
class ConfigService:
def __init__(self, config):
self._config = config
def build(self):
self._config.override({"default": {"db_path": "~/test"}})
# __main__.py
from container import Service
config = Service.config()
config.build()
site = Service.site() |
Hi, I create my own Dependency Injection library to show you what I means https://github.com/wiryonolau/python-easydi. I mainly wrap the registered variable with a function, to make it not creating the object on registration but only register the class path for both the factory and the dependency. This way there is no need to think about the order when declaring container. My library is not optimize but you should be able to get the general idea.
It's not a circular dependencies that I need, that is dangerous. It's more like lazy loading, you define everything regardless order, if it's not found the container will throw an error. With this approach I think we can have a declarative container using dictionary, instead of using variable directly. |
Hi @wiryonolau , great, congratulation on |
Hi no problem. I just use it for my own project. |
Hi @wiryonolau , I've reviewed As of the lazy vs ordered declaration style, I designed Dependency Injector to avoid string identifiers. That was done with opened eyes. Having reference identification requires ordered declaration. To make Dependency Injector support laziness, some features were introduced since that post was originated. Here is how your example could look like now: """Containers module."""
from dependency_injector import containers, providers
from .services import ConfigService
class Core(containers.DeclarativeContainer):
config = providers.Configuration('config')
class Storage(containers.DeclarativeContainer):
queue = providers.Singleton(lambda: 'Some storage')
class Adapter(containers.DeclarativeContainer):
core = providers.DependenciesContainer(config=providers.Configuration())
tinydb = providers.Singleton(
lambda db_path: f'DB Path=[{db_path}]',
db_path=core.config.default.db_path,
)
class Repository(containers.DeclarativeContainer):
adapter = providers.DependenciesContainer()
storage = providers.DependenciesContainer()
site = providers.Singleton(
lambda adapter, queue: f'Adapter=[{adapter}], queue=[{queue}]',
adapter=adapter.tinydb,
queue=storage.queue,
)
class Service(containers.DeclarativeContainer):
core = providers.DependenciesContainer()
config = providers.Singleton(ConfigService, core.config.provider)
class Application(containers.DeclarativeContainer):
core = providers.Container(Core)
storage = providers.Container(Storage)
adapter = providers.Container(Adapter, core=core)
repository = providers.Container(Repository, adapter=adapter, storage=storage)
service = providers.Container(Service, core=core)
if __name__ == '__main__':
application = Application()
config = application.service.config()
config.build()
print(application.repository.site())
# Output: Adapter=[DB Path=[~/test]], queue=[Some storage] You can find the code here: https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/application-multiple-containers-runtime-overriding I guess you will keep using |
Hi, thanks for the feedback I'll test it. |
Hi,
I'm grouping provider to Service, Repository and Adapter, the group provider is extending DeclarativeContainer.
I have this dependency:
"Service A" require "Repository A"
"Repository A" require "Adapter A" and "Service B"
"Repository A" cannot be created because Repository class is define before Service class, is this how it suppose to work ? Is it possible to handle this using DynamicDeclarative
I'm using Ubuntu 16.04, Python 3.5.2, dependency_injector 3.12.4
The text was updated successfully, but these errors were encountered: