Sometimes it's useful to test if a function is a coroutine function, so implement a version of asyncio.iscoroutinefunction that works with asyncio.coroutine as well as compat_coroutine.coroutine (since both kinds of coroutine functions behave identically for our purposes). --- lib/portage/util/futures/_asyncio/__init__.py | 14 ++++++++++++++ lib/portage/util/futures/compat_coroutine.py | 12 ++++++++++++ 2 files changed, 26 insertions(+)
diff --git a/lib/portage/util/futures/_asyncio/__init__.py b/lib/portage/util/futures/_asyncio/__init__.py index faab98e47..2a637624d 100644 --- a/lib/portage/util/futures/_asyncio/__init__.py +++ b/lib/portage/util/futures/_asyncio/__init__.py @@ -36,6 +36,7 @@ except ImportError: import portage portage.proxy.lazyimport.lazyimport(globals(), 'portage.util.futures.unix_events:_PortageEventLoopPolicy', + 'portage.util.futures:compat_coroutine@_compat_coroutine', ) from portage.util._eventloop.asyncio_event_loop import AsyncioEventLoop as _AsyncioEventLoop from portage.util._eventloop.global_event_loop import ( @@ -152,6 +153,19 @@ def create_subprocess_exec(*args, **kwargs): return result +def iscoroutinefunction(func): + """ + Return True if func is a decorated coroutine function, + supporting both asyncio.coroutine and compat_coroutine since + their behavior is identical for all practical purposes. + """ + if _compat_coroutine._iscoroutinefunction(func): + return True + elif _real_asyncio is not None and _real_asyncio.iscoroutinefunction(func): + return True + return False + + class Task(Future): """ Schedule the execution of a coroutine: wrap it in a future. A task diff --git a/lib/portage/util/futures/compat_coroutine.py b/lib/portage/util/futures/compat_coroutine.py index 59fdc31b6..be305c1b5 100644 --- a/lib/portage/util/futures/compat_coroutine.py +++ b/lib/portage/util/futures/compat_coroutine.py @@ -8,6 +8,17 @@ portage.proxy.lazyimport.lazyimport(globals(), 'portage.util.futures:asyncio', ) +# A marker for iscoroutinefunction. +_is_coroutine = object() + + +def _iscoroutinefunction(func): + """ + Return True if func is a decorated coroutine function + created with the coroutine decorator for this module. + """ + return getattr(func, '_is_coroutine', None) is _is_coroutine + def coroutine(generator_func): """ @@ -34,6 +45,7 @@ def coroutine(generator_func): @functools.wraps(generator_func) def wrapped(*args, **kwargs): return _generator_future(generator_func, *args, **kwargs) + wrapped._is_coroutine = _is_coroutine return wrapped -- 2.16.4