diff --git a/requirements-tests.txt b/requirements-tests.txt index 1c0d6147c4ff..811c4f7747e1 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -23,7 +23,7 @@ stubdefaulter==0.1.0; python_version < "3.14" termcolor>=2.3 tomli==2.2.1 tomlkit==0.13.2 -typing_extensions>=4.13.0rc1 +typing_extensions>=4.14.0rc1 uv==0.7.4 # Utilities for typeshed infrastructure scripts. diff --git a/stdlib/@tests/stubtest_allowlists/py310.txt b/stdlib/@tests/stubtest_allowlists/py310.txt index cb686b140098..1cb422f3c9a5 100644 --- a/stdlib/@tests/stubtest_allowlists/py310.txt +++ b/stdlib/@tests/stubtest_allowlists/py310.txt @@ -77,6 +77,10 @@ importlib.metadata._meta.SimplePath.__truediv__ # Runtime definition of protoco builtins.float.__setformat__ # Internal method for CPython test suite typing._SpecialForm.__mro_entries__ # Exists at runtime, but missing from stubs +# Will always raise. Not included to avoid type checkers inferring that +# Sentinel instances are callable. +typing_extensions.Sentinel.__call__ + # ======= # <= 3.10 diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index 9dce720929db..f634f09ae0fc 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -169,10 +169,10 @@ typing(_extensions)?\.IO\.writelines .*\.ForwardRef\.__stringifier_dict__ # These protocols use ABC hackery at runtime. -io.Reader.__class_getitem__ -io.Reader.read -io.Writer.__class_getitem__ -io.Writer.write +(io|typing_extensions)\.Reader\.__class_getitem__ +(io|typing_extensions)\.Reader\.read +(io|typing_extensions)\.Writer\.__class_getitem__ +(io|typing_extensions)\.Writer\.write # ============================================================= diff --git a/stdlib/@tests/stubtest_allowlists/py39.txt b/stdlib/@tests/stubtest_allowlists/py39.txt index 496eb7231453..571e2c76c894 100644 --- a/stdlib/@tests/stubtest_allowlists/py39.txt +++ b/stdlib/@tests/stubtest_allowlists/py39.txt @@ -44,6 +44,10 @@ tempfile.SpooledTemporaryFile.writable tkinter.Tk.split # Exists at runtime, but missing from stubs +# Will always raise. Not included to avoid type checkers inferring that +# Sentinel instances are callable. +typing_extensions.Sentinel.__call__ + # ======= # <= 3.11 diff --git a/stdlib/typing_extensions.pyi b/stdlib/typing_extensions.pyi index 37f8e8ba6a4b..07cd57ebc18f 100644 --- a/stdlib/typing_extensions.pyi +++ b/stdlib/typing_extensions.pyi @@ -110,6 +110,8 @@ __all__ = [ "SupportsIndex", "SupportsInt", "SupportsRound", + "Reader", + "Writer", # One-off things. "Annotated", "assert_never", @@ -136,6 +138,7 @@ __all__ = [ "overload", "override", "Protocol", + "Sentinel", "reveal_type", "runtime", "runtime_checkable", @@ -199,6 +202,7 @@ _T = _TypeVar("_T") _F = _TypeVar("_F", bound=Callable[..., Any]) _TC = _TypeVar("_TC", bound=type[object]) _T_co = _TypeVar("_T_co", covariant=True) # Any type covariant containers. +_T_contra = _TypeVar("_T_contra", contravariant=True) class _Final: ... # This should be imported from typing but that breaks pytype @@ -446,6 +450,19 @@ else: @abc.abstractmethod def __round__(self, ndigits: int, /) -> _T_co: ... +if sys.version_info >= (3, 14): + from io import Reader as Reader, Writer as Writer +else: + @runtime_checkable + class Reader(Protocol[_T_co]): + @abc.abstractmethod + def read(self, size: int = ..., /) -> _T_co: ... + + @runtime_checkable + class Writer(Protocol[_T_contra]): + @abc.abstractmethod + def write(self, data: _T_contra, /) -> int: ... + if sys.version_info >= (3, 13): from types import CapsuleType as CapsuleType from typing import ( @@ -670,6 +687,16 @@ else: globals: Mapping[str, Any] | None = None, # value types depend on the key locals: Mapping[str, Any] | None = None, # value types depend on the key type_params: Iterable[TypeVar | ParamSpec | TypeVarTuple] | None = None, - format: Format = Format.VALUE, # noqa: Y011 + format: Format | None = None, _recursive_guard: Container[str] = ..., ) -> AnnotationForm: ... + +# PEP 661 +class Sentinel: + def __init__(self, name: str, repr: str | None = None) -> None: ... + if sys.version_info >= (3, 14): + def __or__(self, other: Any) -> UnionType: ... # other can be any type form legal for unions + def __ror__(self, other: Any) -> UnionType: ... # other can be any type form legal for unions + else: + def __or__(self, other: Any) -> _SpecialForm: ... # other can be any type form legal for unions + def __ror__(self, other: Any) -> _SpecialForm: ... # other can be any type form legal for unions