Skip to content

Problems with overloads / mypy bug #410

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
thepabloaguilar opened this issue Jun 9, 2020 · 4 comments · Fixed by #667
Closed

Problems with overloads / mypy bug #410

thepabloaguilar opened this issue Jun 9, 2020 · 4 comments · Fixed by #667
Labels
bug Something isn't working dependencies Pull requests that update a dependency file

Comments

@thepabloaguilar
Copy link
Member

thepabloaguilar commented Jun 9, 2020

I'm having some errors with typing, if it's not a returns problem feel free to close this issue

Mypy errors:

get_stream_details.py:78: error: Argument 1 to "apply" of "Result" has incompatible type "Result[overloaded function, Any]"; expected "Result[Callable[[Stream], StreamDetails], FailureDetails]"
get_stream_details.py:78: error: Argument 1 has incompatible type "Result[StreamDetails, FailureDetails]"; expected "Maybe[Any]"
get_stream_details.py:78: error: Incompatible return value type (got "Maybe[Any]", expected "Result[StreamDetails, FailureDetails]")
get_stream_details.py:79: error: Argument 1 to "_flow" has incompatible type "Result[overloaded function, Any]"; expected "Result[overloaded function, Any]"
get_stream_details.py:79: error: Argument 1 to "from_value" of "Result" has incompatible type overloaded function; expected overloaded function
get_stream_details.py:81: error: Cannot infer type argument 1 of "_bind"
get_stream_details.py:81: error: Argument 1 to "_bind" has incompatible type "Callable[[Any], Result[Any, FailureDetails]]"; expected "Callable[[Any], Maybe[Any]]"
get_stream_details.py:81: error: Incompatible return value type (got "Result[Any, FailureDetails]", expected "Maybe[object]")
get_stream_details.py:81: error: Incompatible return value type (got "Result[Any, FailureDetails]", expected "Maybe[Any]")
get_stream_details.py:81: error: Cannot infer type argument 1 of "Success"
get_stream_details.py:82: error: Cannot infer type argument 1 of "_bind"
get_stream_details.py:82: error: Argument 1 to "_bind" has incompatible type "Callable[[Any], Result[Any, FailureDetails]]"; expected "Callable[[Any], Maybe[Any]]"
get_stream_details.py:82: error: Incompatible return value type (got "Result[Any, FailureDetails]", expected "Maybe[object]")
get_stream_details.py:82: error: Incompatible return value type (got "Result[Any, FailureDetails]", expected "Maybe[Any]")
get_stream_details.py:82: error: Cannot infer type argument 1 of "Success"

All the errors above are from my return statement in GetStreamDetailsUsecase.__call__!

Code:

@dataclass_json
@dataclass
class StreamDetails:
    stream: Stream
    projects: List[Project]
    ksql_stream_detailed: KSQLStreamDetailed

    @classmethod
    @curry
    def build(
        cls,
        stream: Stream,
        projects: List[Project],
        ksql_stream_detailed: KSQLStreamDetailed,
    ) -> "StreamDetails":
        return cls(stream, projects, ksql_stream_detailed)


class FindStreamByStreamId(ABC):
    @abstractmethod
    def __call__(self, stream_id: UUID) -> Result[Maybe[Stream], FailureDetails]:
        pass


class FindProjectsByStream(ABC):
    @abstractmethod
    def __call__(self, stream: Stream) -> Result[List[Project], FailureDetails]:
        pass


# "GetStreamByNameUsecase" definition
# class GetStreamByNameUsecase:
#     def __call__(
#             self, stream_name: str
#         ) -> Result[KSQLStreamDetailed, BusinessFailureDetails]:
#         pass


