mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-25 11:04:01 +03:00
Container.reset_singletons() (#390)
* Rename container tests * Add implementation + tests * Update changelog * Add examples and docs
This commit is contained in:
parent
c4892af31e
commit
c964253204
|
@ -23,4 +23,5 @@ Containers module API docs - :py:mod:`dependency_injector.containers`.
|
||||||
dynamic
|
dynamic
|
||||||
specialization
|
specialization
|
||||||
overriding
|
overriding
|
||||||
|
reset_singletons
|
||||||
traversal
|
traversal
|
||||||
|
|
19
docs/containers/reset_singletons.rst
Normal file
19
docs/containers/reset_singletons.rst
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Reset container singletons
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
To reset all container singletons use method ``.reset_singletons()``.
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/containers/reset_singletons.py
|
||||||
|
:language: python
|
||||||
|
:lines: 3-
|
||||||
|
:emphasize-lines: 16
|
||||||
|
|
||||||
|
Method ``.reset_singletons()`` also resets singletons in sub-containers: ``providers.Container`` and
|
||||||
|
``providers.DependenciesContainer.``
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/containers/reset_singletons_subcontainers.py
|
||||||
|
:language: python
|
||||||
|
:lines: 3-
|
||||||
|
:emphasize-lines: 21
|
||||||
|
|
||||||
|
.. disqus::
|
|
@ -9,6 +9,7 @@ follows `Semantic versioning`_
|
||||||
|
|
||||||
Development version
|
Development version
|
||||||
-------------------
|
-------------------
|
||||||
|
- Add ``container.reset_singleton()`` method to reset container singletons.
|
||||||
- Refactor ``container.apply_container_providers_overridings()`` to use ``container.traverse()``.
|
- Refactor ``container.apply_container_providers_overridings()`` to use ``container.traverse()``.
|
||||||
This enables deep lazy initialization of ``Container`` providers.
|
This enables deep lazy initialization of ``Container`` providers.
|
||||||
- Add tests for ``Selector`` provider.
|
- Add tests for ``Selector`` provider.
|
||||||
|
|
21
examples/containers/reset_singletons.py
Normal file
21
examples/containers/reset_singletons.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
"""Container reset singletons example."""
|
||||||
|
|
||||||
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service1 = providers.Singleton(object)
|
||||||
|
service2 = providers.Singleton(object)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
service1 = container.service1()
|
||||||
|
service2 = container.service2()
|
||||||
|
|
||||||
|
container.reset_singletons()
|
||||||
|
|
||||||
|
assert service1 is not container.service1()
|
||||||
|
assert service2 is not container.service2()
|
26
examples/containers/reset_singletons_subcontainers.py
Normal file
26
examples/containers/reset_singletons_subcontainers.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
"""Container reset singletons in subcontainer example."""
|
||||||
|
|
||||||
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
|
class SubContainer(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service = providers.Singleton(object)
|
||||||
|
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service = providers.Singleton(object)
|
||||||
|
sub = providers.Container(SubContainer)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
service1 = container.service()
|
||||||
|
service2 = container.sub().service()
|
||||||
|
|
||||||
|
container.reset_singletons()
|
||||||
|
|
||||||
|
assert service1 is not container.service()
|
||||||
|
assert service2 is not container.sub().service()
|
File diff suppressed because it is too large
Load Diff
|
@ -43,6 +43,8 @@ class Container:
|
||||||
def unwire(self) -> None: ...
|
def unwire(self) -> None: ...
|
||||||
def init_resources(self) -> Optional[Awaitable]: ...
|
def init_resources(self) -> Optional[Awaitable]: ...
|
||||||
def shutdown_resources(self) -> Optional[Awaitable]: ...
|
def shutdown_resources(self) -> Optional[Awaitable]: ...
|
||||||
|
def apply_container_providers_overridings(self) -> None: ...
|
||||||
|
def reset_singletons(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def traverse(self, types: Optional[Sequence[Type]] = None) -> Iterator[Provider]: ...
|
def traverse(self, types: Optional[Sequence[Type]] = None) -> Iterator[Provider]: ...
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -271,6 +271,11 @@ class DynamicContainer(Container):
|
||||||
for provider in self.traverse(types=[providers.Container]):
|
for provider in self.traverse(types=[providers.Container]):
|
||||||
provider.apply_overridings()
|
provider.apply_overridings()
|
||||||
|
|
||||||
|
def reset_singletons(self):
|
||||||
|
"""Reset all container singletons."""
|
||||||
|
for provider in self.traverse(types=[providers.Singleton]):
|
||||||
|
provider.reset()
|
||||||
|
|
||||||
|
|
||||||
class DeclarativeContainerMetaClass(type):
|
class DeclarativeContainerMetaClass(type):
|
||||||
"""Declarative inversion of control container meta class."""
|
"""Declarative inversion of control container meta class."""
|
||||||
|
|
|
@ -140,7 +140,7 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
container_a.override_providers(unknown=providers.Provider())
|
container_a.override_providers(unknown=providers.Provider())
|
||||||
|
|
||||||
def test_reset_last_overridding(self):
|
def test_reset_last_overriding(self):
|
||||||
class _Container(containers.DeclarativeContainer):
|
class _Container(containers.DeclarativeContainer):
|
||||||
p11 = providers.Provider()
|
p11 = providers.Provider()
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
self.assertEqual(container.p11.overridden,
|
self.assertEqual(container.p11.overridden,
|
||||||
(overriding_container1.p11,))
|
(overriding_container1.p11,))
|
||||||
|
|
||||||
def test_reset_last_overridding_when_not_overridden(self):
|
def test_reset_last_overriding_when_not_overridden(self):
|
||||||
container = ContainerA()
|
container = ContainerA()
|
||||||
|
|
||||||
with self.assertRaises(errors.Error):
|
with self.assertRaises(errors.Error):
|
||||||
|
@ -287,3 +287,51 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
self.assertEqual(_init1.shutdown_counter, 2)
|
self.assertEqual(_init1.shutdown_counter, 2)
|
||||||
self.assertEqual(_init2.init_counter, 2)
|
self.assertEqual(_init2.init_counter, 2)
|
||||||
self.assertEqual(_init2.shutdown_counter, 2)
|
self.assertEqual(_init2.shutdown_counter, 2)
|
||||||
|
|
||||||
|
def reset_singletons(self):
|
||||||
|
class SubSubContainer(containers.DeclarativeContainer):
|
||||||
|
singleton = providers.Singleton(object)
|
||||||
|
|
||||||
|
class SubContainer(containers.DeclarativeContainer):
|
||||||
|
singleton = providers.Singleton(object)
|
||||||
|
sub_sub_container = providers.Container(SubSubContainer)
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
singleton = providers.Singleton(object)
|
||||||
|
sub_container = providers.Container(SubContainer)
|
||||||
|
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
obj11 = container.singleton()
|
||||||
|
obj12 = container.sub_container().singleton()
|
||||||
|
obj13 = container.sub_container().sub_sub_container().singleton()
|
||||||
|
|
||||||
|
obj21 = container.singleton()
|
||||||
|
obj22 = container.sub_container().singleton()
|
||||||
|
obj23 = container.sub_container().sub_sub_container().singleton()
|
||||||
|
|
||||||
|
self.assertIs(obj11, obj21)
|
||||||
|
self.assertIs(obj12, obj22)
|
||||||
|
self.assertIs(obj13, obj23)
|
||||||
|
|
||||||
|
container.reset_singletons()
|
||||||
|
|
||||||
|
obj31 = container.singleton()
|
||||||
|
obj32 = container.sub_container().singleton()
|
||||||
|
obj33 = container.sub_container().sub_sub_container().singleton()
|
||||||
|
|
||||||
|
obj41 = container.singleton()
|
||||||
|
obj42 = container.sub_container().singleton()
|
||||||
|
obj43 = container.sub_container().sub_sub_container().singleton()
|
||||||
|
|
||||||
|
self.assertIsNot(obj11, obj31)
|
||||||
|
self.assertIsNot(obj12, obj32)
|
||||||
|
self.assertIsNot(obj13, obj33)
|
||||||
|
|
||||||
|
self.assertIsNot(obj21, obj31)
|
||||||
|
self.assertIsNot(obj22, obj32)
|
||||||
|
self.assertIsNot(obj23, obj33)
|
||||||
|
|
||||||
|
self.assertIs(obj31, obj41)
|
||||||
|
self.assertIs(obj32, obj42)
|
||||||
|
self.assertIs(obj33, obj43)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user