From 3058bec873ef8b2b5630df36c4cbea0e3734dc5f Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 30 May 2020 06:50:49 -0700 Subject: [PATCH] make io classes inherit from typing IO classes (#4145) This makes these classes usable if type annotations are given as "IO" or "TextIO". In the future, we'll then be able to move open() to return a concrete class instead (#3951). --- stdlib/3/io.pyi | 73 ++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 49 deletions(-) diff --git a/stdlib/3/io.pyi b/stdlib/3/io.pyi index 945c21b5d..76cbce447 100644 --- a/stdlib/3/io.pyi +++ b/stdlib/3/io.pyi @@ -1,12 +1,11 @@ from typing import ( - List, BinaryIO, TextIO, Iterator, Union, Optional, Callable, Tuple, Type, Any, IO, Iterable + List, BinaryIO, TextIO, Iterator, Union, Optional, Callable, Tuple, Type, Any, IO, Iterable, TypeVar ) import builtins import codecs import sys from mmap import mmap from types import TracebackType -from typing import TypeVar if sys.version_info >= (3, 8): from typing import Literal @@ -85,9 +84,10 @@ class BufferedIOBase(IOBase): def read(self, __size: Optional[int] = ...) -> bytes: ... def read1(self, __size: int = ...) -> bytes: ... -class FileIO(RawIOBase): +class FileIO(RawIOBase, BinaryIO): mode: str - name: Union[int, str] + # Technically this is whatever is passed in as file, either a str, a bytes, or an int. + name: Union[int, str] # type: ignore def __init__( self, file: Union[str, bytes, int], @@ -95,6 +95,9 @@ class FileIO(RawIOBase): closefd: bool = ..., opener: Optional[Callable[[Union[int, str], str], int]] = ... ) -> None: ... + def write(self, __b: bytes) -> int: ... + def read(self, __size: int = ...) -> bytes: ... + def __enter__(self: _T) -> _T: ... class BytesIO(BufferedIOBase, BinaryIO): def __init__(self, initial_bytes: bytes = ...) -> None: ... @@ -110,7 +113,8 @@ class BytesIO(BufferedIOBase, BinaryIO): else: def read1(self, __size: Optional[int]) -> bytes: ... # type: ignore -class BufferedReader(BufferedIOBase): +class BufferedReader(BufferedIOBase, BinaryIO): + def __enter__(self: _T) -> _T: ... def __init__(self, raw: RawIOBase, buffer_size: int = ...) -> None: ... def peek(self, __size: int = ...) -> bytes: ... if sys.version_info >= (3, 7): @@ -118,15 +122,15 @@ class BufferedReader(BufferedIOBase): else: def read1(self, __size: int) -> bytes: ... # type: ignore -class BufferedWriter(BufferedIOBase): +class BufferedWriter(BufferedIOBase, BinaryIO): + def __enter__(self: _T) -> _T: ... def __init__(self, raw: RawIOBase, buffer_size: int = ...) -> None: ... - def flush(self) -> None: ... def write(self, __buffer: Union[bytes, bytearray]) -> int: ... class BufferedRandom(BufferedReader, BufferedWriter): + def __enter__(self: _T) -> _T: ... def __init__(self, raw: RawIOBase, buffer_size: int = ...) -> None: ... def seek(self, __target: int, __whence: int = ...) -> int: ... - def tell(self) -> int: ... if sys.version_info >= (3, 7): def read1(self, __size: int = ...) -> bytes: ... else: @@ -144,25 +148,18 @@ class TextIOBase(IOBase): def __iter__(self) -> Iterator[str]: ... # type: ignore def __next__(self) -> str: ... # type: ignore def detach(self) -> BinaryIO: ... - def write(self, s: str) -> int: ... + def write(self, __s: str) -> int: ... def writelines(self, __lines: List[str]) -> None: ... # type: ignore - def readline(self, size: int = ...) -> str: ... # type: ignore + def readline(self, __size: int = ...) -> str: ... # type: ignore def readlines(self, __hint: int = ...) -> List[str]: ... # type: ignore - def read(self, size: Optional[int] = ...) -> str: ... - def seek(self, offset: int, whence: int = ...) -> int: ... + def read(self, __size: Optional[int] = ...) -> str: ... def tell(self) -> int: ... -# TODO should extend from TextIOBase -class TextIOWrapper(TextIO): +class TextIOWrapper(TextIOBase, TextIO): line_buffering: bool - # TODO uncomment after fixing mypy about using write_through - # def __init__(self, buffer: IO[bytes], encoding: str = ..., - # errors: Optional[str] = ..., newline: Optional[str] = ..., - # line_buffering: bool = ..., write_through: bool = ...) \ - # -> None: ... def __init__( self, - buffer: BinaryIO, + buffer: IO[bytes], encoding: Optional[str] = ..., errors: Optional[str] = ..., newline: Optional[str] = ..., @@ -181,36 +178,15 @@ class TextIOWrapper(TextIO): line_buffering: Optional[bool] = ..., write_through: Optional[bool] = ... ) -> None: ... - # copied from IOBase - def __exit__(self, t: Optional[Type[BaseException]] = ..., value: Optional[BaseException] = ..., - traceback: Optional[TracebackType] = ...) -> Optional[bool]: ... - def close(self) -> None: ... - def fileno(self) -> int: ... - def flush(self) -> None: ... - def isatty(self) -> bool: ... - def readable(self) -> bool: ... - def readlines(self, __hint: int = ...) -> List[str]: ... - def seekable(self) -> bool: ... - def truncate(self, __size: Optional[int] = ...) -> int: ... - def writable(self) -> bool: ... - # TODO should be the next line instead - # def writelines(self, lines: List[str]) -> None: ... - def writelines(self, __lines: Any) -> None: ... - def __del__(self) -> None: ... closed: bool - # copied from TextIOBase - encoding: str - errors: Optional[str] - newlines: Union[str, Tuple[str, ...], None] - def __iter__(self) -> Iterator[str]: ... - def __next__(self) -> str: ... - def __enter__(self) -> TextIO: ... - def detach(self) -> BinaryIO: ... - def write(self, __text: str) -> int: ... - def readline(self, __size: int = ...) -> str: ... - def read(self, __size: Optional[int] = ...) -> str: ... + # These are inherited from TextIOBase, but must exist in the stub to satisfy mypy. + def __enter__(self: _T) -> _T: ... + def __iter__(self) -> Iterator[str]: ... # type: ignore + def __next__(self) -> str: ... # type: ignore + def writelines(self, __lines: List[str]) -> None: ... # type: ignore + def readline(self, __size: int = ...) -> str: ... # type: ignore + def readlines(self, __hint: int = ...) -> List[str]: ... # type: ignore def seek(self, __cookie: int, __whence: int = ...) -> int: ... - def tell(self) -> int: ... class StringIO(TextIOWrapper): def __init__(self, initial_value: Optional[str] = ..., @@ -220,7 +196,6 @@ class StringIO(TextIOWrapper): # as a read-only property on IO[]. name: Any def getvalue(self) -> str: ... - def __enter__(self) -> StringIO: ... class IncrementalNewlineDecoder(codecs.IncrementalDecoder): def __init__(self, decoder: Optional[codecs.IncrementalDecoder],