Skip to content

Attempting to inject, getting: "AttributeError: 'Provide' object has no attribute X" #658

Open
@eriknelson

Description

@eriknelson

Trying to understand how to correctly inject dependencies into a class constructor, the following is a sandbox example where I've extracted the key parts from a broader project.

from dependency_injector import containers, providers
from dependency_injector.wiring import Provide, inject

class Config():
    def __init__(self, config_file: str = None):
        self.config_file = config_file

class Container(containers.DeclarativeContainer):
    config = providers.Singleton(Config)

class Engine():
    @inject
    def __init__(
        self,
        config: Config = Provide[Container.config],
    ):
        self.config = config

    def init(self) -> None:
        print(f'Reading from config: {self.config.config_file}')

def container_factory(config_file: str = None) -> Container:
    container = containers.DynamicContainer()
    config_provider = providers.Factory(Config, config_file=config_file) \
        if config_file else providers.Factory(Config)
    container.config = config_provider
    return container

def main():
    container = container_factory('/tmp/config.yml')
    container.wire(modules=[__name__])
    engine = Engine()
    engine.init()

if __name__ == '__main__':
    main()

I'm getting an error here from the init log:
AttributeError: 'Provide' object has no attribute 'config_file'

My expected behavior is that config is an instance of the Config class that has been passed the config_file value in its constructor. Instead I seem to be given an instance of the Provide class?

I have a few questions about this:

  • The documentation is very vague about what wire actually does, and what it expects for its modules/packages arguments. What should these values be? The module and/or package that needs to have dependencies injected?
  • I'm assuming the problem here is that the wire has failed so it's unable to inject correctly?
  • I'm having a hard time finding examples that demonstrate where the @inject decorator needs to go for a class -- is it on the class declaration or on the actual __init__ def, if I wish to inject into the constructor?

If it's relevant, I use virtualenv .venv to create a virtual env at the root of the project and am using poetry install and poetry shell to load the environment and run it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions