Open milokmet opened 3 years ago
Hi @milokmet ,
Good question. No, there is nothing for now you could use to make it work out of the box. You need to have a factory method. Here is a closest implementation:
from abc import ABC, abstractmethod
from dependency_injector import containers, providers
class Source(ABC):
@abstractmethod
def do_something(self):
pass
class OracleSource(Source):
def __init__(self, params):
self._params = params
def do_something(self):
print('Oracle', self._params)
class ListSource(Source):
def __init__(self, tasks):
self._tasks = tasks
def do_something(self):
print('List', self._tasks)
class MultiSource(Source):
_sources = []
def __init__(self, sources=None):
self._sources = sources or []
def add(self, source):
if source not in self._sources:
self._sources.append(source)
def do_something(self):
print('Starting to do something')
for s in self._sources:
s.do_something()
@classmethod
def create(cls, config, sources_factory):
sources = []
for source_config in config.copy():
source_type = source_config.pop('type')
source = sources_factory(source_type, **source_config)
sources.append(source)
return cls(sources)
class Container(containers.DeclarativeContainer):
config = providers.Configuration()
sources_factory = providers.FactoryAggregate(
oracle=providers.Factory(OracleSource),
list=providers.Factory(ListSource),
)
multi_source = providers.Factory(
MultiSource.create,
config=config.source,
sources_factory=sources_factory.provider,
)
if __name__ == '__main__':
container = Container()
container.config.from_yaml('workaround.yml')
multi_source = container.multi_source()
multi_source.do_something()
There is a new feature in the development to cover that type of cases: build container from schemas. That's how example schema looks like:
version: "1"
container:
config:
provider: Configuration
database_client:
provider: Singleton
provides: sqlite3.connect
args:
- container.config.database.dsn
s3_client:
provider: Singleton
provides: boto3.client
kwargs:
service_name: s3
aws_access_key_id: container.config.aws.access_key_id
aws_secret_access_key: container.config.aws.secret_access_key
user_service:
provider: Factory
provides: schemasample.services.UserService
kwargs:
db: container.database_client
auth_service:
provider: Factory
provides: schemasample.services.AuthService
kwargs:
db: container.database_client
token_ttl: container.config.auth.token_ttl.as_int()
photo_service:
provider: Factory
provides: schemasample.services.PhotoService
kwargs:
db: container.database_client
s3: container.s3_client
Follow #337 if you're interested.
Wow. I didn't expect an answer so quickly. Thank you very much. I am going to try it. The container builder from schema looks interesting.
Ok, cool. Let me know if you need any other help.
Hello Roman, I am playing a little bit with dependency_injector and I don't know, how could I configure in yaml and write into Container ListProvider next example:
Is it possible to rewrite this with dependency_injector?
And the yaml confg should like like this:
Will it be possible to detect by type of config? If config.source will be dict, it will configure the source by type directly, if it will be list, it will use MultiSource?
Is it possible to rewrite this into container with list provider a config?
Thanks