gh-94912: Added marker for non-standard coroutine function detection (#99247)

This introduces a new decorator `@inspect.markcoroutinefunction`,
which, applied to a sync function, makes it appear async to
`inspect.iscoroutinefunction()`.
This commit is contained in:
Carlton Gibson 2022-12-18 20:13:24 +01:00 committed by GitHub
parent 1cf3d78c92
commit 532aa4e4e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 4 deletions

View file

@ -125,6 +125,7 @@ __all__ = [
"ismodule",
"isroutine",
"istraceback",
"markcoroutinefunction",
"signature",
"stack",
"trace",
@ -391,12 +392,33 @@ def isgeneratorfunction(obj):
See help(isfunction) for a list of attributes."""
return _has_code_flag(obj, CO_GENERATOR)
# A marker for markcoroutinefunction and iscoroutinefunction.
_is_coroutine_marker = object()
def _has_coroutine_mark(f):
while ismethod(f):
f = f.__func__
f = functools._unwrap_partial(f)
if not (isfunction(f) or _signature_is_functionlike(f)):
return False
return getattr(f, "_is_coroutine_marker", None) is _is_coroutine_marker
def markcoroutinefunction(func):
"""
Decorator to ensure callable is recognised as a coroutine function.
"""
if hasattr(func, '__func__'):
func = func.__func__
func._is_coroutine_marker = _is_coroutine_marker
return func
def iscoroutinefunction(obj):
"""Return true if the object is a coroutine function.
Coroutine functions are defined with "async def" syntax.
Coroutine functions are normally defined with "async def" syntax, but may
be marked via markcoroutinefunction.
"""
return _has_code_flag(obj, CO_COROUTINE)
return _has_code_flag(obj, CO_COROUTINE) or _has_coroutine_mark(obj)
def isasyncgenfunction(obj):
"""Return true if the object is an asynchronous generator function.