diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index f56e9d6db..a2fb49e59 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -129,9 +129,6 @@ importlib.machinery.__all__ importlib.machinery.AppleFrameworkLoader importlib.util.__all__ importlib.util.Loader -io.__all__ -io.Reader -io.Writer ipaddress._IPAddressBase.version logging.handlers.SysLogHandler.__init__ marshal.dump @@ -299,6 +296,13 @@ typing(_extensions)?\.IO\.writelines .*\.ForwardRef\.__owner__ .*\.ForwardRef\.__stringifier_dict__ +# These protocols use ABC hackery at runtime. +io.Reader.__class_getitem__ +io.Reader.read +io.Writer.__class_getitem__ +io.Writer.write + + # ============================================================= # Allowlist entries that cannot or should not be fixed; >= 3.13 # ============================================================= diff --git a/stdlib/io.pyi b/stdlib/io.pyi index 5c26cb245..1313df183 100644 --- a/stdlib/io.pyi +++ b/stdlib/io.pyi @@ -20,7 +20,7 @@ from _io import ( open as open, open_code as open_code, ) -from typing import Final +from typing import Final, Protocol, TypeVar __all__ = [ "BlockingIOError", @@ -44,11 +44,17 @@ __all__ = [ "SEEK_END", ] +if sys.version_info >= (3, 14): + __all__ += ["Reader", "Writer"] + if sys.version_info >= (3, 11): from _io import text_encoding as text_encoding __all__ += ["DEFAULT_BUFFER_SIZE", "IncrementalNewlineDecoder", "text_encoding"] +_T_co = TypeVar("_T_co", covariant=True) +_T_contra = TypeVar("_T_contra", contravariant=True) + SEEK_SET: Final = 0 SEEK_CUR: Final = 1 SEEK_END: Final = 2 @@ -58,3 +64,10 @@ class IOBase(_IOBase, metaclass=abc.ABCMeta): ... class RawIOBase(_RawIOBase, IOBase): ... class BufferedIOBase(_BufferedIOBase, IOBase): ... class TextIOBase(_TextIOBase, IOBase): ... + +if sys.version_info >= (3, 14): + class Reader(Protocol[_T_co]): + def read(self, size: int = ..., /) -> _T_co: ... + + class Writer(Protocol[_T_contra]): + def write(self, data: _T_contra, /) -> int: ...