Fix #380: .init_resources() and .shutdown_resource() dont ignore nested resources

This commit is contained in:
Roman Mogylatov 2021-02-01 09:54:36 -05:00
parent 3ca6dd9af1
commit e9a16d1f17
4 changed files with 962 additions and 986 deletions

View File

@ -10,6 +10,10 @@ follows `Semantic versioning`_
Development version Development version
------------------- -------------------
- Add container providers traversal. - Add container providers traversal.
- Fix an issue with ``container.init_resource()`` and ``container.shutdown_resource()`` ignoring
nested resources that are not present on the root level.
See issue: `#380 <https://github.com/ets-labs/python-dependency-injector/issues/380>`_.
Thanks to `@approxit <https://github.com/approxit>`_ for finding and reporting the issue.
- Add ``.provides`` attribute to ``Singleton`` and its subclasses. - Add ``.provides`` attribute to ``Singleton`` and its subclasses.
It's a consistency change to make ``Singleton`` match ``Callable`` It's a consistency change to make ``Singleton`` match ``Callable``
and ``Factory`` interfaces. and ``Factory`` interfaces.

File diff suppressed because it is too large Load Diff

View File

@ -239,10 +239,8 @@ class DynamicContainer(object):
def init_resources(self): def init_resources(self):
"""Initialize all container resources.""" """Initialize all container resources."""
futures = [] futures = []
for provider in self.providers.values():
if not isinstance(provider, providers.Resource):
continue
for provider in self.traverse(types=[providers.Resource]):
resource = provider.init() resource = provider.init()
if _isawaitable(resource): if _isawaitable(resource):
@ -254,10 +252,8 @@ class DynamicContainer(object):
def shutdown_resources(self): def shutdown_resources(self):
"""Shutdown all container resources.""" """Shutdown all container resources."""
futures = [] futures = []
for provider in self.providers.values():
if not isinstance(provider, providers.Resource):
continue
for provider in self.traverse(types=[providers.Resource]):
shutdown = provider.shutdown() shutdown = provider.shutdown()
if _isawaitable(shutdown): if _isawaitable(shutdown):

View File

@ -237,3 +237,53 @@ 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 test_init_shutdown_nested_resources(self):
def _init1():
_init1.init_counter += 1
yield
_init1.shutdown_counter += 1
_init1.init_counter = 0
_init1.shutdown_counter = 0
def _init2():
_init2.init_counter += 1
yield
_init2.shutdown_counter += 1
_init2.init_counter = 0
_init2.shutdown_counter = 0
class Container(containers.DeclarativeContainer):
service = providers.Factory(
dict,
resource1=providers.Resource(_init1),
resource2=providers.Resource(_init2),
)
container = Container()
self.assertEqual(_init1.init_counter, 0)
self.assertEqual(_init1.shutdown_counter, 0)
self.assertEqual(_init2.init_counter, 0)
self.assertEqual(_init2.shutdown_counter, 0)
container.init_resources()
self.assertEqual(_init1.init_counter, 1)
self.assertEqual(_init1.shutdown_counter, 0)
self.assertEqual(_init2.init_counter, 1)
self.assertEqual(_init2.shutdown_counter, 0)
container.shutdown_resources()
self.assertEqual(_init1.init_counter, 1)
self.assertEqual(_init1.shutdown_counter, 1)
self.assertEqual(_init2.init_counter, 1)
self.assertEqual(_init2.shutdown_counter, 1)
container.init_resources()
container.shutdown_resources()
self.assertEqual(_init1.init_counter, 2)
self.assertEqual(_init1.shutdown_counter, 2)
self.assertEqual(_init2.init_counter, 2)
self.assertEqual(_init2.shutdown_counter, 2)