Skip to content

Commit 2fe0e00

Browse files
authored
Singleton.full_reset() (#391)
* Improve .traverse() typing stubs * Fix container.reset_singletons() * Add implementation, tests, and typing stubs * Add docs and example * Update changelog
1 parent 78f623c commit 2fe0e00

File tree

11 files changed

+2959
-2679
lines changed

11 files changed

+2959
-2679
lines changed

docs/main/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ that were made in every particular version.
77
From version 0.7.6 *Dependency Injector* framework strictly
88
follows `Semantic versioning`_
99

10+
Development version
11+
-------------------
12+
- Add ``singleton.full_reset()`` method to reset all underlying singleton providers.
13+
- Fix ``container.reset_singleton()`` to reset all provider types, not only ``Singleton``.
14+
- Improve ``container.traverse(types=[...])`` and ``provider.traverse(types=[...])`` typing stubs
15+
to return ``types`` -typed iterator.
16+
1017
4.18.0
1118
------
1219
- Add ``container.reset_singleton()`` method to reset container singletons.

docs/providers/singleton.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ provider.
5454
Resetting of the memorized object clears the reference to it. Further object's lifecycle is
5555
managed by the garbage collector.
5656

57+
Method ``.reset()`` resets only current provider. To reset all dependent singleton providers
58+
call ``.full_reset()`` method.
59+
60+
.. literalinclude:: ../../examples/providers/singleton_full_resetting.py
61+
:language: python
62+
:lines: 3-
63+
:emphasize-lines: 25
64+
5765
Using singleton with multiple threads
5866
-------------------------------------
5967

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""`Singleton` provider full resetting example."""
2+
3+
from dependency_injector import containers, providers
4+
5+
6+
class Database:
7+
...
8+
9+
10+
class UserService:
11+
def __init__(self, db: Database):
12+
self.db = db
13+
14+
15+
class Container(containers.DeclarativeContainer):
16+
17+
database = providers.Singleton(Database)
18+
19+
user_service = providers.Singleton(UserService, db=database)
20+
21+
22+
if __name__ == '__main__':
23+
container = Container()
24+
25+
user_service1 = container.user_service()
26+
27+
container.user_service.full_reset()
28+
29+
user_service2 = container.user_service()
30+
assert user_service2 is not user_service1
31+
assert user_service2.db is not user_service1.db

examples/providers/singleton_resetting.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ class UserService:
99

1010
class Container(containers.DeclarativeContainer):
1111

12-
user_service_provider = providers.Singleton(UserService)
12+
user_service = providers.Singleton(UserService)
1313

1414

1515
if __name__ == '__main__':
1616
container = Container()
1717

18-
user_service1 = container.user_service_provider()
18+
user_service1 = container.user_service()
1919

20-
container.user_service_provider.reset()
20+
container.user_service.reset()
2121

22-
user_service2 = container.user_service_provider()
22+
user_service2 = container.user_service()
2323
assert user_service2 is not user_service1

src/dependency_injector/containers.c

Lines changed: 19 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/dependency_injector/containers.pyi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ from .providers import Provider
2121
C_Base = TypeVar('C_Base', bound='Container')
2222
C = TypeVar('C', bound='DeclarativeContainer')
2323
C_Overriding = TypeVar('C_Overriding', bound='DeclarativeContainer')
24+
TT = TypeVar('TT')
2425

2526

2627
class Container:
@@ -46,10 +47,10 @@ class Container:
4647
def apply_container_providers_overridings(self) -> None: ...
4748
def reset_singletons(self) -> None: ...
4849
@overload
49-
def traverse(self, types: Optional[Sequence[Type]] = None) -> Iterator[Provider]: ...
50+
def traverse(self, types: Optional[Sequence[TT]] = None) -> Iterator[TT]: ...
5051
@classmethod
5152
@overload
52-
def traverse(cls, types: Optional[Sequence[Type]] = None) -> Iterator[Provider]: ...
53+
def traverse(cls, types: Optional[Sequence[TT]] = None) -> Iterator[TT]: ...
5354

5455

5556
class DynamicContainer(Container): ...

src/dependency_injector/containers.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ class DynamicContainer(Container):
272272
provider.apply_overridings()
273273

274274
def reset_singletons(self):
275-
"""Reset all container singletons."""
276-
for provider in self.traverse(types=[providers.Singleton]):
275+
"""Reset container singletons."""
276+
for provider in self.traverse(types=[providers.BaseSingleton]):
277277
provider.reset()
278278

279279

0 commit comments

Comments
 (0)