From 4370c3adaa32af6198d52c2dd4e2de7d1474fc63 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 22 Jun 2026 11:04:45 -0700 Subject: [PATCH 1/2] asyncio, inspect: use static types in TypeIs The set-theoretically correct way to write these TypeIs functions is with a type that includes all instances of the type they are narrowing to; for example "Awaitable[Any]" means "some unknown set of awaitables"; "Awaitable[object]" means "all awaitables, regardless of what they await to". We can't spell this type for cases involving invariant type parameters or callable parameter sets, so leave those alone for now. This may cause new type checker diagnostics because it will lead type checkers to often infer more precise types. Those errors are at least in theory correct, but let's see how big the fallout is. --- stdlib/asyncio/coroutines.pyi | 4 ++-- stdlib/inspect.pyi | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stdlib/asyncio/coroutines.pyi b/stdlib/asyncio/coroutines.pyi index 62d0bc4db8b9..4ac8fcbdd060 100644 --- a/stdlib/asyncio/coroutines.pyi +++ b/stdlib/asyncio/coroutines.pyi @@ -1,7 +1,7 @@ import sys from collections.abc import Awaitable, Callable, Coroutine from typing import Any, ParamSpec, TypeGuard, TypeVar, overload -from typing_extensions import TypeIs, deprecated +from typing_extensions import Never, TypeIs, deprecated # Keep asyncio.__all__ updated with any changes to __all__ here if sys.version_info >= (3, 11): @@ -17,7 +17,7 @@ if sys.version_info < (3, 11): @deprecated("Deprecated since Python 3.8; removed in Python 3.11. Use `async def` instead.") def coroutine(func: _FunctionT) -> _FunctionT: ... -def iscoroutine(obj: object) -> TypeIs[Coroutine[Any, Any, Any]]: ... +def iscoroutine(obj: object) -> TypeIs[Coroutine[object, Never, object]]: ... if sys.version_info >= (3, 11): @overload diff --git a/stdlib/inspect.pyi b/stdlib/inspect.pyi index 5a7b74b2d1ba..d676be4e8604 100644 --- a/stdlib/inspect.pyi +++ b/stdlib/inspect.pyi @@ -39,7 +39,7 @@ from typing import ( overload, type_check_only, ) -from typing_extensions import Self, TypeIs, deprecated, disjoint_base +from typing_extensions import Never, Self, TypeIs, deprecated, disjoint_base if sys.version_info >= (3, 14): from annotationlib import Format @@ -218,7 +218,7 @@ if sys.version_info >= (3, 11): def getmodulename(path: StrPath) -> str | None: ... def ismodule(object: object) -> TypeIs[ModuleType]: ... -def isclass(object: object) -> TypeIs[type[Any]]: ... +def isclass(object: object) -> TypeIs[type[object]]: ... def ismethod(object: object) -> TypeIs[MethodType]: ... if sys.version_info >= (3, 14): @@ -244,9 +244,9 @@ def iscoroutinefunction(obj: Callable[_P, Awaitable[_T]]) -> TypeGuard[Callable[ def iscoroutinefunction(obj: Callable[_P, object]) -> TypeGuard[Callable[_P, CoroutineType[Any, Any, Any]]]: ... @overload def iscoroutinefunction(obj: object) -> TypeGuard[Callable[..., CoroutineType[Any, Any, Any]]]: ... -def isgenerator(object: object) -> TypeIs[GeneratorType[Any, Any, Any]]: ... -def iscoroutine(object: object) -> TypeIs[CoroutineType[Any, Any, Any]]: ... -def isawaitable(object: object) -> TypeIs[Awaitable[Any]]: ... +def isgenerator(object: object) -> TypeIs[GeneratorType[object, Never, object]]: ... +def iscoroutine(object: object) -> TypeIs[CoroutineType[object, Never, object]]: ... +def isawaitable(object: object) -> TypeIs[Awaitable[object]]: ... @overload def isasyncgenfunction(obj: Callable[..., AsyncGenerator[Any, Any]]) -> bool: ... @overload @@ -261,7 +261,7 @@ class _SupportsSet(Protocol[_T_contra, _V_contra]): class _SupportsDelete(Protocol[_T_contra]): def __delete__(self, instance: _T_contra, /) -> None: ... -def isasyncgen(object: object) -> TypeIs[AsyncGeneratorType[Any, Any]]: ... +def isasyncgen(object: object) -> TypeIs[AsyncGeneratorType[object, Never]]: ... def istraceback(object: object) -> TypeIs[TracebackType]: ... def isframe(object: object) -> TypeIs[FrameType]: ... def iscode(object: object) -> TypeIs[CodeType]: ... @@ -286,7 +286,7 @@ def ismethoddescriptor(object: object) -> TypeIs[MethodDescriptorType]: ... def ismemberdescriptor(object: object) -> TypeIs[MemberDescriptorType]: ... def isabstract(object: object) -> bool: ... def isgetsetdescriptor(object: object) -> TypeIs[GetSetDescriptorType]: ... -def isdatadescriptor(object: object) -> TypeIs[_SupportsSet[Any, Any] | _SupportsDelete[Any]]: ... +def isdatadescriptor(object: object) -> TypeIs[_SupportsSet[Never, Never] | _SupportsDelete[Never]]: ... # # Retrieving source code From b1e8a6608d933dc89afe2c3987d4f6dcd30a88da Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 23 Jun 2026 21:02:53 -0700 Subject: [PATCH 2/2] undo some --- stdlib/asyncio/coroutines.pyi | 4 ++-- stdlib/inspect.pyi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/asyncio/coroutines.pyi b/stdlib/asyncio/coroutines.pyi index fff98c624c14..7599c692949b 100644 --- a/stdlib/asyncio/coroutines.pyi +++ b/stdlib/asyncio/coroutines.pyi @@ -1,7 +1,7 @@ import sys from collections.abc import Awaitable, Callable, Coroutine from typing import Any, ParamSpec, TypeGuard, TypeVar, overload -from typing_extensions import Never, TypeIs, deprecated +from typing_extensions import TypeIs, deprecated # Keep asyncio.__all__ updated with any changes to __all__ here if sys.version_info >= (3, 11): @@ -17,7 +17,7 @@ if sys.version_info < (3, 11): @deprecated("Deprecated since Python 3.8; removed in Python 3.11. Use `async def` instead.") def coroutine(func: _FunctionT) -> _FunctionT: ... -def iscoroutine(obj: object) -> TypeIs[Coroutine[object, Never, object]]: ... +def iscoroutine(obj: object) -> TypeIs[Coroutine[Any, Any, Any]]: ... if sys.version_info >= (3, 11): @overload diff --git a/stdlib/inspect.pyi b/stdlib/inspect.pyi index 05a18e90aa97..c3110ce28d8e 100644 --- a/stdlib/inspect.pyi +++ b/stdlib/inspect.pyi @@ -246,8 +246,8 @@ def iscoroutinefunction(obj: Callable[_P, object]) -> TypeGuard[Callable[_P, Cor def iscoroutinefunction(obj: object) -> TypeGuard[Callable[..., CoroutineType[Any, Any, Any]]]: ... def isgenerator(object: object) -> TypeIs[GeneratorType[object, Never, object]]: ... -def iscoroutine(object: object) -> TypeIs[CoroutineType[object, Never, object]]: ... -def isawaitable(object: object) -> TypeIs[Awaitable[object]]: ... +def iscoroutine(object: object) -> TypeIs[CoroutineType[Any, Any, Any]]: ... +def isawaitable(object: object) -> TypeIs[Awaitable[Any]]: ... @overload def isasyncgenfunction(obj: Callable[..., AsyncGenerator[Any, Any]]) -> bool: ...