Skip to content

Abstract __getitem__ in Sequence doesn't type check #3458

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

Closed
MichalKononenko opened this issue Nov 12, 2019 · 2 comments
Closed

Abstract __getitem__ in Sequence doesn't type check #3458

MichalKononenko opened this issue Nov 12, 2019 · 2 comments

Comments

@MichalKononenko
Copy link

I have the following code snippet

from typing import Sequence

class AbstractSequence(Sequence[float]):
    @overload
    def __getitem__(self, index: int) -> float:
        pass

    @overload
    def __getitem__( 
            self, index: slice
    ) -> 'AbstractSequence':
        pass

    @abc.abstractmethod
    def __getitem__( 
            self, index: Union[int, slice]
        ) -> Union[float, 'AbstractSequence']:
        raise NotImplementedError()

Mypy claims that the signature of the abstract getitem is incompatible with that of the supertype. Can anyone give me a hand with this?

@posita
Copy link
Contributor

posita commented Jul 30, 2021

I don't think this is specific to typeshed. Even without Sequence, it still fails (which seems super weird, given python/mypy#10895):

# test_case.py

from abc import abstractmethod
from typing import List, Union, overload

class GetItemBase:
    @overload
    def __getitem__(self, key: int) -> int:
        ...
    @overload
    def __getitem__(self, key: slice) -> List[int]:
        ...
    @abstractmethod
    def __getitem__(self, key: Union[int, slice]) -> Union[int, List[int]]:
        ...

class GetItemTest(GetItemBase):
    def __getitem__(self, key: Union[int, slice]) -> Union[int, List[int]]:  # <- typing error despite being identical
        return list(range(10))[key]

Runtime:

% python --version
Python 3.9.6
% pip list
Package           Version
----------------- --------
mypy              0.910
mypy-extensions   0.4.3
pip               21.2.1
setuptools        57.4.0
toml              0.10.2
typing-extensions 3.10.0.0
% mypy --config=/dev/null test_case.py
/dev/null: No [mypy] section in config file
test_case.py:18: error: Signature of "__getitem__" incompatible with supertype "GetItemBase"
Found 1 error in 1 file (checked 1 source file)
% mypy --version
mypy 0.910

@Akuli
Copy link
Collaborator

Akuli commented Jul 30, 2021

GetItemBase says that instance[some_integer] must be an integer and instance[some_slice] must be a list. The inheriting class doesn't provide any guarantees like this; as far as mypy knows, instance[some_integer] with that __getitem__ method could be an integer or a list.

To fix this, you can # type: ignore the erroring line or copy/paste the overloads to the subclass:

class GetItemBase:
    @overload
    def __getitem__(self, key: int) -> int:
        ...
    @overload
    def __getitem__(self, key: slice) -> List[int]:
        ...
    @abstractmethod
    def __getitem__(self, key: Union[int, slice]) -> Union[int, List[int]]:
        ...

class GetItemTest(GetItemBase):
    @overload
    def __getitem__(self, key: int) -> int:
        ...
    @overload
    def __getitem__(self, key: slice) -> List[int]:
        ...
    def __getitem__(self, key: Union[int, slice]) -> Union[int, List[int]]:  # <- typing error despite being identical
        return list(range(10))[key]

@Akuli Akuli closed this as completed Jul 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants