summaryrefslogtreecommitdiffstats
path: root/Lib/inspect.py
diff options
context:
space:
mode:
authorCarlton Gibson <carlton@noumenal.es>2022-12-18 19:13:24 (GMT)
committerGitHub <noreply@github.com>2022-12-18 19:13:24 (GMT)
commit532aa4e4e019812d0388920768ede7c04232ebe1 (patch)
treebac6a6c3f467bc6a7d7ac1210fc5f9929cc2742a /Lib/inspect.py
parent1cf3d78c92eb07dc09d15cc2e773b0b1b9436825 (diff)
downloadcpython-532aa4e4e019812d0388920768ede7c04232ebe1.zip
cpython-532aa4e4e019812d0388920768ede7c04232ebe1.tar.gz
cpython-532aa4e4e019812d0388920768ede7c04232ebe1.tar.bz2
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()`.
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r--Lib/inspect.py26
1 files changed, 24 insertions, 2 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index e92c355..052f0bf 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -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.