From 559200a59ff638844ae1ab8700aac4192e111e38 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 18 Jul 2022 21:42:03 +0100 Subject: [PATCH 1/9] gh-82406: document duck-type nature of inspect.is*function --- Doc/library/inspect.rst | 10 ++++++++++ Lib/inspect.py | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 700cd9122cd34c..d7df79f68b7cd2 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -340,6 +340,9 @@ attributes: Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a Python generator function. + .. versionchanged:: 3.10.5 + Duck-type functions now return ``True`` if their code object has the CO_GENERATOR + flag .. function:: isgenerator(object) @@ -357,6 +360,10 @@ attributes: Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a :term:`coroutine function`. + .. versionchanged:: 3.10.5 + Duck-type functions now return ``True`` if their code object has the CO_COROUTINE + flag + .. function:: iscoroutine(object) @@ -402,6 +409,9 @@ attributes: Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a :term:`asynchronous generator` function. + .. versionchanged:: 3.10.5 + Duck-type functions now return ``True`` if their code object has the CO_ASYNC_GENERATOR + flag .. function:: isasyncgen(object) diff --git a/Lib/inspect.py b/Lib/inspect.py index cbc0632484b832..18d757bb6b2780 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -396,6 +396,8 @@ def _has_code_flag(f, flag): f = f.__func__ f = functools._unwrap_partial(f) if not (isfunction(f) or _signature_is_functionlike(f)): + # If it's not a pure Python function, and not a duck type + # of pure function (Cython and Mock functions, for instance), then: return False return bool(f.__code__.co_flags & flag) @@ -2334,7 +2336,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) @@ -2503,7 +2505,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) From 864d46ca20255d0b9a111a26d76aa0b24b78798b Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 18 Jul 2022 21:44:32 +0100 Subject: [PATCH 2/9] Update Doc/library/inspect.rst --- Doc/library/inspect.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index d7df79f68b7cd2..21228fa7352ff1 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -364,7 +364,6 @@ attributes: Duck-type functions now return ``True`` if their code object has the CO_COROUTINE flag - .. function:: iscoroutine(object) Return ``True`` if the object is a :term:`coroutine` created by an From 07d7a5fed4bc381a230c0b4accf995e51cd9c52b Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 18 Jul 2022 21:46:49 +0100 Subject: [PATCH 3/9] comment document the implicit else branch --- Lib/inspect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index 18d757bb6b2780..d023eb48d64b60 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -396,9 +396,9 @@ def _has_code_flag(f, flag): f = f.__func__ f = functools._unwrap_partial(f) if not (isfunction(f) or _signature_is_functionlike(f)): - # If it's not a pure Python function, and not a duck type - # of pure function (Cython and Mock functions, for instance), then: 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): From 3c3d198d90784479009c79219df69487fd2bb31f Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 21:00:48 +0000 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst diff --git a/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst b/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst new file mode 100644 index 00000000000000..cbfb413b3cd7a4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst @@ -0,0 +1,3 @@ +Document that :func:`inspect.iscoroutinefunction`, :func:`inspect.isgeneratorfunction`, +and :func:`inspect.isasyncgenfunction` now properly return ``True`` for +duck-typed function-like objects so that Cython functions can support them From b3b5301cff034c5dabe59c2f437f76cfcc51f46a Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Tue, 19 Jul 2022 10:33:32 +0100 Subject: [PATCH 5/9] the inspect.is*function duck type change missed the boat for 3.10.5 --- Doc/library/inspect.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 21228fa7352ff1..94e093df250fcb 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -340,7 +340,7 @@ attributes: Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a Python generator function. - .. versionchanged:: 3.10.5 + .. versionchanged:: 3.10.6 Duck-type functions now return ``True`` if their code object has the CO_GENERATOR flag @@ -360,7 +360,7 @@ attributes: Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a :term:`coroutine function`. - .. versionchanged:: 3.10.5 + .. versionchanged:: 3.10.6 Duck-type functions now return ``True`` if their code object has the CO_COROUTINE flag @@ -408,7 +408,7 @@ attributes: Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a :term:`asynchronous generator` function. - .. versionchanged:: 3.10.5 + .. versionchanged:: 3.10.6 Duck-type functions now return ``True`` if their code object has the CO_ASYNC_GENERATOR flag From 666abb7180f5b9d4c2589013fb2e98d2d1b4e894 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 2 Sep 2026 10:32:41 +0100 Subject: [PATCH 6/9] Apply batched suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartosz Sławecki --- Doc/library/inspect.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 1a18e7173bda6d..b2678dab78aad9 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -487,7 +487,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. versionchanged:: 3.10.6 Duck-type functions now return ``True`` if their code object has the CO_GENERATOR - fla + flag. .. versionchanged:: 3.13 Functions wrapped in :func:`functools.partialmethod` now return ``True`` @@ -513,7 +513,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. versionchanged:: 3.10.6 Duck-type functions now return ``True`` if their code object has the CO_COROUTINE - flag + flag. .. versionchanged:: 3.12 Sync functions marked with :func:`markcoroutinefunction` now return @@ -591,7 +591,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. versionchanged:: 3.10.6 Duck-type functions now return ``True`` if their code object has the CO_ASYNC_GENERATOR - flag + flag. .. versionchanged:: 3.13 Functions wrapped in :func:`functools.partialmethod` now return ``True`` From 04325faafd8bb347706502ce8ca6742d5b16a1a3 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 2 Sep 2026 10:37:43 +0100 Subject: [PATCH 7/9] fix lint --- .../Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst b/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst index cbfb413b3cd7a4..6d3fe472c2a0e5 100644 --- a/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst +++ b/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst @@ -1,3 +1,3 @@ -Document that :func:`inspect.iscoroutinefunction`, :func:`inspect.isgeneratorfunction`, -and :func:`inspect.isasyncgenfunction` now properly return ``True`` for +Document that :func:`inspect.iscoroutinefunction`, :func:`inspect.isgeneratorfunction`, +and :func:`inspect.isasyncgenfunction` now properly return ``True`` for duck-typed function-like objects so that Cython functions can support them From a651bc97883ebdea7b8fe5295227a4ef5541a00b Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 2 Sep 2026 10:37:46 +0100 Subject: [PATCH 8/9] Reword duck-type wording and finish the sentences Review feedback: use "function-like objects" and link the duck-typing glossary term rather than saying "duck-type functions". This matches the wording already used in the NEWS entry for gh-84753. --- Doc/library/inspect.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index b2678dab78aad9..39caee4f89016b 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -486,8 +486,8 @@ attributes (see :ref:`import-mod-attrs` for module attributes): wrapped function is a Python generator function. .. versionchanged:: 3.10.6 - Duck-type functions now return ``True`` if their code object has the CO_GENERATOR - flag. + :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`` @@ -512,8 +512,8 @@ attributes (see :ref:`import-mod-attrs` for module attributes): wrapped function is a :term:`coroutine function`. .. versionchanged:: 3.10.6 - Duck-type functions now return ``True`` if their code object has the CO_COROUTINE - flag. + :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 @@ -590,8 +590,8 @@ attributes (see :ref:`import-mod-attrs` for module attributes): wrapped function is an :term:`asynchronous generator` function. .. versionchanged:: 3.10.6 - Duck-type functions now return ``True`` if their code object has the CO_ASYNC_GENERATOR - flag. + :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`` From 2abecc310b6ca2b50b851160eb6e104a7193ed3b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 2 Sep 2026 17:03:51 +0200 Subject: [PATCH 9/9] Remove NEWS entry --- .../next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst diff --git a/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst b/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst deleted file mode 100644 index 6d3fe472c2a0e5..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-07-18-21-00-46.gh-issue-82406.pGgraY.rst +++ /dev/null @@ -1,3 +0,0 @@ -Document that :func:`inspect.iscoroutinefunction`, :func:`inspect.isgeneratorfunction`, -and :func:`inspect.isasyncgenfunction` now properly return ``True`` for -duck-typed function-like objects so that Cython functions can support them