Skip to content

Commit 559200a

Browse files
committed
gh-82406: document duck-type nature of inspect.is*function
1 parent 73eab9f commit 559200a

2 files changed

Lines changed: 14 additions & 2 deletions

File tree

Doc/library/inspect.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ attributes:
340340
Functions wrapped in :func:`functools.partial` now return ``True`` if the
341341
wrapped function is a Python generator function.
342342

343+
.. versionchanged:: 3.10.5
344+
Duck-type functions now return ``True`` if their code object has the CO_GENERATOR
345+
flag
343346

344347
.. function:: isgenerator(object)
345348

@@ -357,6 +360,10 @@ attributes:
357360
Functions wrapped in :func:`functools.partial` now return ``True`` if the
358361
wrapped function is a :term:`coroutine function`.
359362

363+
.. versionchanged:: 3.10.5
364+
Duck-type functions now return ``True`` if their code object has the CO_COROUTINE
365+
flag
366+
360367

361368
.. function:: iscoroutine(object)
362369

@@ -402,6 +409,9 @@ attributes:
402409
Functions wrapped in :func:`functools.partial` now return ``True`` if the
403410
wrapped function is a :term:`asynchronous generator` function.
404411

412+
.. versionchanged:: 3.10.5
413+
Duck-type functions now return ``True`` if their code object has the CO_ASYNC_GENERATOR
414+
flag
405415

406416
.. function:: isasyncgen(object)
407417

Lib/inspect.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ def _has_code_flag(f, flag):
396396
f = f.__func__
397397
f = functools._unwrap_partial(f)
398398
if not (isfunction(f) or _signature_is_functionlike(f)):
399+
# If it's not a pure Python function, and not a duck type
400+
# of pure function (Cython and Mock functions, for instance), then:
399401
return False
400402
return bool(f.__code__.co_flags & flag)
401403

@@ -2334,7 +2336,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
23342336
is_duck_function = True
23352337
else:
23362338
# If it's not a pure Python function, and not a duck type
2337-
# of pure function:
2339+
# of pure function (Cython and Mock functions, for instance), then:
23382340
raise TypeError('{!r} is not a Python function'.format(func))
23392341

23402342
s = getattr(func, "__text_signature__", None)
@@ -2503,7 +2505,7 @@ def _signature_from_callable(obj, *,
25032505

25042506
if isfunction(obj) or _signature_is_functionlike(obj):
25052507
# If it's a pure Python function, or an object that is duck type
2506-
# of a Python function (Cython functions, for instance), then:
2508+
# of a Python function (Cython and Mock functions, for instance), then:
25072509
return _signature_from_function(sigcls, obj,
25082510
skip_bound_arg=skip_bound_arg,
25092511
globals=globals, locals=locals, eval_str=eval_str)

0 commit comments

Comments
 (0)