From 52c19bf52eb4a0c0692f8ebdab4958c370bc1c79 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 6 May 2022 22:31:26 -0700 Subject: [PATCH 01/11] tempfile.SpooledTemporaryFile: inherit from IOBase on 3.11 python/cpython#29560 --- stdlib/tempfile.pyi | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 4f2b4a545ff7..70bb72b3f288 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -1,3 +1,4 @@ +import io import os import sys from _typeshed import Self @@ -219,7 +220,11 @@ class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): # It does not actually derive from IO[AnyStr], but it does implement the # protocol. -class SpooledTemporaryFile(IO[AnyStr]): +if sys.version_info >= (3, 11): + _STFBase = io.IOBase +else: + _STFBase = object +class SpooledTemporaryFile(IO[AnyStr], _STFBase): @property def encoding(self) -> str: ... # undocumented @property @@ -318,6 +323,13 @@ class SpooledTemporaryFile(IO[AnyStr]): def fileno(self) -> int: ... def flush(self) -> None: ... def isatty(self) -> bool: ... + if sys.version_info >= (3, 11): + def readable(self) -> bool: ... + def read1(self, __size: int = ...) -> AnyStr: ... + def readinto(self, b: WriteableBuffer) -> int: ... + def readinto1(self, b: WriteableBuffer) -> int: ... + def seekable(self) -> bool: ... + def read(self, n: int = ...) -> AnyStr: ... def readline(self, limit: int = ...) -> AnyStr: ... def readlines(self, hint: int = ...) -> list[AnyStr]: ... From 3381dbae62f27984878b5fdff9c27d96dc100a04 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 7 May 2022 05:32:39 +0000 Subject: [PATCH 02/11] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/tempfile.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 70bb72b3f288..6b9f254dfad5 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -224,6 +224,7 @@ if sys.version_info >= (3, 11): _STFBase = io.IOBase else: _STFBase = object + class SpooledTemporaryFile(IO[AnyStr], _STFBase): @property def encoding(self) -> str: ... # undocumented From 5d41486373ec5bb97f34c8d6352a5b923fae49ea Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 7 May 2022 11:33:25 +0100 Subject: [PATCH 03/11] Add missing import --- stdlib/tempfile.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 6b9f254dfad5..0b074855d56e 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -1,7 +1,7 @@ import io import os import sys -from _typeshed import Self +from _typeshed import Self, WriteableBuffer from collections.abc import Iterable, Iterator from types import TracebackType from typing import IO, Any, AnyStr, Generic, overload From 20bbbcadcfb65e69afb23a3dba2c239d6bbe06cd Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 7 May 2022 18:35:02 -0700 Subject: [PATCH 04/11] Fix pre-3.11 lies --- stdlib/tempfile.pyi | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 0b074855d56e..fbae3d6f80ce 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -218,8 +218,8 @@ class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): def write(self, s: AnyStr) -> int: ... def writelines(self, lines: Iterable[AnyStr]) -> None: ... -# It does not actually derive from IO[AnyStr], but it does implement the -# protocol. +# It does not actually derive from IO[AnyStr], but it does mostly behave +# like one. if sys.version_info >= (3, 11): _STFBase = io.IOBase else: @@ -325,11 +325,9 @@ class SpooledTemporaryFile(IO[AnyStr], _STFBase): def flush(self) -> None: ... def isatty(self) -> bool: ... if sys.version_info >= (3, 11): - def readable(self) -> bool: ... def read1(self, __size: int = ...) -> AnyStr: ... def readinto(self, b: WriteableBuffer) -> int: ... def readinto1(self, b: WriteableBuffer) -> int: ... - def seekable(self) -> bool: ... def read(self, n: int = ...) -> AnyStr: ... def readline(self, limit: int = ...) -> AnyStr: ... @@ -340,7 +338,7 @@ class SpooledTemporaryFile(IO[AnyStr], _STFBase): def write(self, s: AnyStr) -> int: ... def writelines(self, iterable: Iterable[AnyStr]) -> None: ... def __iter__(self) -> Iterator[AnyStr]: ... - # Other than the following methods, which do not exist on SpooledTemporaryFile + # These exist at runtime only on 3.11+. def readable(self) -> bool: ... def seekable(self) -> bool: ... def writable(self) -> bool: ... From 2f480cd527d6ff864a43f110a9510289290a7bc2 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 7 May 2022 18:49:30 -0700 Subject: [PATCH 05/11] goodbye LSP --- stdlib/tempfile.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index fbae3d6f80ce..6720a3ca93a3 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -330,14 +330,14 @@ class SpooledTemporaryFile(IO[AnyStr], _STFBase): def readinto1(self, b: WriteableBuffer) -> int: ... def read(self, n: int = ...) -> AnyStr: ... - def readline(self, limit: int = ...) -> AnyStr: ... - def readlines(self, hint: int = ...) -> list[AnyStr]: ... + def readline(self, limit: int | None = ...) -> AnyStr: ... # type: ignore[override] + def readlines(self, hint: int = ...) -> list[AnyStr]: ... # type: ignore[override] def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def truncate(self, size: int | None = ...) -> None: ... # type: ignore[override] def write(self, s: AnyStr) -> int: ... - def writelines(self, iterable: Iterable[AnyStr]) -> None: ... - def __iter__(self) -> Iterator[AnyStr]: ... + def writelines(self, iterable: Iterable[AnyStr]) -> None: ... # type: ignore[override] + def __iter__(self) -> Iterator[AnyStr]: ... # type: ignore[override] # These exist at runtime only on 3.11+. def readable(self) -> bool: ... def seekable(self) -> bool: ... From 14ed18d9e8ca4a765eaa9684ada782c9e84f8ff3 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 7 May 2022 18:50:13 -0700 Subject: [PATCH 06/11] less cryptic name --- stdlib/tempfile.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 6720a3ca93a3..094c466e5e12 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -221,11 +221,11 @@ class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): # It does not actually derive from IO[AnyStr], but it does mostly behave # like one. if sys.version_info >= (3, 11): - _STFBase = io.IOBase + _SpooledTemporaryFileBase = io.IOBase else: - _STFBase = object + _SpooledTemporaryFileBase = object -class SpooledTemporaryFile(IO[AnyStr], _STFBase): +class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): @property def encoding(self) -> str: ... # undocumented @property From c8793ecc30e393314e3515247ccc4e4fe34b9b88 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 7 May 2022 19:04:24 -0700 Subject: [PATCH 07/11] another one --- stdlib/tempfile.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 094c466e5e12..964c62b6eb8c 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -342,7 +342,7 @@ class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): def readable(self) -> bool: ... def seekable(self) -> bool: ... def writable(self) -> bool: ... - def __next__(self) -> AnyStr: ... + def __next__(self) -> AnyStr: ... # type: ignore[override] if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... From 091a8262fce5baf6b7889956f0bf214f920275d4 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 8 May 2022 07:29:05 -0700 Subject: [PATCH 08/11] add .detach() --- stdlib/tempfile.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 964c62b6eb8c..c764bd500512 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -328,6 +328,7 @@ class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): def read1(self, __size: int = ...) -> AnyStr: ... def readinto(self, b: WriteableBuffer) -> int: ... def readinto1(self, b: WriteableBuffer) -> int: ... + def detach(self) -> io.RawIOBase: ... def read(self, n: int = ...) -> AnyStr: ... def readline(self, limit: int | None = ...) -> AnyStr: ... # type: ignore[override] From d4d73e503c6af2e64e8f875369ea374d1684af8d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 17 May 2022 05:26:16 -0700 Subject: [PATCH 09/11] stubtest --- tests/stubtest_allowlists/py311.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/stubtest_allowlists/py311.txt b/tests/stubtest_allowlists/py311.txt index 07c8c8a01896..adac782a06cd 100644 --- a/tests/stubtest_allowlists/py311.txt +++ b/tests/stubtest_allowlists/py311.txt @@ -225,10 +225,6 @@ subprocess.getstatusoutput symtable.SymbolTable.has_exec sys.UnraisableHookArgs # Not exported from sys sys.exception -tempfile.SpooledTemporaryFile.detach -tempfile.SpooledTemporaryFile.read1 -tempfile.SpooledTemporaryFile.readinto -tempfile.SpooledTemporaryFile.readinto1 tkinter._VersionInfoType.__doc__ traceback.StackSummary.format_frame_summary traceback.TracebackException.__init__ From 1106632fcae166ee60c5c4686078d95ca97380ce Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 17 May 2022 18:08:28 -0700 Subject: [PATCH 10/11] pos-only args --- stdlib/tempfile.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index c764bd500512..8035b798cb27 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -330,9 +330,9 @@ class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): def readinto1(self, b: WriteableBuffer) -> int: ... def detach(self) -> io.RawIOBase: ... - def read(self, n: int = ...) -> AnyStr: ... - def readline(self, limit: int | None = ...) -> AnyStr: ... # type: ignore[override] - def readlines(self, hint: int = ...) -> list[AnyStr]: ... # type: ignore[override] + def read(self, __n: int = ...) -> AnyStr: ... + def readline(self, __limit: int | None = ...) -> AnyStr: ... # type: ignore[override] + def readlines(self, __hint: int = ...) -> list[AnyStr]: ... # type: ignore[override] def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def truncate(self, size: int | None = ...) -> None: ... # type: ignore[override] From 4a27d2dae5b982982dbbd7e03191f9847cc746c1 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 17 May 2022 18:10:33 -0700 Subject: [PATCH 11/11] comments --- stdlib/tempfile.pyi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/tempfile.pyi b/stdlib/tempfile.pyi index 8035b798cb27..9efa2d942401 100644 --- a/stdlib/tempfile.pyi +++ b/stdlib/tempfile.pyi @@ -218,13 +218,13 @@ class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): def write(self, s: AnyStr) -> int: ... def writelines(self, lines: Iterable[AnyStr]) -> None: ... -# It does not actually derive from IO[AnyStr], but it does mostly behave -# like one. if sys.version_info >= (3, 11): _SpooledTemporaryFileBase = io.IOBase else: _SpooledTemporaryFileBase = object +# It does not actually derive from IO[AnyStr], but it does mostly behave +# like one. class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): @property def encoding(self) -> str: ... # undocumented @@ -325,6 +325,8 @@ class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): def flush(self) -> None: ... def isatty(self) -> bool: ... if sys.version_info >= (3, 11): + # These three work only if the SpooledTemporaryFile is opened in binary mode, + # because the underlying object in text mode does not have these methods. def read1(self, __size: int = ...) -> AnyStr: ... def readinto(self, b: WriteableBuffer) -> int: ... def readinto1(self, b: WriteableBuffer) -> int: ...