From b43124c3c841552561129a0cfa9a9c101df20cb4 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 21 Oct 2026 10:22:25 +0200 Subject: [PATCH 1/7] Remove IOBase.read and write --- stdlib/_io.pyi | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/_io.pyi b/stdlib/_io.pyi index 5e216123be98..8698a47f5e47 100644 --- a/stdlib/_io.pyi +++ b/stdlib/_io.pyi @@ -36,14 +36,12 @@ if sys.version_info >= (3, 12): def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... - read: Callable[..., Any] def readlines(self, hint: int = -1, /) -> list[bytes]: ... def seek(self, offset: int, whence: int = 0, /) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def truncate(self, size: int | None = None, /) -> int: ... def writable(self) -> bool: ... - write: Callable[..., Any] def writelines(self, lines: Iterable[ReadableBuffer], /) -> None: ... def readline(self, size: int | None = -1, /) -> bytes: ... def __del__(self) -> None: ... From 70c75aacf16aae008b6bf039349456f952e159ae Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 21 Oct 2026 11:07:00 +0200 Subject: [PATCH 2/7] Add abstract methods --- stdlib/_io.pyi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stdlib/_io.pyi b/stdlib/_io.pyi index 8698a47f5e47..264739cbd9d2 100644 --- a/stdlib/_io.pyi +++ b/stdlib/_io.pyi @@ -2,6 +2,7 @@ import builtins import codecs import sys from _typeshed import FileDescriptorOrPath, MaybeNone, ReadableBuffer, WriteableBuffer +from abc import abstractmethod from collections.abc import Callable, Iterable, Iterator from io import BufferedIOBase, RawIOBase, TextIOBase, UnsupportedOperation as UnsupportedOperation from os import _Opener @@ -36,12 +37,16 @@ if sys.version_info >= (3, 12): def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... + @abstractmethod + def read(self) -> Any: ... # the arguments and return type depend on the sub-class def readlines(self, hint: int = -1, /) -> list[bytes]: ... def seek(self, offset: int, whence: int = 0, /) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def truncate(self, size: int | None = None, /) -> int: ... def writable(self) -> bool: ... + @abstractmethod + def write(self, s: Any, /) -> Any: ... # the exact arguments and return type depend on the sub-class def writelines(self, lines: Iterable[ReadableBuffer], /) -> None: ... def readline(self, size: int | None = -1, /) -> bytes: ... def __del__(self) -> None: ... From 415dc995e59218c525cc40a4a8567027ff8b6ccf Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 21 Oct 2026 11:10:24 +0200 Subject: [PATCH 3/7] Make changes to both branches --- stdlib/_io.pyi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/_io.pyi b/stdlib/_io.pyi index 264739cbd9d2..b4aa3340c672 100644 --- a/stdlib/_io.pyi +++ b/stdlib/_io.pyi @@ -67,14 +67,16 @@ else: def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... - read: Callable[..., Any] + @abstractmethod + def read(self) -> Any: ... # the arguments and return type depend on the sub-class def readlines(self, hint: int = -1, /) -> list[bytes]: ... def seek(self, offset: int, whence: int = 0, /) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def truncate(self, size: int | None = None, /) -> int: ... def writable(self) -> bool: ... - write: Callable[..., Any] + @abstractmethod + def write(self, s: Any, /) -> Any: ... # the exact arguments and return type depend on the sub-class def writelines(self, lines: Iterable[ReadableBuffer], /) -> None: ... def readline(self, size: int | None = -1, /) -> bytes: ... def __del__(self) -> None: ... From 6c9246b56173e5b5b4a3b680b97792ecadef5191 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 21 Oct 2026 11:11:42 +0200 Subject: [PATCH 4/7] Add allowlist entries --- stdlib/@tests/stubtest_allowlists/common.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stdlib/@tests/stubtest_allowlists/common.txt b/stdlib/@tests/stubtest_allowlists/common.txt index a02939590f22..699fe63c3b4b 100644 --- a/stdlib/@tests/stubtest_allowlists/common.txt +++ b/stdlib/@tests/stubtest_allowlists/common.txt @@ -291,6 +291,10 @@ importlib.metadata._meta.SimplePath.joinpath # Runtime definition of protocol i inspect.Parameter.__init__ inspect.Signature.__init__ +# Abstract methods that don't exist at runtime +_io._IOBase.read +_io._IOBase.write + logging.LogRecord.__setattr__ # doesn't exist, but makes things easy if we pretend it does # Iterable classes that don't define __iter__ at runtime (usually iterable via __getitem__) From 4de0fc02d8c7d40267ea2cf9e3153ca37a81c536 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 09:13:56 +0000 Subject: [PATCH 5/7] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/_io.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/_io.pyi b/stdlib/_io.pyi index b4aa3340c672..6bba0408ae7d 100644 --- a/stdlib/_io.pyi +++ b/stdlib/_io.pyi @@ -3,7 +3,7 @@ import codecs import sys from _typeshed import FileDescriptorOrPath, MaybeNone, ReadableBuffer, WriteableBuffer from abc import abstractmethod -from collections.abc import Callable, Iterable, Iterator +from collections.abc import Iterable, Iterator from io import BufferedIOBase, RawIOBase, TextIOBase, UnsupportedOperation as UnsupportedOperation from os import _Opener from types import TracebackType From 1e359e71659d80d3b348dd1b6fdb608e977dd604 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 21 Oct 2026 11:38:22 +0200 Subject: [PATCH 6/7] Remove @abstractmethod decorator --- stdlib/_io.pyi | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stdlib/_io.pyi b/stdlib/_io.pyi index 6bba0408ae7d..3d3b343d50c8 100644 --- a/stdlib/_io.pyi +++ b/stdlib/_io.pyi @@ -2,7 +2,6 @@ import builtins import codecs import sys from _typeshed import FileDescriptorOrPath, MaybeNone, ReadableBuffer, WriteableBuffer -from abc import abstractmethod from collections.abc import Iterable, Iterator from io import BufferedIOBase, RawIOBase, TextIOBase, UnsupportedOperation as UnsupportedOperation from os import _Opener @@ -67,16 +66,16 @@ else: def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... - @abstractmethod - def read(self) -> Any: ... # the arguments and return type depend on the sub-class + # Abstract method that doesn't exist at runtime, the exact arguments and return type depend on the sub-class + def read(self) -> Any: ... def readlines(self, hint: int = -1, /) -> list[bytes]: ... def seek(self, offset: int, whence: int = 0, /) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def truncate(self, size: int | None = None, /) -> int: ... def writable(self) -> bool: ... - @abstractmethod - def write(self, s: Any, /) -> Any: ... # the exact arguments and return type depend on the sub-class + # Abstract method that doesn't exist at runtime, the exact arguments and return type depend on the sub-class + def write(self, s: Any, /) -> Any: ... def writelines(self, lines: Iterable[ReadableBuffer], /) -> None: ... def readline(self, size: int | None = -1, /) -> bytes: ... def __del__(self) -> None: ... From 9685f276b613fb5690212e9c0b42c50c15573a66 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 21 Oct 2026 11:57:16 +0200 Subject: [PATCH 7/7] both branches --- stdlib/_io.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/_io.pyi b/stdlib/_io.pyi index 3d3b343d50c8..c32807c3ce22 100644 --- a/stdlib/_io.pyi +++ b/stdlib/_io.pyi @@ -36,16 +36,16 @@ if sys.version_info >= (3, 12): def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... - @abstractmethod - def read(self) -> Any: ... # the arguments and return type depend on the sub-class + # Abstract method that doesn't exist at runtime, the exact arguments and return type depend on the sub-class + def read(self) -> Any: ... def readlines(self, hint: int = -1, /) -> list[bytes]: ... def seek(self, offset: int, whence: int = 0, /) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def truncate(self, size: int | None = None, /) -> int: ... def writable(self) -> bool: ... - @abstractmethod - def write(self, s: Any, /) -> Any: ... # the exact arguments and return type depend on the sub-class + # Abstract method that doesn't exist at runtime, the exact arguments and return type depend on the sub-class + def write(self, s: Any, /) -> Any: ... def writelines(self, lines: Iterable[ReadableBuffer], /) -> None: ... def readline(self, size: int | None = -1, /) -> bytes: ... def __del__(self) -> None: ...