diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 07b0b005ceb3f5..dc096b743c6334 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -485,6 +485,10 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a Python generator function. + .. versionchanged:: 3.10.6 + :term:`Duck-typed ` function-like objects now return + ``True`` if their code object has the :data:`CO_GENERATOR` flag. + .. versionchanged:: 3.13 Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a Python generator function. @@ -507,6 +511,10 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a :term:`coroutine function`. + .. versionchanged:: 3.10.6 + :term:`Duck-typed ` function-like objects now return + ``True`` if their code object has the :data:`CO_COROUTINE` flag. + .. versionchanged:: 3.12 Sync functions marked with :func:`markcoroutinefunction` now return ``True``. @@ -581,6 +589,10 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is an :term:`asynchronous generator` function. + .. versionchanged:: 3.10.6 + :term:`Duck-typed ` function-like objects now return + ``True`` if their code object has the :data:`CO_ASYNC_GENERATOR` flag. + .. versionchanged:: 3.13 Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a :term:`asynchronous generator` function. diff --git a/Lib/inspect.py b/Lib/inspect.py index 92664f46d351ac..837216e2eca130 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -298,6 +298,8 @@ def _has_code_flag(f, flag): f = functools._unwrap_partial(f) if not (isfunction(f) or _signature_is_functionlike(f)): return False + # If it's a pure Python function, or an object that is duck type + # of a Python function (Cython and Mock functions, for instance), then: return bool(f.__code__.co_flags & flag) def isgeneratorfunction(obj): @@ -2328,7 +2330,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True, is_duck_function = True else: # If it's not a pure Python function, and not a duck type - # of pure function: + # of pure function (Cython and Mock functions, for instance), then: raise TypeError('{!r} is not a Python function'.format(func)) s = getattr(func, "__text_signature__", None) @@ -2521,7 +2523,7 @@ def _signature_from_callable(obj, *, if isfunction(obj) or _signature_is_functionlike(obj): # If it's a pure Python function, or an object that is duck type - # of a Python function (Cython functions, for instance), then: + # of a Python function (Cython and Mock functions, for instance), then: return _signature_from_function(sigcls, obj, skip_bound_arg=skip_bound_arg, globals=globals, locals=locals, eval_str=eval_str,