python-dependency-injector
python-dependency-injector copied to clipboard
Provide, providers.Dependency() and order of containers.
trafficstars
This works:
class Foo:
def __init__(self, bar):
self.bar = bar
class SubContainer(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__], packages=[]
)
bar = providers.Dependency(instance_of=str)
foo = providers.Factory(Foo, bar=bar)
class MainContainer(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__], packages=[]
)
sub_container = providers.Container(SubContainer, bar="BAR")
foo = sub_container.foo
foo: Foo = Provide["foo"]
container = MainContainer()
container.check_dependencies()
but this doesn't:
class Foo:
def __init__(self, bar):
self.bar = bar
class SubContainer(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__], packages=[]
)
bar = providers.Dependency(instance_of=str)
foo = providers.Factory(Foo, bar=bar)
foo: Foo = Provide["foo"]
class MainContainer(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__], packages=[]
)
sub_container = providers.Container(SubContainer, bar="BAR") # runs into issues while trying to process this line
foo = sub_container.foo
container = MainContainer()
container.check_dependencies()
pycharm traceback:
File "./main.py", line 41, in <module>
class MainContainer(containers.DeclarativeContainer):
File "./main.py", line 45, in MainContainer
sub_container = providers.Container(SubContainer, bar="BAR")
File "src/dependency_injector/providers.pyx", line 3905, in dependency_injector.providers.Container.__init__
File "src/dependency_injector/containers.pyx", line 748, in dependency_injector.containers.DeclarativeContainer.__new__
File "src/dependency_injector/containers.pyx", line 317, in dependency_injector.containers.DynamicContainer.wire
File "./venv/lib/python3.10/site-packages/dependency_injector/wiring.py", line 348, in wire
_patch_attribute(module, member_name, member, providers_map)
File "./venv/lib/python3.10/site-packages/dependency_injector/wiring.py", line 482, in _patch_attribute
instance = provider()
File "src/dependency_injector/providers.pyx", line 224, in dependency_injector.providers.Provider.__call__
File "src/dependency_injector/providers.pyx", line 2594, in dependency_injector.providers.Factory._provide
File "src/dependency_injector/providers.pxd", line 649, in dependency_injector.providers.__factory_call
File "src/dependency_injector/providers.pxd", line 576, in dependency_injector.providers.__call
File "src/dependency_injector/providers.pxd", line 444, in dependency_injector.providers.__provide_keyword_args
File "src/dependency_injector/providers.pxd", line 364, in dependency_injector.providers.__get_value
File "src/dependency_injector/providers.pyx", line 814, in dependency_injector.providers.Dependency.__call__
File "src/dependency_injector/providers.pyx", line 958, in dependency_injector.providers.Dependency._raise_undefined_error
dependency_injector.errors.Error: Dependency "SubContainer.bar" is not defined
What I'm wondering is if this is intended behaviour. Seems to me there should be no difference whether Provide["foo"] is declared before or after MainContainer declaration as long as I'm not trying to use the foo variable BEFORE MainContainer is initialized.
This in general is what i'm trying to accomplish:
# external library class
class Foo:
def __init__(self, bar):
self.bar = bar
# sub_module/container.py
class SubContainer(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__], packages=[]
)
bar = providers.Dependency(instance_of=str)
foo = providers.Factory(Foo, bar=bar)
# sub_module/foo.py
foo: Foo = Provide["foo"]
# main.py
from .sub_module import foo
class MainContainer(containers.DeclarativeContainer):
sub_container = providers.Container(SubContainer, bar="BAR")
container = MainContainer()
container.check_dependencies()
app = App(foo)