"""Dependency injector container provider unit tests.""" import copy import unittest from dependency_injector import containers, providers, errors TEST_VALUE_1 = "core_section_value1" TEST_CONFIG_1 = { "core": { "section": { "value": TEST_VALUE_1, }, }, } TEST_VALUE_2 = "core_section_value2" TEST_CONFIG_2 = { "core": { "section": { "value": TEST_VALUE_2, }, }, } def _copied(value): return copy.deepcopy(value) class TestCore(containers.DeclarativeContainer): config = providers.Configuration("core") value_getter = providers.Callable(lambda _: _, config.section.value) class TestApplication(containers.DeclarativeContainer): config = providers.Configuration("config") core = providers.Container(TestCore, config=config.core) dict_factory = providers.Factory(dict, value=core.value_getter) class ContainerTests(unittest.TestCase): def test(self): application = TestApplication(config=_copied(TEST_CONFIG_1)) self.assertEqual(application.dict_factory(), {"value": TEST_VALUE_1}) def test_double_override(self): application = TestApplication() application.config.override(_copied(TEST_CONFIG_1)) application.config.override(_copied(TEST_CONFIG_2)) self.assertEqual(application.dict_factory(), {"value": TEST_VALUE_2}) def test_override(self): # See: https://github.com/ets-labs/python-dependency-injector/issues/354 class D(containers.DeclarativeContainer): foo = providers.Object("foo") class A(containers.DeclarativeContainer): d = providers.DependenciesContainer() bar = providers.Callable(lambda f: f + "++", d.foo.provided) class B(containers.DeclarativeContainer): d = providers.Container(D) a = providers.Container(A, d=d) b = B(d=D()) result = b.a().bar() self.assertEqual(result, "foo++") def test_override_not_root_provider(self): # See: https://github.com/ets-labs/python-dependency-injector/issues/379 class NestedContainer(containers.DeclarativeContainer): settings = providers.Configuration() print_settings = providers.Callable( lambda s: s, settings, ) class TestContainer(containers.DeclarativeContainer): settings = providers.Configuration() root_container = providers.Container( NestedContainer, settings=settings, ) not_root_container = providers.Selector( settings.container, using_factory=providers.Factory( NestedContainer, settings=settings, ), using_container=providers.Container( NestedContainer, settings=settings, ) ) container_using_factory = TestContainer(settings=dict( container="using_factory", foo="bar" )) self.assertEqual( container_using_factory.root_container().print_settings(), {"container": "using_factory", "foo": "bar"}, ) self.assertEqual( container_using_factory.not_root_container().print_settings(), {"container": "using_factory", "foo": "bar"}, ) container_using_container = TestContainer(settings=dict( container="using_container", foo="bar" )) self.assertEqual( container_using_container.root_container().print_settings(), {"container": "using_container", "foo": "bar"}, ) self.assertEqual( container_using_container.not_root_container().print_settings(), {"container": "using_container", "foo": "bar"}, ) def test_override_by_not_a_container(self): provider = providers.Container(TestCore) with self.assertRaises(errors.Error): provider.override(providers.Object("foo")) def test_lazy_overriding(self): # See: https://github.com/ets-labs/python-dependency-injector/issues/354 class D(containers.DeclarativeContainer): foo = providers.Object("foo") class A(containers.DeclarativeContainer): d = providers.DependenciesContainer() bar = providers.Callable(lambda f: f + "++", d.foo.provided) class B(containers.DeclarativeContainer): d = providers.DependenciesContainer() a = providers.Container(A, d=d) b = B(d=D()) result = b.a().bar() self.assertEqual(result, "foo++") def test_lazy_overriding_deep(self): # Extended version of test_lazy_overriding() class D(containers.DeclarativeContainer): foo = providers.Object("foo") class C(containers.DeclarativeContainer): d = providers.DependenciesContainer() bar = providers.Callable(lambda f: f + "++", d.foo.provided) class A(containers.DeclarativeContainer): d = providers.DependenciesContainer() c = providers.Container(C, d=d) class B(containers.DeclarativeContainer): d = providers.DependenciesContainer() a = providers.Container(A, d=d) b = B(d=D()) result = b.a().c().bar() self.assertEqual(result, "foo++") def test_reset_last_overriding(self): application = TestApplication(config=_copied(TEST_CONFIG_1)) application.core.override(TestCore(config=_copied(TEST_CONFIG_2["core"]))) application.core.reset_last_overriding() self.assertEqual(application.dict_factory(), {"value": TEST_VALUE_1}) def test_reset_last_overriding_only_overridden(self): application = TestApplication(config=_copied(TEST_CONFIG_1)) application.core.override(providers.DependenciesContainer(config=_copied(TEST_CONFIG_2["core"]))) application.core.reset_last_overriding() self.assertEqual(application.dict_factory(), {"value": TEST_VALUE_1}) def test_override_context_manager(self): application = TestApplication(config=_copied(TEST_CONFIG_1)) overriding_core = TestCore(config=_copied(TEST_CONFIG_2["core"])) with application.core.override(overriding_core) as context_core: self.assertEqual(application.dict_factory(), {"value": TEST_VALUE_2}) self.assertIs(context_core(), overriding_core) self.assertEqual(application.dict_factory(), {"value": TEST_VALUE_1}) def test_reset_override(self): application = TestApplication(config=_copied(TEST_CONFIG_1)) application.core.override(TestCore(config=_copied(TEST_CONFIG_2["core"]))) application.core.reset_override() self.assertEqual(application.dict_factory(), {"value": None}) def test_reset_override_only_overridden(self): application = TestApplication(config=_copied(TEST_CONFIG_1)) application.core.override(providers.DependenciesContainer(config=_copied(TEST_CONFIG_2["core"]))) application.core.reset_override() self.assertEqual(application.dict_factory(), {"value": None}) def test_assign_parent(self): parent = providers.DependenciesContainer() provider = providers.Container(TestCore) provider.assign_parent(parent) self.assertIs(provider.parent, parent) def test_parent_name(self): container = containers.DynamicContainer() provider = providers.Container(TestCore) container.name = provider self.assertEqual(provider.parent_name, "name") def test_parent_name_with_deep_parenting(self): provider = providers.Container(TestCore) container = providers.DependenciesContainer(name=provider) _ = providers.DependenciesContainer(container=container) self.assertEqual(provider.parent_name, "container.name") def test_parent_name_is_none(self): provider = providers.Container(TestCore) self.assertIsNone(provider.parent_name) def test_parent_deepcopy(self): container = containers.DynamicContainer() provider = providers.Container(TestCore) container.name = provider copied = providers.deepcopy(container) self.assertIs(container.name.parent, container) self.assertIs(copied.name.parent, copied) self.assertIsNot(container, copied) self.assertIsNot(container.name, copied.name) self.assertIsNot(container.name.parent, copied.name.parent) def test_resolve_provider_name(self): container = providers.Container(TestCore) self.assertEqual(container.resolve_provider_name(container.value_getter), "value_getter") def test_resolve_provider_name_no_provider(self): container = providers.Container(TestCore) with self.assertRaises(errors.Error): container.resolve_provider_name(providers.Provider())