mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-22 22:53:00 +03:00
Implement positional injections, add tests and make refactoring
This commit is contained in:
parent
af51779477
commit
53a5d07b3a
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -339,25 +339,33 @@ cdef inline tuple __separate_prefixed_kwargs(dict kwargs):
|
|||
|
||||
@cython.boundscheck(False)
|
||||
@cython.wraparound(False)
|
||||
cdef inline tuple __provide_positional_args(
|
||||
cdef inline object __provide_positional_args(
|
||||
tuple args,
|
||||
tuple inj_args,
|
||||
int inj_args_len,
|
||||
):
|
||||
cdef int index
|
||||
cdef list positional_args
|
||||
cdef list positional_args = []
|
||||
cdef list awaitables = []
|
||||
cdef PositionalInjection injection
|
||||
|
||||
if inj_args_len == 0:
|
||||
return args
|
||||
|
||||
positional_args = list()
|
||||
for index in range(inj_args_len):
|
||||
injection = <PositionalInjection>inj_args[index]
|
||||
positional_args.append(__get_value(injection))
|
||||
value = __get_value(injection)
|
||||
positional_args.append(value)
|
||||
|
||||
if __isawaitable(value):
|
||||
awaitables.append((index, value))
|
||||
|
||||
positional_args.extend(args)
|
||||
|
||||
return tuple(positional_args)
|
||||
if awaitables:
|
||||
return __awaitable_args_kwargs_future(positional_args, awaitables)
|
||||
|
||||
return positional_args
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
|
@ -403,24 +411,29 @@ cdef inline object __provide_keyword_args(
|
|||
awaitables.append((name, value))
|
||||
|
||||
if awaitables:
|
||||
future_result = asyncio.Future()
|
||||
|
||||
args_future = asyncio.Future()
|
||||
args_future.set_result((future_result, kwargs, awaitables))
|
||||
kwargs_ready = asyncio.gather(args_future, *[value for _, value in awaitables])
|
||||
kwargs_ready.add_done_callback(__async_prepare_kwargs_callback)
|
||||
asyncio.ensure_future(kwargs_ready)
|
||||
|
||||
return future_result
|
||||
return __awaitable_args_kwargs_future(kwargs, awaitables)
|
||||
|
||||
return kwargs
|
||||
|
||||
|
||||
cdef inline void __async_prepare_kwargs_callback(object future):
|
||||
(future_result, kwargs, awaitables), *awaited = future.result()
|
||||
for value, (name, _) in zip(awaited, awaitables):
|
||||
kwargs[name] = value
|
||||
future_result.set_result(kwargs)
|
||||
cdef inline object __awaitable_args_kwargs_future(object args, list awaitables):
|
||||
future_result = asyncio.Future()
|
||||
|
||||
args_future = asyncio.Future()
|
||||
args_future.set_result((future_result, args, awaitables))
|
||||
|
||||
args_ready = asyncio.gather(args_future, *[value for _, value in awaitables])
|
||||
args_ready.add_done_callback(__async_prepare_args_kwargs_callback)
|
||||
asyncio.ensure_future(args_ready)
|
||||
|
||||
return future_result
|
||||
|
||||
|
||||
cdef inline void __async_prepare_args_kwargs_callback(object future):
|
||||
(future_result, args, awaitables), *awaited = future.result()
|
||||
for value, (key, _) in zip(awaited, awaitables):
|
||||
args[key] = value
|
||||
future_result.set_result(args)
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
|
@ -458,12 +471,27 @@ cdef inline object __call(
|
|||
injection_kwargs_len,
|
||||
)
|
||||
|
||||
if __isawaitable(kwargs):
|
||||
args_awaitable = __isawaitable(args)
|
||||
kwargs_awaitable = __isawaitable(kwargs)
|
||||
|
||||
if args_awaitable or kwargs_awaitable:
|
||||
if not args_awaitable:
|
||||
future = asyncio.Future()
|
||||
future.set_result(args)
|
||||
args = future
|
||||
|
||||
if not kwargs_awaitable:
|
||||
future = asyncio.Future()
|
||||
future.set_result(kwargs)
|
||||
kwargs = future
|
||||
|
||||
|
||||
future_result = asyncio.Future()
|
||||
|
||||
args_future = asyncio.Future()
|
||||
args_future.set_result((future_result, call, args))
|
||||
args_kwargs_ready = asyncio.gather(args_future, kwargs)
|
||||
future = asyncio.Future()
|
||||
future.set_result((future_result, call))
|
||||
|
||||
args_kwargs_ready = asyncio.gather(future, args, kwargs)
|
||||
args_kwargs_ready.add_done_callback(__async_call_callback)
|
||||
asyncio.ensure_future(args_kwargs_ready)
|
||||
|
||||
|
@ -473,7 +501,7 @@ cdef inline object __call(
|
|||
|
||||
|
||||
cdef inline void __async_call_callback(object future):
|
||||
(future_result, call, args), kwargs = future.result()
|
||||
(future_result, call), args, kwargs = future.result()
|
||||
result = call(*args, **kwargs)
|
||||
future_result.set_result(result)
|
||||
|
||||
|
|
|
@ -56,8 +56,96 @@ class Container(containers.DeclarativeContainer):
|
|||
|
||||
class FactoryTests(AsyncTestCase):
|
||||
|
||||
def test_direct_injection(self):
|
||||
container = Container()
|
||||
def test_args_injection(self):
|
||||
class ContainerWithArgs(containers.DeclarativeContainer):
|
||||
resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
|
||||
|
||||
client = providers.Factory(
|
||||
Client,
|
||||
resource1,
|
||||
resource2,
|
||||
)
|
||||
|
||||
service = providers.Factory(
|
||||
Service,
|
||||
client,
|
||||
)
|
||||
|
||||
container = ContainerWithArgs()
|
||||
|
||||
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)
|
||||
|
||||
def test_kwargs_injection(self):
|
||||
container = Container()
|
||||
|
||||
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)
|
||||
|
||||
def test_args_kwargs_injection(self):
|
||||
class ContainerWithArgsAndKwArgs(containers.DeclarativeContainer):
|
||||
resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
|
||||
resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
|
||||
|
||||
client = providers.Factory(
|
||||
Client,
|
||||
resource1,
|
||||
resource2=resource2,
|
||||
)
|
||||
|
||||
service = providers.Factory(
|
||||
Service,
|
||||
client=client,
|
||||
)
|
||||
|
||||
container = ContainerWithArgsAndKwArgs()
|
||||
|
||||
client1 = self._run(container.client())
|
||||
client2 = self._run(container.client())
|
||||
|
@ -70,9 +158,6 @@ class FactoryTests(AsyncTestCase):
|
|||
self.assertIs(client2.resource1, RESOURCE1)
|
||||
self.assertIs(client2.resource2, RESOURCE2)
|
||||
|
||||
def test_children_injection(self):
|
||||
container = Container()
|
||||
|
||||
service1 = self._run(container.service())
|
||||
service2 = self._run(container.service())
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user