mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-03-13 08:25:50 +03:00
Improve async mode exceptions handling
This commit is contained in:
parent
131373227c
commit
77b8d55203
|
@ -9,8 +9,8 @@ follows `Semantic versioning`_
|
|||
|
||||
Development version
|
||||
-------------------
|
||||
- Improve async mode exceptions handling to prevent infinite hanging when exception occurs.
|
||||
- Fix double printing of exception when resource initialization causes an error.
|
||||
- Improve async mode exceptions handling.
|
||||
- Fix double printing of exception when resource initialization causes an error in async mode.
|
||||
|
||||
4.23.1
|
||||
------
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -457,11 +457,12 @@ cdef inline void __async_prepare_args_kwargs_callback(
|
|||
):
|
||||
try:
|
||||
awaited = future.result()
|
||||
|
||||
for value, (key, _) in zip(awaited, awaitables):
|
||||
args[key] = value
|
||||
except Exception as exception:
|
||||
future_result.set_exception(exception)
|
||||
else:
|
||||
for value, (key, _) in zip(awaited, awaitables):
|
||||
args[key] = value
|
||||
future_result.set_result(args)
|
||||
|
||||
|
||||
|
@ -502,8 +503,14 @@ cdef inline object __async_inject_attributes(future_instance, future_attributes)
|
|||
|
||||
|
||||
cdef inline void __async_inject_attributes_callback(object future_result, object future):
|
||||
try:
|
||||
instance, attributes = future.result()
|
||||
__inject_attributes(instance, attributes)
|
||||
|
||||
for name, value in attributes.items():
|
||||
setattr(instance, name, value)
|
||||
except Exception as exception:
|
||||
future_result.set_exception(exception)
|
||||
else:
|
||||
future_result.set_result(instance)
|
||||
|
||||
|
||||
|
@ -566,16 +573,14 @@ cdef inline object __call(
|
|||
cdef inline void __async_call_callback(object future_result, object call, object future):
|
||||
try:
|
||||
args, kwargs = future.result()
|
||||
result = call(*args, **kwargs)
|
||||
except Exception as exception:
|
||||
future_result.set_exception(exception)
|
||||
else:
|
||||
result = call(*args, **kwargs)
|
||||
|
||||
if __isawaitable(result):
|
||||
result = asyncio.ensure_future(result)
|
||||
result.add_done_callback(functools.partial(__async_result_callback, future_result))
|
||||
return
|
||||
|
||||
future_result.set_result(result)
|
||||
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ class FactoryTests(AsyncTestCase):
|
|||
|
||||
self.assertIsNot(service1.client, service2.client)
|
||||
|
||||
def test_kwargs_error_injection(self):
|
||||
def test_injection_error(self):
|
||||
async def init_resource():
|
||||
raise Exception('Something went wrong')
|
||||
|
||||
|
@ -209,6 +209,47 @@ class FactoryTests(AsyncTestCase):
|
|||
self._run(container.client())
|
||||
self.assertEqual(str(context.exception), 'Something went wrong')
|
||||
|
||||
def test_injection_runtime_error_async_provides(self):
|
||||
async def create_client(*args, **kwargs):
|
||||
raise Exception('Something went wrong')
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
|
||||
client = providers.Factory(
|
||||
create_client,
|
||||
resource1=resource,
|
||||
resource2=None,
|
||||
)
|
||||
|
||||
container = Container()
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
self._run(container.client())
|
||||
self.assertEqual(str(context.exception), 'Something went wrong')
|
||||
|
||||
def test_injection_call_error_async_provides(self):
|
||||
async def create_client(): # <-- no args defined
|
||||
...
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
|
||||
client = providers.Factory(
|
||||
create_client,
|
||||
resource1=resource,
|
||||
resource2=None,
|
||||
)
|
||||
|
||||
container = Container()
|
||||
|
||||
with self.assertRaises(TypeError) as context:
|
||||
self._run(container.client())
|
||||
self.assertEqual(
|
||||
str(context.exception),
|
||||
"create_client() got an unexpected keyword argument 'resource1'",
|
||||
)
|
||||
|
||||
def test_attributes_injection(self):
|
||||
class ContainerWithAttributes(containers.DeclarativeContainer):
|
||||
resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
|
@ -255,6 +296,53 @@ class FactoryTests(AsyncTestCase):
|
|||
|
||||
self.assertIsNot(service1.client, service2.client)
|
||||
|
||||
def test_attributes_injection_attribute_error(self):
|
||||
class ClientWithException(Client):
|
||||
@property
|
||||
def attribute_set_error(self):
|
||||
return None
|
||||
|
||||
@attribute_set_error.setter
|
||||
def attribute_set_error(self, value):
|
||||
raise Exception('Something went wrong')
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
|
||||
client = providers.Factory(
|
||||
ClientWithException,
|
||||
resource1=resource,
|
||||
resource2=resource,
|
||||
)
|
||||
client.add_attributes(attribute_set_error=123)
|
||||
|
||||
container = Container()
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
self._run(container.client())
|
||||
self.assertEqual(str(context.exception), 'Something went wrong')
|
||||
|
||||
def test_attributes_injection_runtime_error(self):
|
||||
async def init_resource():
|
||||
raise Exception('Something went wrong')
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
resource = providers.Resource(init_resource)
|
||||
|
||||
client = providers.Factory(
|
||||
Client,
|
||||
resource1=None,
|
||||
resource2=None,
|
||||
)
|
||||
client.add_attributes(resource1=resource)
|
||||
client.add_attributes(resource2=resource)
|
||||
|
||||
container = Container()
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
self._run(container.client())
|
||||
self.assertEqual(str(context.exception), 'Something went wrong')
|
||||
|
||||
def test_async_instance_and_sync_attributes_injection(self):
|
||||
class ContainerWithAttributes(containers.DeclarativeContainer):
|
||||
resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
|
|
Loading…
Reference in New Issue
Block a user