Skip to content
12 changes: 12 additions & 0 deletions Doc/library/inspect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <duck-typing>` 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.
Expand All @@ -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 <duck-typing>` 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``.
Expand Down Expand Up @@ -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 <duck-typing>` 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.
Expand Down
6 changes: 4 additions & 2 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -2338,7 +2340,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)
Expand Down Expand Up @@ -2531,7 +2533,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,
Expand Down
Loading