python-dependency-injector icon indicating copy to clipboard operation
python-dependency-injector copied to clipboard

Self provider not being copied by @copy

Open Qjammer opened this issue 3 years ago • 0 comments

It seems the Self provider is not being copied properly. Consider the following:

class A(containers.DeclarativeContainer):
    __self__ = providers.Self()
    dep = providers.Singleton(dict, container=__self__)

@containers.copy(A)
class CopyA(A):
    # __self__ = providers.Self()
    # A.__self__.override(__self__)
    # Neither of these two lines fix the problem
    pass

container = CopyA()
dep = container.dep()
print(container)
print(dep["container"])

Expected output: Both containers are the same instance

<dependency_injector.containers.DynamicContainer object at 0x7f7ad44a94b0>
<dependency_injector.containers.DynamicContainer object at 0x7f7ad44a94b0>

Actual output: First one is container, second is the class name of the original non-copied container

<dependency_injector.containers.DynamicContainer object at 0x7f7ad44a94b0>
<class '__main__.A'>

The commented lines don't fix the issue. It only changes the second output to be:

<class '__main__.CopyA'>

The following two fragments work as expected:

Composition of containers:

class A(containers.DeclarativeContainer):
    __self__ = providers.Self()
    dep = providers.Singleton(dict, container=__self__)


class ComposedA(containers.DeclarativeContainer):
    __self__ = providers.Self()
    a = providers.Container(A, __self__=__self__)

container = ComposedA()
dep = container.a.dep()
print(container)        # <dependency_injector.containers.DynamicContainer object at 0x7f7ad44a94b0>
print(dep["container"]) # <dependency_injector.containers.DynamicContainer object at 0x7f7ad44a94b0>

Copy of provider that is not Self:

class A(containers.DeclarativeContainer):
    __self__ = providers.Self()
    dep = providers.Singleton(dict, container=__self__)


@containers.copy(A)
class CopyDepA(A):
    str = providers.Singleton(str, "overridden_value")
    A.dep = providers.Singleton(dict, container=str)
    # The following method also works
    # A.dep.override(providers.Singleton(dict, container=str))

container = CopyDepA()
value = container.str()
dep = container.dep()
print(value)            # overridden_value
print(dep["container"]) # overridden_value

Could it be that the Self provider is not being copied? I read this in the docs:

Provider Self is not listed in container .providers attributes.

The implementation of @copy uses the .providers attribute to get the providers to copy. Could this be the issue?

Qjammer avatar Sep 01 '22 12:09 Qjammer