From 2ff071dc8092dc8349ac24a2ab6723cc44102e40 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 29 May 2020 19:04:37 -0700 Subject: [PATCH] make io classes inherit from typing IO classes 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 945c21b5d680..76cbce4477ce 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],