-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
make io.pyi import everything from _io.py(i), like io.py does #1395
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Also, as far as possible, try to simplify, by moving methods into base classes.
This PR got larger than expected. The basic motivation is to allow code like
to pass type-checking. (Which it didn't before, since |
Do you have code that directly imports Anyway, I tested this without our internal code and it found one issue, io.BufferedIOBase is supposed to define I am also still worried about some classes not inheriting from BinaryIO where they should. BinaryIO is abstract, we must ensure the abstractness or concreteness of various classes matches those in the stdlib. |
We do, unfortunately. Some in internal code, but I'm also seeing occurrences in third party packages like pymock and astroid.
Right. Made |
Seeing all the |
I don't see why not. Let me look into it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the cleanup! I left some comments from comparing this with the C code and (mostly) the docs.
stdlib/2/_io.pyi
Outdated
def seek(self, offset: int, whence: int = ...) -> int: ... | ||
def seekable(self) -> bool: ... | ||
def tell(self) -> int: ... | ||
def truncate(self, size: Optional[int] = ...) -> int: ... | ||
def writable(self) -> bool: ... | ||
def write(self, s: bytes) -> int: ... | ||
def __exit__(self, type, value, traceback) -> bool: ... | ||
# This just returns self: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then why not use a self type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
stdlib/2/_io.pyi
Outdated
def seek(self, offset: int, whence: int = ...) -> int: ... | ||
def seekable(self) -> bool: ... | ||
def tell(self) -> int: ... | ||
def truncate(self, size: Optional[int] = ...) -> int: ... | ||
def writable(self) -> bool: ... | ||
def write(self, s: bytes) -> int: ... | ||
def __exit__(self, type, value, traceback) -> bool: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you remove the argument types here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad. The types got under the wheel when I shifted __exit__
back and fro.
That said, I'm not sure what we get out of having types on __exit__
. This function is invoked by the type-checker, not user code (nobody ever does a manual x.__exit__(a, b,c)
), and the parameters are not originating from user code, either.
Either way, I added types.
stdlib/2/_io.pyi
Outdated
def detach(self) -> "_BufferedIOBase": ... | ||
def __enter__(self) -> '_BufferedIOBase': ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks odd to have double quotes on one line and single on the next. Since this is a stub, we can just remove all quotes anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
stdlib/2/_io.pyi
Outdated
|
||
class FileIO(_RawIOBase): | ||
class FileIO(_RawIOBase, BytesIO): # type: ignore # for __enter__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this not be necessary if you used self types for these __enter__
methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
stdlib/2/io.pyi
Outdated
@@ -7,98 +7,28 @@ | |||
from typing import List, BinaryIO, TextIO, IO, overload, Iterator, Iterable, Any, Union, Optional | |||
import _io | |||
|
|||
DEFAULT_BUFFER_SIZE = 0 | |||
from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These need x as x
imports to make clear that they're re-exported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
stdlib/2/_io.pyi
Outdated
|
||
class BufferedRWPair(_BufferedIOBase): | ||
def peek(self, n: int = ...) -> str: ... | ||
def __init__(self, reader: _RawIOBase, writer: _RawIOBase) -> None: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also takes buffer_size
and max_buffer_size
arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
stdlib/2/_io.pyi
Outdated
class _TextIOBase(_IOBase): | ||
|
||
# Note: In the actual _io.py, _TextIOBase inherits from _IOBase. | ||
class _TextIOBase(TextIO): | ||
errors = ... # type: Optional[str] | ||
newlines = ... # type: Union[str, unicode] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the docs it can also be None or a tuple of strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, on _TextIOBase
, this always returns None:
https://github.com/python/cpython/blob/2.7/Modules/_io/textio.c#L104
overloaded below.
stdlib/2/_io.pyi
Outdated
def _checkSeekable(self) -> None: ... | ||
def _checkWritable(self) -> None: ... | ||
def close(self) -> None: ... | ||
def detach(self) -> None: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This returns the underlying BufferedIOBase, not None.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to make this IO
, since _TextIOBase doesn't inherit from BufferedIOBase
, and the underlying stream might be either.
buffer
is IO
below, too.
stdlib/2/_io.pyi
Outdated
_CHUNK_SIZE = ... # type: int | ||
|
||
def open(file: Union[int, str], mode: str = ...) -> _IOBase: ... | ||
def __init__(self, buffer: IO, encoding: unicode = ..., |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be IO[bytes]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this works:
_io.TextIOWrapper(_io.StringIO(u"hello world")).read()
stdlib/2/_io.pyi
Outdated
|
||
def open(file: Union[int, str], mode: str = ...) -> _IOBase: ... | ||
def __init__(self, buffer: IO, encoding: unicode = ..., | ||
errors: unicode = ..., newline: unicode = ..., |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Further up you had encoding and errors attributes as str
on _TextIOBase
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. These parameters are actually more permissive. They allow None
, as well.
Thanks for the thorough review! |
Is there a way to tell github that (you think) you addressed all the requested changes on a PR? It seems we occasionally have dangling PRs because it's not clear whether the author is still working on it or not. |
I don't think so, the convention we follow is for the contributor to send a
comment to the PR saying they're done addressing the feedback.
|
That's also something I've missed in GitHub's workflow (similar to "request review" in Phabricator). I'll take another look at this PR in a few days. |
Well, "request review" exists -- it's just that "request re-review" doesn't. :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally think this is good to go, but I'll leave it up to @JelleZijlstra to approve and merge.
I guess I was stretching the definition of "a few days" :) Thanks! |
No description provided.