Skip to content
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

Change builtin method signatures to be compatible with Sequence, at the expense of accuracy. #1107

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 34 additions & 31 deletions stdlib/3/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,15 @@ class str(Sequence[str]):
def __init__(self, o: bytes, encoding: str = ..., errors: str = 'strict') -> None: ...
def capitalize(self) -> str: ...
def center(self, width: int, fillchar: str = ' ') -> str: ...
def count(self, x: str) -> int: ...
def count(self, x: str, start: int = None, stop: int = None) -> int: ... # TODO: __index__
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional[int] = .... In order to make future use of SupportsIndex or similar easier, you could for now define a type alias _Index = int, then declare these parameters as Optional[_Index]. If we gain support for SupportsIndex in the future, we can then easily change the alias.

def encode(self, encoding: str = 'utf-8', errors: str = 'strict') -> bytes: ...
def endswith(self, suffix: Union[str, Tuple[str, ...]], start: int = None,
end: int = None) -> bool: ...
end: int = None) -> bool: ... # TODO: __index__
def expandtabs(self, tabsize: int = 8) -> str: ...
def find(self, sub: str, start: int = 0, end: int = 0) -> int: ...
def find(self, sub: str, start: int = None, end: int = None) -> int: ... # TODO: __index__
def format(self, *args: Any, **kwargs: Any) -> str: ...
def format_map(self, map: Mapping[str, Any]) -> str: ...
def index(self, sub: str, start: int = 0, end: int = 0) -> int: ...
def index(self, sub: str, start: int = None, end: int = None) -> int: ... # TODO: __index__
def isalnum(self) -> bool: ...
def isalpha(self) -> bool: ...
def isdecimal(self) -> bool: ...
Expand All @@ -247,16 +247,16 @@ class str(Sequence[str]):
def lstrip(self, chars: str = None) -> str: ...
def partition(self, sep: str) -> Tuple[str, str, str]: ...
def replace(self, old: str, new: str, count: int = -1) -> str: ...
def rfind(self, sub: str, start: int = 0, end: int = 0) -> int: ...
def rindex(self, sub: str, start: int = 0, end: int = 0) -> int: ...
def rfind(self, sub: str, start: int = None, end: int = None) -> int: ... # TODO: __index__
def rindex(self, sub: str, start: int = None, end: int = None) -> int: ... # TODO: __index__
def rjust(self, width: int, fillchar: str = ' ') -> str: ...
def rpartition(self, sep: str) -> Tuple[str, str, str]: ...
def rsplit(self, sep: str = None, maxsplit: int = -1) -> List[str]: ...
def rstrip(self, chars: str = None) -> str: ...
def split(self, sep: str = None, maxsplit: int = -1) -> List[str]: ...
def splitlines(self, keepends: bool = ...) -> List[str]: ...
def startswith(self, prefix: Union[str, Tuple[str, ...]], start: int = None,
end: int = None) -> bool: ...
end: int = None) -> bool: ... # TODO: __index__
def strip(self, chars: str = None) -> str: ...
def swapcase(self) -> str: ...
def title(self) -> str: ...
Expand Down Expand Up @@ -306,22 +306,22 @@ class bytes(ByteString):
def capitalize(self) -> bytes: ...
def center(self, width: int, fillchar: bytes = ...) -> bytes: ...
if sys.version_info >= (3, 3):
def count(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def count(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def count(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def count(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
def decode(self, encoding: str = 'utf-8', errors: str = 'strict') -> str: ...
def endswith(self, suffix: Union[bytes, Tuple[bytes, ...]]) -> bool: ...
def expandtabs(self, tabsize: int = 8) -> bytes: ...
if sys.version_info >= (3, 3):
def find(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def find(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def find(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def find(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
if sys.version_info >= (3, 5):
def hex(self) -> str: ...
if sys.version_info >= (3, 3):
def index(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def index(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def index(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def index(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
def isalnum(self) -> bool: ...
def isalpha(self) -> bool: ...
def isdigit(self) -> bool: ...
Expand All @@ -336,13 +336,13 @@ class bytes(ByteString):
def partition(self, sep: bytes) -> Tuple[bytes, bytes, bytes]: ...
def replace(self, old: bytes, new: bytes, count: int = -1) -> bytes: ...
if sys.version_info >= (3, 3):
def rfind(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def rfind(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def rfind(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def rfind(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
if sys.version_info >= (3, 3):
def rindex(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def rindex(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def rindex(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def rindex(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
def rjust(self, width: int, fillchar: bytes = ...) -> bytes: ...
def rpartition(self, sep: bytes) -> Tuple[bytes, bytes, bytes]: ...
def rsplit(self, sep: bytes = None, maxsplit: int = -1) -> List[bytes]: ...
Expand Down Expand Up @@ -395,22 +395,22 @@ class bytearray(MutableSequence[int], ByteString):
def capitalize(self) -> bytearray: ...
def center(self, width: int, fillchar: bytes = ...) -> bytearray: ...
if sys.version_info >= (3, 3):
def count(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def count(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def count(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def count(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
def decode(self, encoding: str = 'utf-8', errors: str = 'strict') -> str: ...
def endswith(self, suffix: bytes) -> bool: ...
def expandtabs(self, tabsize: int = 8) -> bytearray: ...
if sys.version_info >= (3, 3):
def find(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def find(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def find(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def find(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
if sys.version_info >= (3, 5):
def hex(self) -> str: ...
if sys.version_info >= (3, 3):
def index(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def index(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def index(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def index(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
def insert(self, index: int, object: int) -> None: ...
def isalnum(self) -> bool: ...
def isalpha(self) -> bool: ...
Expand All @@ -426,13 +426,13 @@ class bytearray(MutableSequence[int], ByteString):
def partition(self, sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ...
def replace(self, old: bytes, new: bytes, count: int = -1) -> bytearray: ...
if sys.version_info >= (3, 3):
def rfind(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def rfind(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def rfind(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def rfind(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
if sys.version_info >= (3, 3):
def rindex(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ...
def rindex(self, sub: Union[bytes, int], start: int = None, end: int = None) -> int: ... # TODO: __index__
else:
def rindex(self, sub: bytes, start: int = None, end: int = None) -> int: ...
def rindex(self, sub: bytes, start: int = None, end: int = None) -> int: ... # TODO: __index__
def rjust(self, width: int, fillchar: bytes = ...) -> bytearray: ...
def rpartition(self, sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ...
def rsplit(self, sep: bytes = None, maxsplit: int = -1) -> List[bytearray]: ...
Expand Down Expand Up @@ -525,7 +525,7 @@ class slice:
@overload
def __init__(self, stop: Optional[int]) -> None: ...
@overload
def __init__(self, start: Optional[int], stop: Optional[int], step: int = None) -> None: ...
def __init__(self, start: Optional[int], stop: int = None, step: int = None) -> None: ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't the previous code correct? The first overload takes care of the case where only one argument is given.

def indices(self, len: int) -> Tuple[int, int, int]: ...

class tuple(Sequence[_T_co], Generic[_T_co]):
Expand All @@ -546,7 +546,8 @@ class tuple(Sequence[_T_co], Generic[_T_co]):
def __rmul__(self, n: int) -> Tuple[_T_co, ...]: ...
def count(self, x: Any) -> int: ...
if sys.version_info >= (3, 5):
def index(self, x: Any, start: int = 0, end: int = 0) -> int: ...
def index(self, x: Any, start: int = None, end: int = None) -> int: ... # TODO: __index__
# NOTE: tuple does not actually support None start/end, but it should to be compatible with Sequence.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should describe how tuple actually behaves, not how it's supposed to.

However, in this case I think you found at least a documentation bug in CPython: when you pass None it says TypeError: slice indices must be integers or None or have an __index__ method, and that error shouldn't mention None if None is not an acceptable value. Feel free to report that at bugs.python.org.

Unrelated problems with the existing code (outside the scope of this PR):

  • The defaults should be ..., not 0.
  • I feel like it would be more helpful to type the argument as _T_co instead of Any.

else:
def index(self, x: Any) -> int: ...

Expand All @@ -568,7 +569,8 @@ class list(MutableSequence[_T], Generic[_T]):
def append(self, object: _T) -> None: ...
def extend(self, iterable: Iterable[_T]) -> None: ...
def pop(self, index: int = -1) -> _T: ...
def index(self, object: _T, start: int = 0, stop: int = ...) -> int: ...
def index(self, object: _T, start: int = None, stop: int = None) -> int: ... # TODO: __index__
# NOTE: list does not actually support None start/stop, but it should to be compatible with Sequence.
def count(self, object: _T) -> int: ...
def insert(self, index: int, object: _T) -> None: ...
def remove(self, object: _T) -> None: ...
Expand Down Expand Up @@ -707,7 +709,8 @@ class range(Sequence[int]):
@overload
def __init__(self, start: int, stop: int, step: int = 1) -> None: ...
def count(self, value: int) -> int: ...
def index(self, value: int, start: int = 0, stop: int = None) -> int: ...
def index(self, value: int, start: int = None, end: int = None) -> int: ... # TODO: __index__
# NOTE: range does not actually have start/end parameters, but it should to be compatible with Sequence.
def __len__(self) -> int: ...
def __contains__(self, o: object) -> bool: ...
def __iter__(self) -> Iterator[int]: ...
Expand Down
2 changes: 1 addition & 1 deletion stdlib/3/typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class Sequence(_Collection[_T_co], Reversible[_T_co], Generic[_T_co]):
def __getitem__(self, s: slice) -> Sequence[_T_co]: ...
# Mixin methods
if sys.version_info >= (3, 5):
def index(self, x: Any, start: int = 0, end: int = 0) -> int: ...
def index(self, x: Any, start: int = None, end: int = None) -> int: ... # TODO: __index__
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional[int] = ... here too.

else:
def index(self, x: Any) -> int: ...
def count(self, x: Any) -> int: ...
Expand Down