Skip to content

Commit bdb06b5

Browse files
JelleZijlstragvanrossum
authored andcommitted
improve codecs stubs (#2114)
Started out as progress towards #1476, but I ended up fixing a few more things: - fixed the signature of _encode_type, which actually returns a pair, not a string - made some attributes into properties in order to prevent the descriptor protocol from turning them into methods - found a bug in CPython in the process (python/cpython#6779) I used the following test file to make sure these classes are now instantiable: ```python import codecs import io from typing import IO bio = io.BytesIO() cod = codecs.lookup('utf-8') codecs.StreamReaderWriter(bio, codecs.StreamReader, codecs.StreamWriter) codecs.StreamRecoder(bio, cod.encode, cod.decode, codecs.StreamReader, codecs.StreamWriter) ```
1 parent d2469c0 commit bdb06b5

File tree

1 file changed

+62
-10
lines changed

1 file changed

+62
-10
lines changed

stdlib/2and3/codecs.pyi

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# https://docs.python.org/2/library/codecs.html and https://docs.python.org/3/library/codecs.html
33
import sys
44
from typing import (
5+
Any,
56
BinaryIO,
67
Callable,
78
Generator,
@@ -33,8 +34,8 @@ _encoded = bytes
3334

3435
# TODO: It is not possible to specify these signatures correctly, because
3536
# they have an optional positional or keyword argument for errors=.
36-
_encode_type = Callable[[_decoded], _encoded] # signature of Codec().encode
37-
_decode_type = Callable[[_encoded], _decoded] # signature of Codec().decode
37+
_encode_type = Callable[[_decoded], Tuple[_encoded, int]] # signature of Codec().encode
38+
_decode_type = Callable[[_encoded], Tuple[_decoded, int]] # signature of Codec().decode
3839
_stream_reader_type = Callable[[IO[_encoded]], 'StreamReader'] # signature of StreamReader __init__
3940
_stream_writer_type = Callable[[IO[_encoded]], 'StreamWriter'] # signature of StreamWriter __init__
4041
_incremental_encoder_type = Callable[[], 'IncrementalEncoder'] # signature of IncrementalEncoder __init__
@@ -49,13 +50,19 @@ def decode(obj: _encoded, encoding: str = ..., errors: str = ...) -> _decoded:
4950
def lookup(encoding: str) -> 'CodecInfo':
5051
...
5152
class CodecInfo(Tuple[_encode_type, _decode_type, _stream_reader_type, _stream_writer_type]):
52-
encode = ... # type: _encode_type
53-
decode = ... # type: _decode_type
54-
streamreader = ... # type: _stream_reader_type
55-
streamwriter = ... # type: _stream_writer_type
56-
incrementalencoder = ... # type: _incremental_encoder_type
57-
incrementaldecoder = ... # type: _incremental_decoder_type
58-
name = ... # type: str
53+
@property
54+
def encode(self) -> _encode_type: ...
55+
@property
56+
def decode(self) -> _decode_type: ...
57+
@property
58+
def streamreader(self) -> _stream_reader_type: ...
59+
@property
60+
def streamwriter(self) -> _stream_writer_type: ...
61+
@property
62+
def incrementalencoder(self) -> _incremental_encoder_type: ...
63+
@property
64+
def incrementaldecoder(self) -> _incremental_decoder_type: ...
65+
name: str
5966
def __init__(self, encode: _encode_type, decode: _decode_type, streamreader: _stream_reader_type = ..., streamwriter: _stream_writer_type = ..., incrementalencoder: _incremental_encoder_type = ..., incrementaldecoder: _incremental_decoder_type = ..., name: str = ...) -> None: ...
6067

6168
def getencoder(encoding: str) -> _encode_type:
@@ -207,7 +214,10 @@ class StreamReaderWriter(TextIO):
207214
def read(self, size: int= ...) -> _decoded: ...
208215
def readline(self, size: Optional[int] = ...) -> _decoded: ...
209216
def readlines(self, sizehint: Optional[int] = ...) -> List[_decoded]: ...
210-
def __next__(self) -> _decoded: ...
217+
if sys.version_info >= (3,):
218+
def __next__(self) -> Text: ...
219+
else:
220+
def next(self) -> Text: ...
211221
def __iter__(self: _T) -> _T: ...
212222
# This actually returns None, but that's incompatible with the supertype
213223
def write(self, data: _decoded) -> int: ...
@@ -217,7 +227,49 @@ class StreamReaderWriter(TextIO):
217227
def seek(self, offset: int, whence: int = ...) -> int: ...
218228
def __enter__(self: _T) -> _T: ...
219229
def __exit__(self, typ: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[types.TracebackType]) -> bool: ...
230+
def __getattr__(self, name: str) -> Any: ...
231+
232+
# These methods don't actually exist directly, but they are needed to satisfy the TextIO
233+
# interface. At runtime, they are delegated through __getattr__.
234+
def close(self) -> None: ...
235+
def fileno(self) -> int: ...
236+
def flush(self) -> None: ...
237+
def isatty(self) -> bool: ...
238+
def readable(self) -> bool: ...
239+
def truncate(self, size: Optional[int] = ...) -> int: ...
240+
def seekable(self) -> bool: ...
241+
def tell(self) -> int: ...
242+
def writable(self) -> bool: ...
243+
244+
_SRT = TypeVar('_SRT', bound=StreamRecoder)
220245

221246
class StreamRecoder(BinaryIO):
222247
def __init__(self, stream: IO[_encoded], encode: _encode_type, decode: _decode_type, Reader: _stream_reader_type, Writer: _stream_writer_type, errors: str = ...) -> None:
223248
...
249+
def read(self, size: int = ...) -> bytes: ...
250+
def readline(self, size: Optional[int] = ...) -> bytes: ...
251+
def readlines(self, sizehint: Optional[int] = ...) -> List[bytes]: ...
252+
if sys.version_info >= (3,):
253+
def __next__(self) -> bytes: ...
254+
else:
255+
def next(self) -> bytes: ...
256+
def __iter__(self: _SRT) -> _SRT: ...
257+
def write(self, data: bytes) -> int: ...
258+
def writelines(self, list: Iterable[bytes]) -> int: ... # type: ignore # it's supposed to return None
259+
def reset(self) -> None: ...
260+
def __getattr__(self, name: str) -> Any: ...
261+
def __enter__(self: _SRT) -> _SRT: ...
262+
def __exit__(self, type: Optional[Type[BaseException]], value: Optional[BaseException], tb: Optional[types.TracebackType]) -> bool: ...
263+
264+
# These methods don't actually exist directly, but they are needed to satisfy the BinaryIO
265+
# interface. At runtime, they are delegated through __getattr__.
266+
def seek(self, offset: int, whence: int = ...) -> int: ...
267+
def close(self) -> None: ...
268+
def fileno(self) -> int: ...
269+
def flush(self) -> None: ...
270+
def isatty(self) -> bool: ...
271+
def readable(self) -> bool: ...
272+
def truncate(self, size: Optional[int] = ...) -> int: ...
273+
def seekable(self) -> bool: ...
274+
def tell(self) -> int: ...
275+
def writable(self) -> bool: ...

0 commit comments

Comments
 (0)