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

Allow mypy to verify if passed object suits to the type hint of an abstract base class #14537

Closed
Dvergatal opened this issue Jan 27, 2023 · 1 comment
Labels

Comments

@Dvergatal
Copy link

Dvergatal commented Jan 27, 2023

Feature

Verification of inheritance with an abstract base classes, meaning that if a variable in method is of type hint of an abstract base class derived from another abstract base class from which inherits also passed parameter to that function, a proper verification shall be done.

Pitch

In case of overloaded functions with type hint e.g. validate_enum_list(key: str, value: str, allowed_values: Iterable[str]) and validate_enum_list(key: str, value: Iterable[str], allowed_values: Iterable[Iterable[str]]) it is not possible without additional implementation of own abstract base class MyIterable to differentiate str from Iterable[str].

I have seen #11001 but it is still open without any clear resolution. It also mentions python/typing#256 and #5090

Use Cases

from typing import Any, Iterable, TypeVar, List, Container
from multimethod import multimethod
from types import GenericAlias

T = TypeVar("T")
class MyIterable(Iterable[T]):
    @classmethod
    def __subclasshook__(cls, subclass: type) -> bool:
        return not issubclass(subclass, str)

    def __class_getitem__(cls, key: Any) -> GenericAlias:
        return GenericAlias(cls, key)

@multimethod
def validate_enum_list(key: str, value: str, allowed_values: MyIterable[str]) -> None:
    print("key: str, value: str, allowed_values: MyIterable[str]")
    print(type(value))
    print(type(allowed_values))

@validate_enum_list.register
def _(key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]) -> None:
    print("key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]")
    print(type(value))
    print(type(allowed_values))

    value = sorted(value)  # this causes mypy error
    allowed_values = sorted([sorted(item) for item in allowed_values])  # this causes mypy error

validate_enum_list("test1", "test1", ["test1"])
validate_enum_list("test2", ["test2"], [["test1"]])
#validate_enum_list("test1", "test1", [["test1"]])  # uncommenting this will cause runtime exception which is GOOD, but no mypy error which is also WRONG

def get_enum_str(key: str, value: str, allowed_values: MyIterable[str]) -> None:
    validate_enum_list(key, value, allowed_values)
    print("get_enum_str")

def get_enum_str_list(key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]) -> None:
    validate_enum_list(key, value, allowed_values)

get_enum_str("test1", "test1", ["test1"])
get_enum_str_list("test2", ["test2"], [["test2"]])
get_enum_str_list("test2", "test2", [["test2"]])  # this causes mypy error

As commented in the code, line validate_enum_list("test1", "test1", [["test1"]]) does not return an error from mypy, but the same issue is with singledispatch decorator which I have already found is a bug.

P.S. I have found some additional informations regardless class_getitem() which is supposed to handle type hinting in such cases, but It is also mentioned that:

Custom implementations of __class_getitem__() on classes defined outside of the standard library may not be understood by third-party type-checkers such as mypy

So for now I'm confused as to whether it should be a feature request or a bug...

@Dvergatal Dvergatal changed the title Allow mypy to verify if passed object suits to the typehint of an abstract base class Allow mypy to verify if passed object suits to the type hint of an abstract base class Jan 27, 2023
@erictraut
Copy link

Mypy appears to be doing the right thing here. The code is attempting to assign a value back to value that violates its declared type. The same is true for allowed_values. And the other errors are all legitimate. Mypy and pyright are in agreement on all of the errors in the file. Recommend closing.

@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Aug 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants