mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-12-01 22:14:04 +03:00
Implement attribute injections and add tests
This commit is contained in:
parent
53a5d07b3a
commit
f07f3e4943
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -438,17 +438,46 @@ cdef inline void __async_prepare_args_kwargs_callback(object future):
|
||||||
|
|
||||||
@cython.boundscheck(False)
|
@cython.boundscheck(False)
|
||||||
@cython.wraparound(False)
|
@cython.wraparound(False)
|
||||||
cdef inline object __inject_attributes(
|
cdef inline object __provide_attributes(tuple attributes, int attributes_len):
|
||||||
object instance,
|
|
||||||
tuple attributes,
|
|
||||||
int attributes_len,
|
|
||||||
):
|
|
||||||
cdef NamedInjection attr_injection
|
cdef NamedInjection attr_injection
|
||||||
|
cdef dict attribute_injections = {}
|
||||||
|
cdef list awaitables = []
|
||||||
|
|
||||||
for index in range(attributes_len):
|
for index in range(attributes_len):
|
||||||
attr_injection = <NamedInjection>attributes[index]
|
attr_injection = <NamedInjection>attributes[index]
|
||||||
setattr(instance,
|
name = __get_name(attr_injection)
|
||||||
__get_name(attr_injection),
|
value = __get_value(attr_injection)
|
||||||
__get_value(attr_injection))
|
attribute_injections[name] = value
|
||||||
|
if __isawaitable(value):
|
||||||
|
awaitables.append((name, value))
|
||||||
|
|
||||||
|
if awaitables:
|
||||||
|
return __awaitable_args_kwargs_future(attribute_injections, awaitables)
|
||||||
|
|
||||||
|
return attribute_injections
|
||||||
|
|
||||||
|
|
||||||
|
cdef inline object __async_inject_attributes(future_instance, future_attributes):
|
||||||
|
future_result = asyncio.Future()
|
||||||
|
|
||||||
|
future = asyncio.Future()
|
||||||
|
future.set_result(future_result)
|
||||||
|
|
||||||
|
attributes_ready = asyncio.gather(future, future_instance, future_attributes)
|
||||||
|
attributes_ready.add_done_callback(__async_inject_attributes_callback)
|
||||||
|
asyncio.ensure_future(attributes_ready)
|
||||||
|
|
||||||
|
return future_result
|
||||||
|
|
||||||
|
cdef inline void __async_inject_attributes_callback(future):
|
||||||
|
future_result, instance, attributes = future.result()
|
||||||
|
__inject_attributes(instance, attributes)
|
||||||
|
future_result.set_result(instance)
|
||||||
|
|
||||||
|
|
||||||
|
cdef inline void __inject_attributes(object instance, dict attributes):
|
||||||
|
for name, value in attributes.items():
|
||||||
|
setattr(instance, name, value)
|
||||||
|
|
||||||
|
|
||||||
cdef inline object __call(
|
cdef inline object __call(
|
||||||
|
@ -485,7 +514,6 @@ cdef inline object __call(
|
||||||
future.set_result(kwargs)
|
future.set_result(kwargs)
|
||||||
kwargs = future
|
kwargs = future
|
||||||
|
|
||||||
|
|
||||||
future_result = asyncio.Future()
|
future_result = asyncio.Future()
|
||||||
|
|
||||||
future = asyncio.Future()
|
future = asyncio.Future()
|
||||||
|
@ -524,9 +552,25 @@ cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
|
||||||
instance = __callable_call(self.__instantiator, args, kwargs)
|
instance = __callable_call(self.__instantiator, args, kwargs)
|
||||||
|
|
||||||
if self.__attributes_len > 0:
|
if self.__attributes_len > 0:
|
||||||
__inject_attributes(instance,
|
attributes = __provide_attributes(self.__attributes, self.__attributes_len)
|
||||||
self.__attributes,
|
|
||||||
self.__attributes_len)
|
instance_awaitable = __isawaitable(instance)
|
||||||
|
attributes_awaitable = __isawaitable(attributes)
|
||||||
|
|
||||||
|
if instance_awaitable or attributes_awaitable:
|
||||||
|
if not instance_awaitable:
|
||||||
|
future = asyncio.Future()
|
||||||
|
future.set_result(instance)
|
||||||
|
instance = future
|
||||||
|
|
||||||
|
if not attributes_awaitable:
|
||||||
|
future = asyncio.Future()
|
||||||
|
future.set_result(attributes)
|
||||||
|
attributes = future
|
||||||
|
|
||||||
|
return __async_inject_attributes(instance, attributes)
|
||||||
|
|
||||||
|
__inject_attributes(instance, attributes)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
|
@ -172,3 +172,49 @@ class FactoryTests(AsyncTestCase):
|
||||||
self.assertIs(service2.client.resource2, RESOURCE2)
|
self.assertIs(service2.client.resource2, RESOURCE2)
|
||||||
|
|
||||||
self.assertIsNot(service1.client, service2.client)
|
self.assertIsNot(service1.client, service2.client)
|
||||||
|
|
||||||
|
def test_attributes_injection(self):
|
||||||
|
class ContainerWithAttributes(containers.DeclarativeContainer):
|
||||||
|
resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||||
|
resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
|
||||||
|
|
||||||
|
client = providers.Factory(
|
||||||
|
Client,
|
||||||
|
resource1,
|
||||||
|
resource2=None,
|
||||||
|
)
|
||||||
|
client.add_attributes(resource2=resource2)
|
||||||
|
|
||||||
|
service = providers.Factory(
|
||||||
|
Service,
|
||||||
|
client=None,
|
||||||
|
)
|
||||||
|
service.add_attributes(client=client)
|
||||||
|
|
||||||
|
container = ContainerWithAttributes()
|
||||||
|
|
||||||
|
client1 = self._run(container.client())
|
||||||
|
client2 = self._run(container.client())
|
||||||
|
|
||||||
|
self.assertIsInstance(client1, Client)
|
||||||
|
self.assertIs(client1.resource1, RESOURCE1)
|
||||||
|
self.assertIs(client1.resource2, RESOURCE2)
|
||||||
|
|
||||||
|
self.assertIsInstance(client2, Client)
|
||||||
|
self.assertIs(client2.resource1, RESOURCE1)
|
||||||
|
self.assertIs(client2.resource2, RESOURCE2)
|
||||||
|
|
||||||
|
service1 = self._run(container.service())
|
||||||
|
service2 = self._run(container.service())
|
||||||
|
|
||||||
|
self.assertIsInstance(service1, Service)
|
||||||
|
self.assertIsInstance(service1.client, Client)
|
||||||
|
self.assertIs(service1.client.resource1, RESOURCE1)
|
||||||
|
self.assertIs(service1.client.resource2, RESOURCE2)
|
||||||
|
|
||||||
|
self.assertIsInstance(service2, Service)
|
||||||
|
self.assertIsInstance(service2.client, Client)
|
||||||
|
self.assertIs(service2.client.resource1, RESOURCE1)
|
||||||
|
self.assertIs(service2.client.resource2, RESOURCE2)
|
||||||
|
|
||||||
|
self.assertIsNot(service1.client, service2.client)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user