mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 18:07:44 +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