diff --git a/src/dependency_injector/containers.pyi b/src/dependency_injector/containers.pyi index aa38f961..ca013906 100644 --- a/src/dependency_injector/containers.pyi +++ b/src/dependency_injector/containers.pyi @@ -49,7 +49,7 @@ class Container: def __delattr__(self, name: str) -> None: ... def set_providers(self, **providers: Provider): ... def set_provider(self, name: str, provider: Provider) -> None: ... - def override(self, overriding: C_Base) -> None: ... + def override(self, overriding: Union[Container, Type[Container]]) -> None: ... def override_providers(self, **overriding_providers: Union[Provider, Any]) -> ProvidersOverridingContext[C_Base]: ... def reset_last_overriding(self) -> None: ... def reset_override(self) -> None: ... @@ -88,6 +88,14 @@ class DeclarativeContainer(Container): cls_providers: ClassVar[Dict[str, Provider]] inherited_providers: ClassVar[Dict[str, Provider]] def __init__(self, **overriding_providers: Union[Provider, Any]) -> None: ... + @classmethod + def override(cls, overriding: Union[Container, Type[Container]]) -> None: ... + @classmethod + def override_providers(cls, **overriding_providers: Union[Provider, Any]) -> ProvidersOverridingContext[C_Base]: ... + @classmethod + def reset_last_overriding(cls) -> None: ... + @classmethod + def reset_override(cls) -> None: ... class ProvidersOverridingContext(Generic[T]): diff --git a/tests/unit/containers/cls/test_main_py2_py3.py b/tests/unit/containers/cls/test_main_py2_py3.py new file mode 100644 index 00000000..1d13d5b3 --- /dev/null +++ b/tests/unit/containers/cls/test_main_py2_py3.py @@ -0,0 +1,498 @@ +"""Main container class tests.""" + +import collections + +from dependency_injector import containers, providers, errors +from pytest import raises + + +class ContainerA(containers.DeclarativeContainer): + p11 = providers.Provider() + p12 = providers.Provider() + + +class ContainerB(ContainerA): + p21 = providers.Provider() + p22 = providers.Provider() + + +class ContainerC(ContainerB): + p31 = providers.Provider() + p32 = providers.Provider() + + +def test_providers_attribute(): + assert ContainerA.providers == dict(p11=ContainerA.p11, p12=ContainerA.p12) + assert ContainerB.providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p21=ContainerB.p21, + p22=ContainerB.p22, + ) + assert ContainerC.providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p21=ContainerB.p21, + p22=ContainerB.p22, + p31=ContainerC.p31, + p32=ContainerC.p32, + ) + + +def test_providers_attribute_with_redefinition(): + p1 = providers.Provider() + p2 = providers.Provider() + + class ContainerA2(ContainerA): + p11 = p1 + p12 = p2 + + assert ContainerA.providers == { + "p11": ContainerA.p11, + "p12": ContainerA.p12, + } + assert ContainerA2.providers == { + "p11": p1, + "p12": p2, + } + + +def test_cls_providers_attribute(): + assert ContainerA.cls_providers == dict(p11=ContainerA.p11, p12=ContainerA.p12) + assert ContainerB.cls_providers == dict(p21=ContainerB.p21, p22=ContainerB.p22) + assert ContainerC.cls_providers == dict(p31=ContainerC.p31, p32=ContainerC.p32) + + +def test_inherited_providers_attribute(): + assert ContainerA.inherited_providers == dict() + assert ContainerB.inherited_providers == dict(p11=ContainerA.p11, p12=ContainerA.p12) + assert ContainerC.inherited_providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p21=ContainerB.p21, + p22=ContainerB.p22, + ) + + +def test_dependencies_attribute(): + class ContainerD(ContainerC): + p41 = providers.Dependency() + p42 = providers.DependenciesContainer() + + class ContainerE(ContainerD): + p51 = providers.Dependency() + p52 = providers.DependenciesContainer() + + assert ContainerD.dependencies == { + "p41": ContainerD.p41, + "p42": ContainerD.p42, + } + assert ContainerE.dependencies == { + "p41": ContainerD.p41, + "p42": ContainerD.p42, + "p51": ContainerE.p51, + "p52": ContainerE.p52, + } + + +def test_set_get_del_providers(): + a_p13 = providers.Provider() + b_p23 = providers.Provider() + + ContainerA.p13 = a_p13 + ContainerB.p23 = b_p23 + + assert ContainerA.providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p13=a_p13, + ) + assert ContainerB.providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p21=ContainerB.p21, + p22=ContainerB.p22, + p23=b_p23, + ) + + assert ContainerA.cls_providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p13=a_p13, + ) + assert ContainerB.cls_providers == dict( + p21=ContainerB.p21, + p22=ContainerB.p22, + p23=b_p23, + ) + + del ContainerA.p13 + del ContainerB.p23 + + assert ContainerA.providers == dict(p11=ContainerA.p11, p12=ContainerA.p12) + assert ContainerB.providers == dict( + p11=ContainerA.p11, + p12=ContainerA.p12, + p21=ContainerB.p21, + p22=ContainerB.p22, + ) + + assert ContainerA.cls_providers == dict(p11=ContainerA.p11, p12=ContainerA.p12) + assert ContainerB.cls_providers == dict(p21=ContainerB.p21, p22=ContainerB.p22) + + +def test_declare_with_valid_provider_type(): + class _Container(containers.DeclarativeContainer): + provider_type = providers.Object + px = providers.Object(object()) + + assert isinstance(_Container.px, providers.Object) + + +def test_declare_with_invalid_provider_type(): + with raises(errors.Error): + class _Container(containers.DeclarativeContainer): + provider_type = providers.Object + px = providers.Provider() + + +def test_seth_valid_provider_type(): + class _Container(containers.DeclarativeContainer): + provider_type = providers.Object + + _Container.px = providers.Object(object()) + + assert isinstance(_Container.px, providers.Object) + +def test_set_invalid_provider_type(): + class _Container(containers.DeclarativeContainer): + provider_type = providers.Object + + with raises(errors.Error): + _Container.px = providers.Provider() + + +def test_override(): + class _Container(containers.DeclarativeContainer): + p11 = providers.Provider() + + class _OverridingContainer1(containers.DeclarativeContainer): + p11 = providers.Provider() + + class _OverridingContainer2(containers.DeclarativeContainer): + p11 = providers.Provider() + p12 = providers.Provider() + + _Container.override(_OverridingContainer1) + _Container.override(_OverridingContainer2) + + assert _Container.overridden == (_OverridingContainer1, _OverridingContainer2) + assert _Container.p11.overridden == (_OverridingContainer1.p11, _OverridingContainer2.p11) + + +def test_override_with_it(): + with raises(errors.Error): + ContainerA.override(ContainerA) + + +def test_override_with_parent(): + with raises(errors.Error): + ContainerB.override(ContainerA) + + +def test_override_decorator(): + class _Container(containers.DeclarativeContainer): + p11 = providers.Provider() + + @containers.override(_Container) + class _OverridingContainer1(containers.DeclarativeContainer): + p11 = providers.Provider() + + @containers.override(_Container) + class _OverridingContainer2(containers.DeclarativeContainer): + p11 = providers.Provider() + p12 = providers.Provider() + + assert _Container.overridden == (_OverridingContainer1, _OverridingContainer2) + assert _Container.p11.overridden == (_OverridingContainer1.p11, _OverridingContainer2.p11) + + +def test_reset_last_overriding(): + class _Container(containers.DeclarativeContainer): + p11 = providers.Provider() + + class _OverridingContainer1(containers.DeclarativeContainer): + p11 = providers.Provider() + + class _OverridingContainer2(containers.DeclarativeContainer): + p11 = providers.Provider() + p12 = providers.Provider() + + _Container.override(_OverridingContainer1) + _Container.override(_OverridingContainer2) + _Container.reset_last_overriding() + + assert _Container.overridden == (_OverridingContainer1,) + assert _Container.p11.overridden == (_OverridingContainer1.p11,) + + +def test_reset_last_overriding_when_not_overridden(): + with raises(errors.Error): + ContainerA.reset_last_overriding() + + +def test_reset_override(): + class _Container(containers.DeclarativeContainer): + p11 = providers.Provider() + + class _OverridingContainer1(containers.DeclarativeContainer): + p11 = providers.Provider() + + class _OverridingContainer2(containers.DeclarativeContainer): + p11 = providers.Provider() + p12 = providers.Provider() + + _Container.override(_OverridingContainer1) + _Container.override(_OverridingContainer2) + _Container.reset_override() + + assert _Container.overridden == tuple() + assert _Container.p11.overridden == tuple() + + +def test_copy(): + @containers.copy(ContainerA) + class _Container1(ContainerA): + pass + + @containers.copy(ContainerA) + class _Container2(ContainerA): + pass + + assert ContainerA.p11 is not _Container1.p11 + assert ContainerA.p12 is not _Container1.p12 + + assert ContainerA.p11 is not _Container2.p11 + assert ContainerA.p12 is not _Container2.p12 + + assert _Container1.p11 is not _Container2.p11 + assert _Container1.p12 is not _Container2.p12 + + +def test_copy_with_replacing(): + class _Container(containers.DeclarativeContainer): + p11 = providers.Object(0) + p12 = providers.Factory(dict, p11=p11) + + @containers.copy(_Container) + class _Container1(_Container): + p11 = providers.Object(1) + p13 = providers.Object(11) + + @containers.copy(_Container) + class _Container2(_Container): + p11 = providers.Object(2) + p13 = providers.Object(22) + + assert _Container.p11 is not _Container1.p11 + assert _Container.p12 is not _Container1.p12 + + assert _Container.p11 is not _Container2.p11 + assert _Container.p12 is not _Container2.p12 + + assert _Container1.p11 is not _Container2.p11 + assert _Container1.p12 is not _Container2.p12 + + assert _Container.p12() == {"p11": 0} + assert _Container1.p12() == {"p11": 1} + assert _Container2.p12() == {"p11": 2} + + assert _Container1.p13() == 11 + assert _Container2.p13() == 22 + + +def test_copy_with_parent_dependency(): + # See: https://github.com/ets-labs/python-dependency-injector/issues/477 + class Base(containers.DeclarativeContainer): + p11 = providers.Object(0) + p12 = providers.Factory(dict, p11=p11) + + @containers.copy(Base) + class New(Base): + p13 = providers.Factory(dict, p12=Base.p12) + + new1 = New() + new2 = New(p11=1) + new3 = New(p11=2) + + assert new1.p13() == {"p12": {"p11": 0}} + assert new2.p13() == {"p12": {"p11": 1}} + assert new3.p13() == {"p12": {"p11": 2}} + + +def test_copy_with_replacing_subcontainer_providers(): + # See: https://github.com/ets-labs/python-dependency-injector/issues/374 + class X(containers.DeclarativeContainer): + foo = providers.Dependency(instance_of=str) + + def build_x(): + return X(foo="1") + + class A(containers.DeclarativeContainer): + x = providers.DependenciesContainer(**X.providers) + y = x.foo + + @containers.copy(A) + class B1(A): + x = providers.Container(build_x) + + b1 = B1() + + assert b1.y() == "1" + + +def test_containers_attribute(): + class Container(containers.DeclarativeContainer): + class Container1(containers.DeclarativeContainer): + pass + + class Container2(containers.DeclarativeContainer): + pass + + Container3 = containers.DynamicContainer() + + assert Container.containers == dict( + Container1=Container.Container1, + Container2=Container.Container2, + Container3=Container.Container3, + ) + + +def test_init_with_overriding_providers(): + p1 = providers.Provider() + p2 = providers.Provider() + + container = ContainerA(p11=p1, p12=p2) + + assert container.p11.last_overriding is p1 + assert container.p12.last_overriding is p2 + + +def test_init_with_overridden_dependency(): + # Bug: https://github.com/ets-labs/python-dependency-injector/issues/198 + class _Container(containers.DeclarativeContainer): + p1 = providers.Dependency(instance_of=int) + + p2 = providers.Dependency(object) + p2.override(providers.Factory(dict, p1=p1)) + + container = _Container(p1=1) + + assert container.p2() == {"p1": 1} + assert container.p2.last_overriding.kwargs["p1"] is container.p1 + assert container.p2.last_overriding.kwargs["p1"] is not _Container.p1 + assert _Container.p2.last_overriding.kwargs["p1"] is _Container.p1 + + +def test_init_with_chained_dependency(): + # Bug: https://github.com/ets-labs/python-dependency-injector/issues/200 + class _Container(containers.DeclarativeContainer): + p1 = providers.Dependency(instance_of=int) + p2 = providers.Factory(p1) + + container = _Container(p1=1) + + assert container.p2() == 1 + assert container.p2.cls is container.p1 + assert _Container.p2.cls is _Container.p1 + assert container.p2.cls is not _Container.p1 + + +def test_init_with_dependency_delegation(): + # Bug: https://github.com/ets-labs/python-dependency-injector/issues/235 + A = collections.namedtuple("A", []) + B = collections.namedtuple("B", ["fa"]) + C = collections.namedtuple("B", ["a"]) + + class Services(containers.DeclarativeContainer): + a = providers.Dependency() + c = providers.Factory(C, a=a) + b = providers.Factory(B, fa=a.provider) + + a = providers.Factory(A) + assert isinstance(Services(a=a).c().a, A) # OK + Services(a=a).b().fa() + + +def test_init_with_grand_child_provider(): + # Bug: https://github.com/ets-labs/python-dependency-injector/issues/350 + provider = providers.Provider() + container = ContainerC(p11=provider) + + assert isinstance(container.p11, providers.Provider) + assert isinstance(container.p12, providers.Provider) + assert isinstance(container.p21, providers.Provider) + assert isinstance(container.p22, providers.Provider) + assert isinstance(container.p31, providers.Provider) + assert isinstance(container.p32, providers.Provider) + assert container.p11.last_overriding is provider + + +def test_parent_set_in__new__(): + class Container(containers.DeclarativeContainer): + dependency = providers.Dependency() + dependencies_container = providers.DependenciesContainer() + container = providers.Container(ContainerA) + + assert Container.dependency.parent is Container + assert Container.dependencies_container.parent is Container + assert Container.container.parent is Container + + +def test_parent_set_in__setattr__(): + class Container(containers.DeclarativeContainer): + pass + + Container.dependency = providers.Dependency() + Container.dependencies_container = providers.DependenciesContainer() + Container.container = providers.Container(ContainerA) + + assert Container.dependency.parent is Container + assert Container.dependencies_container.parent is Container + assert Container.container.parent is Container + + +def test_resolve_provider_name(): + assert ContainerA.resolve_provider_name(ContainerA.p11) == "p11" + + +def test_resolve_provider_name_no_provider(): + with raises(errors.Error): + ContainerA.resolve_provider_name(providers.Provider()) + + +def test_child_dependency_parent_name(): + class Container(containers.DeclarativeContainer): + dependency = providers.Dependency() + + with raises(errors.Error, match="Dependency \"Container.dependency\" is not defined"): + Container.dependency() + + +def test_child_dependencies_container_parent_name(): + class Container(containers.DeclarativeContainer): + dependencies_container = providers.DependenciesContainer() + + with raises(errors.Error, match="Dependency \"Container.dependencies_container.dependency\" is not defined"): + Container.dependencies_container.dependency() + + +def test_child_container_parent_name(): + class ChildContainer(containers.DeclarativeContainer): + dependency = providers.Dependency() + + class Container(containers.DeclarativeContainer): + child_container = providers.Container(ChildContainer) + + with raises(errors.Error, match="Dependency \"Container.child_container.dependency\" is not defined"): + Container.child_container.dependency() diff --git a/tests/unit/containers/test_declarative_py2_py3.py b/tests/unit/containers/test_declarative_py2_py3.py index f6176893..ac774e3f 100644 --- a/tests/unit/containers/test_declarative_py2_py3.py +++ b/tests/unit/containers/test_declarative_py2_py3.py @@ -1,517 +1,13 @@ """Dependency injector declarative container unit tests.""" -import collections import unittest from dependency_injector import ( containers, providers, - errors, ) -class ContainerA(containers.DeclarativeContainer): - p11 = providers.Provider() - p12 = providers.Provider() - - -class ContainerB(ContainerA): - p21 = providers.Provider() - p22 = providers.Provider() - - -class ContainerC(ContainerB): - p31 = providers.Provider() - p32 = providers.Provider() - - -class DeclarativeContainerTests(unittest.TestCase): - - def test_providers_attribute(self): - self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12)) - self.assertEqual(ContainerB.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p21=ContainerB.p21, - p22=ContainerB.p22)) - self.assertEqual(ContainerC.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p21=ContainerB.p21, - p22=ContainerB.p22, - p31=ContainerC.p31, - p32=ContainerC.p32)) - - def test_providers_attribute_with_redefinition(self): - p1 = providers.Provider() - p2 = providers.Provider() - - class ContainerA2(ContainerA): - p11 = p1 - p12 = p2 - - self.assertEqual( - ContainerA.providers, - { - "p11": ContainerA.p11, - "p12": ContainerA.p12, - }, - ) - self.assertEqual( - ContainerA2.providers, - { - "p11": p1, - "p12": p2, - }, - ) - - def test_cls_providers_attribute(self): - self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12)) - self.assertEqual(ContainerB.cls_providers, dict(p21=ContainerB.p21, - p22=ContainerB.p22)) - self.assertEqual(ContainerC.cls_providers, dict(p31=ContainerC.p31, - p32=ContainerC.p32)) - - def test_inherited_providers_attribute(self): - self.assertEqual(ContainerA.inherited_providers, dict()) - self.assertEqual(ContainerB.inherited_providers, - dict(p11=ContainerA.p11, - p12=ContainerA.p12)) - self.assertEqual(ContainerC.inherited_providers, - dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p21=ContainerB.p21, - p22=ContainerB.p22)) - - def test_dependencies_attribute(self): - class ContainerD(ContainerC): - p41 = providers.Dependency() - p42 = providers.DependenciesContainer() - - class ContainerE(ContainerD): - p51 = providers.Dependency() - p52 = providers.DependenciesContainer() - - self.assertEqual( - ContainerD.dependencies, - { - "p41": ContainerD.p41, - "p42": ContainerD.p42, - }, - ) - self.assertEqual( - ContainerE.dependencies, - { - "p41": ContainerD.p41, - "p42": ContainerD.p42, - "p51": ContainerE.p51, - "p52": ContainerE.p52, - }, - ) - - def test_set_get_del_providers(self): - a_p13 = providers.Provider() - b_p23 = providers.Provider() - - ContainerA.p13 = a_p13 - ContainerB.p23 = b_p23 - - self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p13=a_p13)) - self.assertEqual(ContainerB.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p21=ContainerB.p21, - p22=ContainerB.p22, - p23=b_p23)) - - self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p13=a_p13)) - self.assertEqual(ContainerB.cls_providers, dict(p21=ContainerB.p21, - p22=ContainerB.p22, - p23=b_p23)) - - del ContainerA.p13 - del ContainerB.p23 - - self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12)) - self.assertEqual(ContainerB.providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12, - p21=ContainerB.p21, - p22=ContainerB.p22)) - - self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11, - p12=ContainerA.p12)) - self.assertEqual(ContainerB.cls_providers, dict(p21=ContainerB.p21, - p22=ContainerB.p22)) - - def test_declare_with_valid_provider_type(self): - class _Container(containers.DeclarativeContainer): - provider_type = providers.Object - px = providers.Object(object()) - - self.assertIsInstance(_Container.px, providers.Object) - - def test_declare_with_invalid_provider_type(self): - with self.assertRaises(errors.Error): - class _Container(containers.DeclarativeContainer): - provider_type = providers.Object - px = providers.Provider() - - def test_seth_valid_provider_type(self): - class _Container(containers.DeclarativeContainer): - provider_type = providers.Object - - _Container.px = providers.Object(object()) - - self.assertIsInstance(_Container.px, providers.Object) - - def test_set_invalid_provider_type(self): - class _Container(containers.DeclarativeContainer): - provider_type = providers.Object - - with self.assertRaises(errors.Error): - _Container.px = providers.Provider() - - def test_override(self): - class _Container(containers.DeclarativeContainer): - p11 = providers.Provider() - - class _OverridingContainer1(containers.DeclarativeContainer): - p11 = providers.Provider() - - class _OverridingContainer2(containers.DeclarativeContainer): - p11 = providers.Provider() - p12 = providers.Provider() - - _Container.override(_OverridingContainer1) - _Container.override(_OverridingContainer2) - - self.assertEqual(_Container.overridden, - (_OverridingContainer1, - _OverridingContainer2)) - self.assertEqual(_Container.p11.overridden, - (_OverridingContainer1.p11, - _OverridingContainer2.p11)) - - def test_override_with_itself(self): - with self.assertRaises(errors.Error): - ContainerA.override(ContainerA) - - def test_override_with_parent(self): - with self.assertRaises(errors.Error): - ContainerB.override(ContainerA) - - def test_override_decorator(self): - class _Container(containers.DeclarativeContainer): - p11 = providers.Provider() - - @containers.override(_Container) - class _OverridingContainer1(containers.DeclarativeContainer): - p11 = providers.Provider() - - @containers.override(_Container) - class _OverridingContainer2(containers.DeclarativeContainer): - p11 = providers.Provider() - p12 = providers.Provider() - - self.assertEqual(_Container.overridden, - (_OverridingContainer1, - _OverridingContainer2)) - self.assertEqual(_Container.p11.overridden, - (_OverridingContainer1.p11, - _OverridingContainer2.p11)) - - def test_reset_last_overriding(self): - class _Container(containers.DeclarativeContainer): - p11 = providers.Provider() - - class _OverridingContainer1(containers.DeclarativeContainer): - p11 = providers.Provider() - - class _OverridingContainer2(containers.DeclarativeContainer): - p11 = providers.Provider() - p12 = providers.Provider() - - _Container.override(_OverridingContainer1) - _Container.override(_OverridingContainer2) - _Container.reset_last_overriding() - - self.assertEqual(_Container.overridden, - (_OverridingContainer1,)) - self.assertEqual(_Container.p11.overridden, - (_OverridingContainer1.p11,)) - - def test_reset_last_overriding_when_not_overridden(self): - with self.assertRaises(errors.Error): - ContainerA.reset_last_overriding() - - def test_reset_override(self): - class _Container(containers.DeclarativeContainer): - p11 = providers.Provider() - - class _OverridingContainer1(containers.DeclarativeContainer): - p11 = providers.Provider() - - class _OverridingContainer2(containers.DeclarativeContainer): - p11 = providers.Provider() - p12 = providers.Provider() - - _Container.override(_OverridingContainer1) - _Container.override(_OverridingContainer2) - _Container.reset_override() - - self.assertEqual(_Container.overridden, tuple()) - self.assertEqual(_Container.p11.overridden, tuple()) - - def test_copy(self): - @containers.copy(ContainerA) - class _Container1(ContainerA): - pass - - @containers.copy(ContainerA) - class _Container2(ContainerA): - pass - - self.assertIsNot(ContainerA.p11, _Container1.p11) - self.assertIsNot(ContainerA.p12, _Container1.p12) - - self.assertIsNot(ContainerA.p11, _Container2.p11) - self.assertIsNot(ContainerA.p12, _Container2.p12) - - self.assertIsNot(_Container1.p11, _Container2.p11) - self.assertIsNot(_Container1.p12, _Container2.p12) - - def test_copy_with_replacing(self): - class _Container(containers.DeclarativeContainer): - p11 = providers.Object(0) - p12 = providers.Factory(dict, p11=p11) - - @containers.copy(_Container) - class _Container1(_Container): - p11 = providers.Object(1) - p13 = providers.Object(11) - - @containers.copy(_Container) - class _Container2(_Container): - p11 = providers.Object(2) - p13 = providers.Object(22) - - self.assertIsNot(_Container.p11, _Container1.p11) - self.assertIsNot(_Container.p12, _Container1.p12) - - self.assertIsNot(_Container.p11, _Container2.p11) - self.assertIsNot(_Container.p12, _Container2.p12) - - self.assertIsNot(_Container1.p11, _Container2.p11) - self.assertIsNot(_Container1.p12, _Container2.p12) - - self.assertEqual(_Container.p12(), {"p11": 0}) - self.assertEqual(_Container1.p12(), {"p11": 1}) - self.assertEqual(_Container2.p12(), {"p11": 2}) - - self.assertEqual(_Container1.p13(), 11) - self.assertEqual(_Container2.p13(), 22) - - def test_copy_with_parent_dependency(self): - # See: https://github.com/ets-labs/python-dependency-injector/issues/477 - class Base(containers.DeclarativeContainer): - p11 = providers.Object(0) - p12 = providers.Factory(dict, p11=p11) - - @containers.copy(Base) - class New(Base): - p13 = providers.Factory(dict, p12=Base.p12) - - new1 = New() - new2 = New(p11=1) - new3 = New(p11=2) - - self.assertEqual(new1.p13(), {"p12": {"p11": 0}}) - self.assertEqual(new2.p13(), {"p12": {"p11": 1}}) - self.assertEqual(new3.p13(), {"p12": {"p11": 2}}) - - def test_copy_with_replacing_subcontainer_providers(self): - # See: https://github.com/ets-labs/python-dependency-injector/issues/374 - class X(containers.DeclarativeContainer): - foo = providers.Dependency(instance_of=str) - - def build_x(): - return X(foo="1") - - class A(containers.DeclarativeContainer): - x = providers.DependenciesContainer(**X.providers) - y = x.foo - - @containers.copy(A) - class B1(A): - x = providers.Container(build_x) - - b1 = B1() - - self.assertEqual(b1.y(), "1") - - def test_containers_attribute(self): - class Container(containers.DeclarativeContainer): - class Container1(containers.DeclarativeContainer): - pass - - class Container2(containers.DeclarativeContainer): - pass - - Container3 = containers.DynamicContainer() - - self.assertEqual(Container.containers, - dict(Container1=Container.Container1, - Container2=Container.Container2, - Container3=Container.Container3)) - - def test_init_with_overriding_providers(self): - p1 = providers.Provider() - p2 = providers.Provider() - - container = ContainerA(p11=p1, p12=p2) - - self.assertIs(container.p11.last_overriding, p1) - self.assertIs(container.p12.last_overriding, p2) - - def test_init_with_overridden_dependency(self): - # Bug: - # https://github.com/ets-labs/python-dependency-injector/issues/198 - class _Container(containers.DeclarativeContainer): - p1 = providers.Dependency(instance_of=int) - - p2 = providers.Dependency(object) - p2.override(providers.Factory(dict, p1=p1)) - - container = _Container(p1=1) - - self.assertEqual(container.p2(), {"p1": 1}) - self.assertIs( - container.p2.last_overriding.kwargs["p1"], - container.p1, - ) - self.assertIsNot( - container.p2.last_overriding.kwargs["p1"], - _Container.p1, - ) - self.assertIs( - _Container.p2.last_overriding.kwargs["p1"], - _Container.p1, - ) - - def test_init_with_chained_dependency(self): - # Bug: - # https://github.com/ets-labs/python-dependency-injector/issues/200 - class _Container(containers.DeclarativeContainer): - p1 = providers.Dependency(instance_of=int) - p2 = providers.Factory(p1) - - container = _Container(p1=1) - - self.assertEqual(container.p2(), 1) - self.assertIs(container.p2.cls, container.p1) - self.assertIs(_Container.p2.cls, _Container.p1) - self.assertIsNot(container.p2.cls, _Container.p1) - - def test_init_with_dependency_delegation(self): - # Bug: - # https://github.com/ets-labs/python-dependency-injector/issues/235 - A = collections.namedtuple("A", []) - B = collections.namedtuple("B", ["fa"]) - C = collections.namedtuple("B", ["a"]) - - class Services(containers.DeclarativeContainer): - a = providers.Dependency() - c = providers.Factory(C, a=a) - b = providers.Factory(B, fa=a.provider) - - a = providers.Factory(A) - assert isinstance(Services(a=a).c().a, A) # ok - Services(a=a).b().fa() - - def test_init_with_grand_child_provider(self): - # Bug: - # https://github.com/ets-labs/python-dependency-injector/issues/350 - provider = providers.Provider() - container = ContainerC(p11=provider) - - self.assertIsInstance(container.p11, providers.Provider) - self.assertIsInstance(container.p12, providers.Provider) - self.assertIsInstance(container.p21, providers.Provider) - self.assertIsInstance(container.p22, providers.Provider) - self.assertIsInstance(container.p31, providers.Provider) - self.assertIsInstance(container.p32, providers.Provider) - self.assertIs(container.p11.last_overriding, provider) - - def test_parent_set_in__new__(self): - class Container(containers.DeclarativeContainer): - dependency = providers.Dependency() - dependencies_container = providers.DependenciesContainer() - container = providers.Container(ContainerA) - - self.assertIs(Container.dependency.parent, Container) - self.assertIs(Container.dependencies_container.parent, Container) - self.assertIs(Container.container.parent, Container) - - def test_parent_set_in__setattr__(self): - class Container(containers.DeclarativeContainer): - pass - - Container.dependency = providers.Dependency() - Container.dependencies_container = providers.DependenciesContainer() - Container.container = providers.Container(ContainerA) - - self.assertIs(Container.dependency.parent, Container) - self.assertIs(Container.dependencies_container.parent, Container) - self.assertIs(Container.container.parent, Container) - - def test_resolve_provider_name(self): - self.assertEqual(ContainerA.resolve_provider_name(ContainerA.p11), "p11") - - def test_resolve_provider_name_no_provider(self): - with self.assertRaises(errors.Error): - ContainerA.resolve_provider_name(providers.Provider()) - - def test_child_dependency_parent_name(self): - class Container(containers.DeclarativeContainer): - dependency = providers.Dependency() - - with self.assertRaises(errors.Error) as context: - Container.dependency() - self.assertEqual( - str(context.exception), - "Dependency \"Container.dependency\" is not defined", - ) - - def test_child_dependencies_container_parent_name(self): - class Container(containers.DeclarativeContainer): - dependencies_container = providers.DependenciesContainer() - - with self.assertRaises(errors.Error) as context: - Container.dependencies_container.dependency() - self.assertEqual( - str(context.exception), - "Dependency \"Container.dependencies_container.dependency\" is not defined", - ) - - def test_child_container_parent_name(self): - class ChildContainer(containers.DeclarativeContainer): - dependency = providers.Dependency() - - class Container(containers.DeclarativeContainer): - child_container = providers.Container(ChildContainer) - - with self.assertRaises(errors.Error) as context: - Container.child_container.dependency() - self.assertEqual( - str(context.exception), - "Dependency \"Container.child_container.dependency\" is not defined", - ) - - class DeclarativeContainerWithCustomStringTests(unittest.TestCase): # See: https://github.com/ets-labs/python-dependency-injector/issues/479