ets-labs/python-dependency-injector

Cannot Access Providers in Container Inheritance

Closed this issue · 3 comments

I have this code:

class SharedContainer(containers.DeclaredContainer):
     config = providers.Configuration()
     stats = providers.Factory(Stats)

class APIContainer(SharedContainer):
    first_api_client = providers.Factory(FirstAPIClient, client_id=config.client_id)  # config from SharedContainer
    second_api_client = providers.Factory(SecondAPIClient, secret=config.secret, client_id=config.client_id)   # config from SharedContainer

It appears the config cannot be accessed. And I don't want to access it from the SharedContainer directly like: SharedContainer.config.*

Any work around?

Thanks

It appears the config cannot be accessed.

Your example won't work due to Python name resolution rules.

Any work around?

Use combination of providers.Container and providers.Dependency:

class APIContainer(containers.DeclaredContainer):
    client_id = providers.Dependency()
    secret = providers.Dependency()
    first_api_client = providers.Factory(FirstAPIClient, client_id=client_id)
    second_api_client = providers.Factory(SecondAPIClient, secret=secret, client_id=client_id)

class SharedContainer(containers.DeclaredContainer):
     config = providers.Configuration()
     stats = providers.Factory(Stats)
     api = providers.Container(APIContainer, client_id=config.client_id, secret=config.secret)

Thank you @ZipFile for your response. However, the solution you suggested will defeat my intention of using inheritance. This was to avoid repeating the config on every DeclarativeContainer subclass I define. Does that mean inheritance is not possible in this context?

I'll appreciate your input and response.

Given the Python limitations, composition instead of inheritance is the only remaining option. You can also check providers.DependenciesContainer if you like the syntax better, but ergonomically it's pretty much the same.