ets-labs / python-dependency-injector

Dependency injection framework for Python
https://python-dependency-injector.ets-labs.org/
BSD 3-Clause "New" or "Revised" License
3.95k stars 305 forks source link

How to restrict DependenciesContainer type? #513

Open chbndrhnns opened 3 years ago

chbndrhnns commented 3 years ago

I am trying to re-create an onion-layer architecture with the dependency injector library. Here is a snippet:

from dependency_injector import containers, providers

class DbAdapter:

  def get_all(self):
    return []

class Repo:
  def __init__(self, adapter):
    self._adapter = adapter

class Adapters(containers.DeclarativeContainer):
    db_adapter = providers.Singleton(
        DbAdapter
    )

class Repositories(containers.DeclarativeContainer):
    adapters: Adapters = containers.DependenciesContainer()

    repo = providers.Factory(
        Repo, adapter=adapters.db_adapter
    )

Can I make dependency-injector check the provided container for adapters and reject invalid types?

chbndrhnns commented 3 years ago

According to my experiences with the library, this seems not possible. Is it something you see as valuable to have, @rmk135?

rmk135 commented 3 years ago

Hi @chbndrhnns ,

Thanks for sharing the use case. Yes, I think you can be something like:

class Repositories(containers.DeclarativeContainer):
    adapters: Adapters = containers.DependenciesContainer(instanceof= Adapters)

    repo = providers.Factory(
        Repo, adapter=adapters.db_adapter
    )

I'll add it to the backlog.

chbndrhnns commented 3 years ago

Your example is not working for me as containers (line 2) does not seem to have a DependenciesContainer. In version 4.37, only providers has DependenciesContainer.

Also, when I try to run Repositories() from the snippet below, it fails:

class Repositories(containers.DeclarativeContainer):
    adapters: Adapters = providers.DependenciesContainer(instance_of=Adapters)

    repo = providers.Factory(Repo, adapter=adapters.db_adapter)

Error:

src/dependency_injector/containers.pyx:742: in dependency_injector.containers.DeclarativeContainer.__new__
    ???
src/dependency_injector/containers.pyx:392: in dependency_injector.containers.DynamicContainer.load_config
    ???
src/dependency_injector/containers.pyx:193: in traverse
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   AttributeError: type object 'Adapters' has no attribute 'related'

src/dependency_injector/providers.pyx:4813: AttributeError
rowan-maclachlan commented 2 years ago

Yeah, same issue for me.

chbndrhnns commented 2 years ago

@rmk135 i am coming back to this issue now and then. Do you have any idea what to do?