Add async resources implementation

This commit is contained in:
Roman Mogylatov 2020-11-18 13:28:51 -05:00
parent c8178cecda
commit 53ce5648af
3 changed files with 2508 additions and 1525 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2699,7 +2699,11 @@ cdef class Resource(Provider):
if self.__shutdowner: if self.__shutdowner:
try: try:
self.__shutdowner(self.__resource) if inspect.iscoroutinefunction(self.__shutdowner):
loop = asyncio.get_event_loop()
loop.run_until_complete(self.__shutdowner(self.__resource))
else:
self.__shutdowner(self.__resource)
except StopIteration: except StopIteration:
pass pass
@ -2723,6 +2727,21 @@ cdef class Resource(Provider):
self.__kwargs_len, self.__kwargs_len,
) )
self.__shutdowner = initializer.shutdown self.__shutdowner = initializer.shutdown
elif self._is_async_resource_subclass(self.__initializer):
loop = asyncio.get_event_loop()
initializer = self.__initializer()
self.__resource = loop.run_until_complete(
__call(
initializer.init,
args,
self.__args,
self.__args_len,
kwargs,
self.__kwargs,
self.__kwargs_len,
),
)
self.__shutdowner = initializer.shutdown
elif inspect.isgeneratorfunction(self.__initializer): elif inspect.isgeneratorfunction(self.__initializer):
initializer = __call( initializer = __call(
self.__initializer, self.__initializer,
@ -2735,6 +2754,31 @@ cdef class Resource(Provider):
) )
self.__resource = next(initializer) self.__resource = next(initializer)
self.__shutdowner = initializer.send self.__shutdowner = initializer.send
elif inspect.iscoroutinefunction(self.__initializer):
loop = asyncio.get_event_loop()
initializer = __call(
self.__initializer,
args,
self.__args,
self.__args_len,
kwargs,
self.__kwargs,
self.__kwargs_len,
)
self.__resource = loop.run_until_complete(initializer)
elif inspect.isasyncgenfunction(self.__initializer):
loop = asyncio.get_event_loop()
initializer = __call(
self.__initializer,
args,
self.__args,
self.__args_len,
kwargs,
self.__kwargs,
self.__kwargs_len,
)
self.__resource = loop.run_until_complete(initializer.__anext__())
self.__shutdowner = initializer.__anext__
elif callable(self.__initializer): elif callable(self.__initializer):
self.__resource = __call( self.__resource = __call(
self.__initializer, self.__initializer,
@ -2756,10 +2800,19 @@ cdef class Resource(Provider):
if sys.version_info < (3, 5): if sys.version_info < (3, 5):
return False return False
if not isinstance(instance, CLASS_TYPES): if not isinstance(instance, CLASS_TYPES):
return return False
from . import resources from . import resources
return issubclass(instance, resources.Resource) return issubclass(instance, resources.Resource)
@staticmethod
def _is_async_resource_subclass(instance):
if sys.version_info < (3, 5):
return False
if not isinstance(instance, CLASS_TYPES):
return False
from . import resources
return issubclass(instance, resources.AsyncResource)
cdef class Container(Provider): cdef class Container(Provider):
"""Container provider provides an instance of declarative container. """Container provider provides an instance of declarative container.

View File

@ -29,3 +29,14 @@ class Resource(Generic[T], metaclass=ResourceMeta):
@abc.abstractmethod @abc.abstractmethod
def shutdown(self, resource: T) -> None: def shutdown(self, resource: T) -> None:
... ...
class AsyncResource(Generic[T], metaclass=ResourceMeta):
@abc.abstractmethod
async def init(self, *args, **kwargs) -> T:
...
@abc.abstractmethod
async def shutdown(self, resource: T) -> None:
...