mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 09:57:37 +03:00 
			
		
		
		
	Merge branch 'release/4.34.2' into master
This commit is contained in:
		
						commit
						98a4b06a12
					
				| 
						 | 
					@ -7,6 +7,12 @@ that were made in every particular version.
 | 
				
			||||||
From version 0.7.6 *Dependency Injector* framework strictly 
 | 
					From version 0.7.6 *Dependency Injector* framework strictly 
 | 
				
			||||||
follows `Semantic versioning`_
 | 
					follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					4.34.2
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					- Fix a bug with reverse shutdown order in ``container.shutdown_resources()``.
 | 
				
			||||||
 | 
					  See issue `#432 <https://github.com/ets-labs/python-dependency-injector/issues/432>`_.
 | 
				
			||||||
 | 
					  Thanks to `Saulius Beinorius <https://github.com/saulbein>`_  for bringing up the issue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4.34.1
 | 
					4.34.1
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
- Update ``container.shutdown_resources()`` to respect dependencies order while shutdown.
 | 
					- Update ``container.shutdown_resources()`` to respect dependencies order while shutdown.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
"""Top-level package."""
 | 
					"""Top-level package."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = '4.34.1'
 | 
					__version__ = '4.34.2'
 | 
				
			||||||
"""Version number.
 | 
					"""Version number.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:type: str
 | 
					:type: str
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -290,24 +290,19 @@ class DynamicContainer(Container):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def shutdown_resources(self):
 | 
					    def shutdown_resources(self):
 | 
				
			||||||
        """Shutdown all container resources."""
 | 
					        """Shutdown all container resources."""
 | 
				
			||||||
        def _no_initialized_dependencies(resource):
 | 
					        def _independent_resources(resources):
 | 
				
			||||||
            for related in resource.related:
 | 
					            for resource in resources:
 | 
				
			||||||
                if isinstance(related, providers.Resource) and related.initialized:
 | 
					                for other_resource in resources:
 | 
				
			||||||
                    return False
 | 
					                    if not other_resource.initialized:
 | 
				
			||||||
            return True
 | 
					                        continue
 | 
				
			||||||
 | 
					                    if resource in other_resource.related:
 | 
				
			||||||
        def _without_initialized_dependencies(resources):
 | 
					                        break
 | 
				
			||||||
            return list(filter(_no_initialized_dependencies, resources))
 | 
					                else:
 | 
				
			||||||
 | 
					                    yield resource
 | 
				
			||||||
        def _any_initialized(resources):
 | 
					 | 
				
			||||||
            return any(resource.initialized for resource in resources)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def _any_in_async_mode(resources):
 | 
					 | 
				
			||||||
            return any(resource.is_async_mode_enabled() for resource in resources)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        async def _async_ordered_shutdown(resources):
 | 
					        async def _async_ordered_shutdown(resources):
 | 
				
			||||||
            while _any_initialized(resources):
 | 
					            while any(resource.initialized for resource in resources):
 | 
				
			||||||
                resources_to_shutdown = _without_initialized_dependencies(resources)
 | 
					                resources_to_shutdown = list(_independent_resources(resources))
 | 
				
			||||||
                if not resources_to_shutdown:
 | 
					                if not resources_to_shutdown:
 | 
				
			||||||
                    raise RuntimeError('Unable to resolve resources shutdown order')
 | 
					                    raise RuntimeError('Unable to resolve resources shutdown order')
 | 
				
			||||||
                futures = []
 | 
					                futures = []
 | 
				
			||||||
| 
						 | 
					@ -318,15 +313,15 @@ class DynamicContainer(Container):
 | 
				
			||||||
                await asyncio.gather(*futures)
 | 
					                await asyncio.gather(*futures)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def _sync_ordered_shutdown(resources):
 | 
					        def _sync_ordered_shutdown(resources):
 | 
				
			||||||
            while _any_initialized(resources):
 | 
					            while any(resource.initialized for resource in resources):
 | 
				
			||||||
                resources_to_shutdown = _without_initialized_dependencies(resources)
 | 
					                resources_to_shutdown = list(_independent_resources(resources))
 | 
				
			||||||
                if not resources_to_shutdown:
 | 
					                if not resources_to_shutdown:
 | 
				
			||||||
                    raise RuntimeError('Unable to resolve resources shutdown order')
 | 
					                    raise RuntimeError('Unable to resolve resources shutdown order')
 | 
				
			||||||
                for resource in resources_to_shutdown:
 | 
					                for resource in resources_to_shutdown:
 | 
				
			||||||
                    resource.shutdown()
 | 
					                    resource.shutdown()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        resources = list(self.traverse(types=[providers.Resource]))
 | 
					        resources = list(self.traverse(types=[providers.Resource]))
 | 
				
			||||||
        if _any_in_async_mode(resources):
 | 
					        if any(resource.is_async_mode_enabled() for resource in resources):
 | 
				
			||||||
            return _async_ordered_shutdown(resources)
 | 
					            return _async_ordered_shutdown(resources)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return _sync_ordered_shutdown(resources)
 | 
					            return _sync_ordered_shutdown(resources)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,15 +70,15 @@ class AsyncResourcesTest(AsyncTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run(container.shutdown_resources())
 | 
					        self._run(container.shutdown_resources())
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run(container.init_resources())
 | 
					        self._run(container.init_resources())
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run(container.shutdown_resources())
 | 
					        self._run(container.shutdown_resources())
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1', 'r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_shutdown_circular_dependencies_breaker(self):
 | 
					    def test_shutdown_circular_dependencies_breaker(self):
 | 
				
			||||||
        async def _resource(name, **_):
 | 
					        async def _resource(name, **_):
 | 
				
			||||||
| 
						 | 
					@ -148,12 +148,12 @@ class AsyncResourcesTest(AsyncTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run(container.shutdown_resources())
 | 
					        self._run(container.shutdown_resources())
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run(container.init_resources())
 | 
					        self._run(container.init_resources())
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run(container.shutdown_resources())
 | 
					        self._run(container.shutdown_resources())
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1', 'r3', 'r2', 'r1'])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,15 +233,15 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        container.shutdown_resources()
 | 
					        container.shutdown_resources()
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        container.init_resources()
 | 
					        container.init_resources()
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        container.shutdown_resources()
 | 
					        container.shutdown_resources()
 | 
				
			||||||
        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(initialized_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
				
			||||||
        self.assertEqual(shutdown_resources, ['r1', 'r2', 'r3', 'r1', 'r2', 'r3'])
 | 
					        self.assertEqual(shutdown_resources, ['r3', 'r2', 'r1', 'r3', 'r2', 'r1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_shutdown_resources_circular_dependencies_breaker(self):
 | 
					    def test_shutdown_resources_circular_dependencies_breaker(self):
 | 
				
			||||||
        def _resource(name, **_):
 | 
					        def _resource(name, **_):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user