mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-23 15:10:49 +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.boundscheck(False)
|
||||||
@cython.wraparound(False)
|
@cython.wraparound(False)
|
||||||
cdef inline tuple __provide_positional_args(
|
cdef inline object __provide_positional_args(
|
||||||
tuple args,
|
tuple args,
|
||||||
tuple inj_args,
|
tuple inj_args,
|
||||||
int inj_args_len,
|
int inj_args_len,
|
||||||
):
|
):
|
||||||
cdef int index
|
cdef int index
|
||||||
cdef list positional_args
|
cdef list positional_args = []
|
||||||
|
cdef list awaitables = []
|
||||||
cdef PositionalInjection injection
|
cdef PositionalInjection injection
|
||||||
|
|
||||||
if inj_args_len == 0:
|
if inj_args_len == 0:
|
||||||
return args
|
return args
|
||||||
|
|
||||||
positional_args = list()
|
|
||||||
for index in range(inj_args_len):
|
for index in range(inj_args_len):
|
||||||
injection = <PositionalInjection>inj_args[index]
|
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)
|
positional_args.extend(args)
|
||||||
|
|
||||||
return tuple(positional_args)
|
if awaitables:
|
||||||
|
return __awaitable_args_kwargs_future(positional_args, awaitables)
|
||||||
|
|
||||||
|
return positional_args
|
||||||
|
|
||||||
|
|
||||||
@cython.boundscheck(False)
|
@cython.boundscheck(False)
|
||||||
|
@ -403,24 +411,29 @@ cdef inline object __provide_keyword_args(
|
||||||
awaitables.append((name, value))
|
awaitables.append((name, value))
|
||||||
|
|
||||||
if awaitables:
|
if awaitables:
|
||||||
future_result = asyncio.Future()
|
return __awaitable_args_kwargs_future(kwargs, awaitables)
|
||||||
|
|
||||||
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 kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
cdef inline void __async_prepare_kwargs_callback(object future):
|
cdef inline object __awaitable_args_kwargs_future(object args, list awaitables):
|
||||||
(future_result, kwargs, awaitables), *awaited = future.result()
|
future_result = asyncio.Future()
|
||||||
for value, (name, _) in zip(awaited, awaitables):
|
|
||||||
kwargs[name] = value
|
args_future = asyncio.Future()
|
||||||
future_result.set_result(kwargs)
|
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)
|
@cython.boundscheck(False)
|
||||||
|
@ -458,12 +471,27 @@ cdef inline object __call(
|
||||||
injection_kwargs_len,
|
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()
|
future_result = asyncio.Future()
|
||||||
|
|
||||||
args_future = asyncio.Future()
|
future = asyncio.Future()
|
||||||
args_future.set_result((future_result, call, args))
|
future.set_result((future_result, call))
|
||||||
args_kwargs_ready = asyncio.gather(args_future, kwargs)
|
|
||||||
|
args_kwargs_ready = asyncio.gather(future, args, kwargs)
|
||||||
args_kwargs_ready.add_done_callback(__async_call_callback)
|
args_kwargs_ready.add_done_callback(__async_call_callback)
|
||||||
asyncio.ensure_future(args_kwargs_ready)
|
asyncio.ensure_future(args_kwargs_ready)
|
||||||
|
|
||||||
|
@ -473,7 +501,7 @@ cdef inline object __call(
|
||||||
|
|
||||||
|
|
||||||
cdef inline void __async_call_callback(object future):
|
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)
|
result = call(*args, **kwargs)
|
||||||
future_result.set_result(result)
|
future_result.set_result(result)
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,96 @@ class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
class FactoryTests(AsyncTestCase):
|
class FactoryTests(AsyncTestCase):
|
||||||
|
|
||||||
def test_direct_injection(self):
|
def test_args_injection(self):
|
||||||
container = Container()
|
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())
|
client1 = self._run(container.client())
|
||||||
client2 = self._run(container.client())
|
client2 = self._run(container.client())
|
||||||
|
@ -70,9 +158,6 @@ class FactoryTests(AsyncTestCase):
|
||||||
self.assertIs(client2.resource1, RESOURCE1)
|
self.assertIs(client2.resource1, RESOURCE1)
|
||||||
self.assertIs(client2.resource2, RESOURCE2)
|
self.assertIs(client2.resource2, RESOURCE2)
|
||||||
|
|
||||||
def test_children_injection(self):
|
|
||||||
container = Container()
|
|
||||||
|
|
||||||
service1 = self._run(container.service())
|
service1 = self._run(container.service())
|
||||||
service2 = self._run(container.service())
|
service2 = self._run(container.service())
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user