Title: `inspect.is*function()` overloads do not match the runtime behavior · Issue #15293 · python/typeshed · GitHub
Open Graph Title: `inspect.is*function()` overloads do not match the runtime behavior · Issue #15293 · python/typeshed
X Title: `inspect.is*function()` overloads do not match the runtime behavior · Issue #15293 · python/typeshed
Description: TypeGuard-based overloads for inspect.is*function() were added in #8057, but they are somewhat controversial. First, the first overload defines the return type via collections.abc.
Open Graph Description: TypeGuard-based overloads for inspect.is*function() were added in #8057, but they are somewhat controversial. First, the first overload defines the return type via collections.abc.
X Description: TypeGuard-based overloads for inspect.is*function() were added in #8057, but they are somewhat controversial. First, the first overload defines the return type via collections.abc.<Object>, w...
Opengraph URL: https://github.com/python/typeshed/issues/15293
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"`inspect.is*function()` overloads do not match the runtime behavior","articleBody":"[`TypeGuard`](https://docs.python.org/3/library/typing.html#typing.TypeGuard)-based overloads for `inspect.is*function()` were added in #8057, but they are somewhat controversial.\n\nFirst, the first overload defines the return type via `collections.abc.\u003cObject\u003e`, while the rest define it via `types.\u003cObject\u003eType`. As a result, type checkers infer the narrower type when the known return type differs from `collections.abc.\u003cObject\u003e`:\n\n```python\nfrom collections.abc import Coroutine\nfrom inspect import iscoroutinefunction\nfrom types import CoroutineType\nfrom typing import reveal_type\n\ndef native_coroutine_factory() -\u003e CoroutineType[None, None, None]: ...\ndef coroutine_factory() -\u003e Coroutine[None, None, None]: ...\ndef object_factory() -\u003e object: ...\n\nif iscoroutinefunction(native_coroutine_factory):\n reveal_type(native_coroutine_factory)\n # () -\u003e CoroutineType[None, None, None]\n\nif iscoroutinefunction(coroutine_factory):\n reveal_type(coroutine_factory)\n # () -\u003e Coroutine[None, None, None]\n\nif iscoroutinefunction(object_factory):\n reveal_type(object_factory)\n # () -\u003e CoroutineType[Any, Any, Any]\n```\n\nSecond, `inspect.is*function()` also returns `True` for functions that return a non-native object (for example, if the function was compiled via Cython), which means that the return type may not be `types.\u003cObject\u003eType`:\n\n```python\n#!/usr/bin/env python3\n\nimport inspect\n\n\ndef generator_function():\n yield\n\n\nasync def coroutine_function():\n pass\n\n\nasync def async_generator_function():\n yield\n\n\ndef main():\n # `True` on both CPython and Cython:\n print(inspect.isgeneratorfunction(generator_function))\n print(inspect.iscoroutinefunction(coroutine_function))\n print(inspect.isasyncgenfunction(async_generator_function))\n\n # `True` on CPython, `False` on Cython:\n print(inspect.isgenerator(generator_function()))\n print(inspect.iscoroutine(coro := coroutine_function()))\n print(inspect.isasyncgen(async_generator_function()))\n\n coro.close() # to avoid `RuntimeWarning`\n\nif __name__ == \"__main__\":\n main()\n```\n\nThird, I am also concerned about [the Python core developer's statement](https://github.com/python/cpython/issues/143908#issuecomment-3761121758) that [`iscoroutinefunction()`](https://docs.python.org/3/library/inspect.html#inspect.iscoroutinefunction) is basically defined for callable objects that return awaitable objects. Does this mean that we should use [`Awaitable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Awaitable) as the return type instead of [`Coroutine`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Coroutine) for [`inspect.iscoroutinefunction()`](https://docs.python.org/3/library/inspect.html#inspect.iscoroutinefunction) (since if users follow that definition, [`inspect.markcoroutinefunction()`](https://docs.python.org/3/library/inspect.html#inspect.markcoroutinefunction) will be applied just as broadly, even though this somewhat contradicts the documentation)?","author":{"url":"https://github.com/x42005e1f","@type":"Person","name":"x42005e1f"},"datePublished":"2026-01-16T19:07:29.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/15293/typeshed/issues/15293"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:8c0a7a68-e4c5-9b6f-1a73-9910241b942c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 9CA4:83A89:10FC2D0:1705B72:6A62DB56 |
| html-safe-nonce | 077208c81faf30ccc14e238976f5123f1d953ff2abb95cc725a7747e5a0bd62e |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5Q0E0OjgzQTg5OjEwRkMyRDA6MTcwNUI3Mjo2QTYyREI1NiIsInZpc2l0b3JfaWQiOiI4ODY2MDE3MTc0NjMwODgyMTM0IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | f797340e2f940bf0715d5d14bed2ba85c517f2249c790a32e727c20a7dfe15c3 |
| hovercard-subject-tag | issue:3823257133 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/typeshed/15293/issue_layout |
| twitter:image | https://opengraph.githubassets.com/04306458c6aa0882222da5ff9b8bebcc122133a3b396d5d8fd824327ec993a15/python/typeshed/issues/15293 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/04306458c6aa0882222da5ff9b8bebcc122133a3b396d5d8fd824327ec993a15/python/typeshed/issues/15293 |
| og:image:alt | TypeGuard-based overloads for inspect.is*function() were added in #8057, but they are somewhat controversial. First, the first overload defines the return type via collections.abc. |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | x42005e1f |
| hostname | github.com |
| expected-hostname | github.com |
| None | df33b1b61ee7b9a0af988199bfc3503c9c1acafb1f1d40e1f140ea7c84f890dd |
| turbo-cache-control | no-preview |
| go-import | github.com/python/typeshed git https://github.com/python/typeshed.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 31696383 |
| octolytics-dimension-repository_nwo | python/typeshed |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 31696383 |
| octolytics-dimension-repository_network_root_nwo | python/typeshed |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | d41cd1bdb290013455c0ac430fa755621733f5eb |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width