Skip to content

Commit 9fbcc6c

Browse files
authored
Use protocols for gzip and _compression (#5170)
Closes: #5099
1 parent 6c01c6a commit 9fbcc6c

File tree

2 files changed

+87
-14
lines changed

2 files changed

+87
-14
lines changed

stdlib/_compression.pyi

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
from _typeshed import WriteableBuffer
22
from io import BufferedIOBase, RawIOBase
3-
from typing import Any, Callable, Tuple, Type, Union
3+
from typing import Any, Callable, Protocol, Tuple, Type, Union
44

55
BUFFER_SIZE: Any
66

7+
class _Reader(Protocol):
8+
def read(self, __n: int) -> bytes: ...
9+
def seekable(self) -> bool: ...
10+
def seek(self, __n: int) -> Any: ...
11+
712
class BaseStream(BufferedIOBase): ...
813

914
class DecompressReader(RawIOBase):
1015
def __init__(
1116
self,
12-
fp: RawIOBase,
17+
fp: _Reader,
1318
decomp_factory: Callable[..., object],
1419
trailing_error: Union[Type[Exception], Tuple[Type[Exception], ...]] = ...,
1520
**decomp_args: Any,

stdlib/gzip.pyi

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,46 @@ import _compression
22
import sys
33
import zlib
44
from _typeshed import AnyPath, ReadableBuffer
5-
from typing import IO, Optional, TextIO, Union, overload
5+
from io import FileIO
6+
from typing import Any, Optional, Protocol, TextIO, Union, overload
67
from typing_extensions import Literal
78

8-
_OpenBinaryMode = Literal["r", "rb", "a", "ab", "w", "wb", "x", "xb"]
9+
_ReadBinaryMode = Literal["r", "rb"]
10+
_WriteBinaryMode = Literal["a", "ab", "w", "wb", "x", "xb"]
911
_OpenTextMode = Literal["rt", "at", "wt", "xt"]
12+
13+
READ: Literal[1]
14+
WRITE: Literal[2]
15+
16+
class _ReadableFileobj(Protocol):
17+
def read(self, __n: int) -> bytes: ...
18+
def seek(self, __n: int) -> Any: ...
19+
# The following attributes and methods are optional:
20+
# name: str
21+
# mode: str
22+
# def fileno() -> int: ...
23+
24+
class _WritableFileobj(Protocol):
25+
def write(self, __b: bytes) -> Any: ...
26+
def flush(self) -> Any: ...
27+
# The following attributes and methods are optional:
28+
# name: str
29+
# mode: str
30+
# def fileno() -> int: ...
31+
32+
@overload
33+
def open(
34+
filename: Union[AnyPath, _ReadableFileobj],
35+
mode: _ReadBinaryMode = ...,
36+
compresslevel: int = ...,
37+
encoding: None = ...,
38+
errors: None = ...,
39+
newline: None = ...,
40+
) -> GzipFile: ...
1041
@overload
1142
def open(
12-
filename: Union[AnyPath, IO[bytes]],
13-
mode: _OpenBinaryMode = ...,
43+
filename: Union[AnyPath, _WritableFileobj],
44+
mode: _WriteBinaryMode,
1445
compresslevel: int = ...,
1546
encoding: None = ...,
1647
errors: None = ...,
@@ -27,7 +58,7 @@ def open(
2758
) -> TextIO: ...
2859
@overload
2960
def open(
30-
filename: Union[AnyPath, IO[bytes]],
61+
filename: Union[AnyPath, _ReadableFileobj, _WritableFileobj],
3162
mode: str,
3263
compresslevel: int = ...,
3364
encoding: Optional[str] = ...,
@@ -36,8 +67,8 @@ def open(
3667
) -> Union[GzipFile, TextIO]: ...
3768

3869
class _PaddedFile:
39-
file: IO[bytes]
40-
def __init__(self, f: IO[bytes], prepend: bytes = ...) -> None: ...
70+
file: _ReadableFileobj
71+
def __init__(self, f: _ReadableFileobj, prepend: bytes = ...) -> None: ...
4172
def read(self, size: int) -> bytes: ...
4273
def prepend(self, prepend: bytes = ...) -> None: ...
4374
def seek(self, off: int) -> int: ...
@@ -47,17 +78,54 @@ if sys.version_info >= (3, 8):
4778
class BadGzipFile(OSError): ...
4879

4980
class GzipFile(_compression.BaseStream):
50-
myfileobj: Optional[IO[bytes]]
51-
mode: str
81+
myfileobj: Optional[FileIO]
82+
mode: Literal[1, 2]
5283
name: str
5384
compress: zlib._Compress
54-
fileobj: IO[bytes]
85+
fileobj: Union[_ReadableFileobj, _WritableFileobj]
86+
@overload
87+
def __init__(
88+
self,
89+
filename: Optional[AnyPath],
90+
mode: _ReadBinaryMode,
91+
compresslevel: int = ...,
92+
fileobj: Optional[_ReadableFileobj] = ...,
93+
mtime: Optional[float] = ...,
94+
) -> None: ...
95+
@overload
96+
def __init__(
97+
self,
98+
*,
99+
mode: _ReadBinaryMode,
100+
compresslevel: int = ...,
101+
fileobj: Optional[_ReadableFileobj] = ...,
102+
mtime: Optional[float] = ...,
103+
) -> None: ...
104+
@overload
105+
def __init__(
106+
self,
107+
filename: Optional[AnyPath],
108+
mode: _WriteBinaryMode,
109+
compresslevel: int = ...,
110+
fileobj: Optional[_WritableFileobj] = ...,
111+
mtime: Optional[float] = ...,
112+
) -> None: ...
113+
@overload
114+
def __init__(
115+
self,
116+
*,
117+
mode: _WriteBinaryMode,
118+
compresslevel: int = ...,
119+
fileobj: Optional[_WritableFileobj] = ...,
120+
mtime: Optional[float] = ...,
121+
) -> None: ...
122+
@overload
55123
def __init__(
56124
self,
57125
filename: Optional[AnyPath] = ...,
58126
mode: Optional[str] = ...,
59127
compresslevel: int = ...,
60-
fileobj: Optional[IO[bytes]] = ...,
128+
fileobj: Union[_ReadableFileobj, _WritableFileobj, None] = ...,
61129
mtime: Optional[float] = ...,
62130
) -> None: ...
63131
@property
@@ -82,7 +150,7 @@ class GzipFile(_compression.BaseStream):
82150
def readline(self, size: Optional[int] = ...) -> bytes: ...
83151

84152
class _GzipReader(_compression.DecompressReader):
85-
def __init__(self, fp: IO[bytes]) -> None: ...
153+
def __init__(self, fp: _ReadableFileobj) -> None: ...
86154
def read(self, size: int = ...) -> bytes: ...
87155

88156
if sys.version_info >= (3, 8):

0 commit comments

Comments
 (0)