mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Improve async mode exceptions handling to prevent infinite hanging when exception occurs
This commit is contained in:
		
							parent
							
								
									f470400bbe
								
							
						
					
					
						commit
						131373227c
					
				| 
						 | 
					@ -9,7 +9,8 @@ follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Development version
 | 
					Development version
 | 
				
			||||||
-------------------
 | 
					-------------------
 | 
				
			||||||
- Fix double printing of exception when initializing resource causes error.
 | 
					- Improve async mode exceptions handling to prevent infinite hanging when exception occurs.
 | 
				
			||||||
 | 
					- Fix double printing of exception when resource initialization causes an error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4.23.1
 | 
					4.23.1
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -455,10 +455,14 @@ cdef inline void __async_prepare_args_kwargs_callback(
 | 
				
			||||||
        object awaitables,
 | 
					        object awaitables,
 | 
				
			||||||
        object future,
 | 
					        object future,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    awaited = future.result()
 | 
					    try:
 | 
				
			||||||
    for value, (key, _) in zip(awaited, awaitables):
 | 
					        awaited = future.result()
 | 
				
			||||||
        args[key] = value
 | 
					    except Exception as exception:
 | 
				
			||||||
    future_result.set_result(args)
 | 
					        future_result.set_exception(exception)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        for value, (key, _) in zip(awaited, awaitables):
 | 
				
			||||||
 | 
					            args[key] = value
 | 
				
			||||||
 | 
					        future_result.set_result(args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@cython.boundscheck(False)
 | 
					@cython.boundscheck(False)
 | 
				
			||||||
| 
						 | 
					@ -560,19 +564,28 @@ cdef inline object __call(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cdef inline void __async_call_callback(object future_result, object call, object future):
 | 
					cdef inline void __async_call_callback(object future_result, object call, object future):
 | 
				
			||||||
    args, kwargs = future.result()
 | 
					    try:
 | 
				
			||||||
    result = call(*args, **kwargs)
 | 
					        args, kwargs = future.result()
 | 
				
			||||||
 | 
					    except Exception as exception:
 | 
				
			||||||
 | 
					        future_result.set_exception(exception)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        result = call(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if __isawaitable(result):
 | 
					        if __isawaitable(result):
 | 
				
			||||||
        result = asyncio.ensure_future(result)
 | 
					            result = asyncio.ensure_future(result)
 | 
				
			||||||
        result.add_done_callback(functools.partial(__async_result_callback, future_result))
 | 
					            result.add_done_callback(functools.partial(__async_result_callback, future_result))
 | 
				
			||||||
        return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    future_result.set_result(result)
 | 
					        future_result.set_result(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cdef inline object __async_result_callback(object future_result, object future):
 | 
					cdef inline object __async_result_callback(object future_result, object future):
 | 
				
			||||||
    future_result.set_result(future.result())
 | 
					    try:
 | 
				
			||||||
 | 
					        result = future.result()
 | 
				
			||||||
 | 
					    except Exception as exception:
 | 
				
			||||||
 | 
					        future_result.set_exception(exception)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        future_result.set_result(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cdef inline object __callable_call(Callable self, tuple args, dict kwargs):
 | 
					cdef inline object __callable_call(Callable self, tuple args, dict kwargs):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,6 +190,25 @@ class FactoryTests(AsyncTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertIsNot(service1.client, service2.client)
 | 
					        self.assertIsNot(service1.client, service2.client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_kwargs_error_injection(self):
 | 
				
			||||||
 | 
					        async def init_resource():
 | 
				
			||||||
 | 
					            raise Exception('Something went wrong')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class Container(containers.DeclarativeContainer):
 | 
				
			||||||
 | 
					            resource_with_error = providers.Resource(init_resource)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            client = providers.Factory(
 | 
				
			||||||
 | 
					                Client,
 | 
				
			||||||
 | 
					                resource1=resource_with_error,
 | 
				
			||||||
 | 
					                resource2=None,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        container = Container()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with self.assertRaises(Exception) as context:
 | 
				
			||||||
 | 
					            self._run(container.client())
 | 
				
			||||||
 | 
					        self.assertEqual(str(context.exception), 'Something went wrong')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_attributes_injection(self):
 | 
					    def test_attributes_injection(self):
 | 
				
			||||||
        class ContainerWithAttributes(containers.DeclarativeContainer):
 | 
					        class ContainerWithAttributes(containers.DeclarativeContainer):
 | 
				
			||||||
            resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | 
					            resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user