class GetStreamDetailsUsecase:
    def __init__(
        self,
        find_stream_by_stream_id: FindStreamByStreamId,
        find_projects_by_stream: FindProjectsByStream,
        get_stream_by_name: GetStreamByNameUsecase,
    ):
        self.__find_stream_by_stream_id = find_stream_by_stream_id
        self.__find_projects_by_stream = find_projects_by_stream
        self.__get_stream_by_name = get_stream_by_name

    def __call__(self, stream_id: UUID) -> Result[StreamDetails, FailureDetails]:
        stream = self.__find_stream_by_stream_id(stream_id).bind(
            self.__verify_if_stream_exist
        )
        partial_projects = partial(stream.bind, self.__find_projects_by_stream)
        partial_ksql = partial(
            stream.bind, lambda stream_: self.__get_stream_by_name(stream_.name)
        )

        return flow(
            Result.from_value(StreamDetails.build),
            stream.apply,
            bind(lambda to_apply: partial_projects().apply(Success(to_apply))),
            bind(lambda to_apply: partial_ksql().apply(Success(to_apply))),
        )

    def __verify_if_stream_exist(
        self, stream: Maybe[Stream]
    ) -> Result[Stream, BusinessFailureDetails]:
        return maybe_to_result(stream).alt(
            lambda __: BusinessFailureDetails(
                reason="NOT_FOUND", failure_message="Stream not found"
            )
        )

But if I change the flow to handmade flow just one error appeared:

Mypy error:

error: Argument 1 to "from_value" of "Result" has incompatible type overloaded function; expected overloaded function

Code:

class GetStreamDetailsUsecase:
    # CODE

    def __call__(self, stream_id: UUID) -> Result[StreamDetails, FailureDetails]:
        stream = self.__find_stream_by_stream_id(stream_id).bind(
            self.__verify_if_stream_exist
        )
        partial_projects = partial(stream.bind, self.__find_projects_by_stream)
        partial_ksql = partial(
            stream.bind, lambda stream_: self.__get_stream_by_name(stream_.name)
        )

        details = Result.from_value(StreamDetails.build)
        details_added_stream = stream.apply(details)
        details_added_projects = details_added_stream.bind(lambda to_apply: partial_projects().apply(Success(to_apply)))
        details_added_ksql = details_added_projects.bind(lambda to_apply: partial_ksql().apply(Success(to_apply)))
        return details_added_ksql

    # CODE
@sobolevn
Copy link
Member

sobolevn commented Jun 9, 2020

Ok, looks like we found a bug in mypy. Here's the minimal example that works:

from returns.curry import curry
from returns.result import Result

@curry
def first(a: int, b: int) -> int:
    ...

reveal_type(
    Result.from_value(first),
)
# Revealed type is 'returns.result.Result[Overload(def (a: builtins.int) -> def (b: builtins.int) -> builtins.int, def (a: builtins.int, b: builtins.int) -> builtins.int), Any]'

But, this does not:

from returns.curry import curry
from returns.result import Result

@curry
def first(a: int, b: int, c: int) -> int:
    ...

reveal_type(
    Result.from_value(first),
)

Output:

» mypy ex.py
ex.py:9: note: Revealed type is 'returns.result.Result[Overload(def (a: builtins.int) -> Overload(def (b: builtins.int, c: builtins.int) -> builtins.int, def (b: builtins.int) -> def (c: builtins.int) -> builtins.int), def (a: builtins.int, b: builtins.int) -> def (c: builtins.int) -> builtins.int, def (a: builtins.int, b: builtins.int, c: builtins.int) -> builtins.int), Any]'
ex.py:9: error: Argument 1 to "from_value" of "Result" has incompatible type overloaded function; expected overloaded function
Found 1 error in 1 file (checked 1 source file)

Can you please create a new bug in mypy's issue tracker?

@sobolevn
Copy link
Member

Minimal reproduction: https://github.com/sobolevn/mypy-bug-410
mypy issue: python/mypy#9017

@sobolevn
Copy link
Member

Sorry, I haven't seen python/mypy#8978
I have closed my new issue as a duplicate.

@sobolevn sobolevn changed the title Typing problems with mypy Problems with overloads / mypy bug Aug 4, 2020
gvanrossum pushed a commit to python/mypy that referenced this issue Aug 5, 2020
@thepabloaguilar
Copy link
Member Author

Waiting for your changes to be released and finally close this issue!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working dependencies Pull requests that update a dependency file
Development

Successfully merging a pull request may close this issue.

2 participants