mypy icon indicating copy to clipboard operation
mypy copied to clipboard

More-helpful typing errors with Generics and Callables

Open tomhampshire opened this issue 2 years ago • 0 comments

Feature

Taking into consideration the following code (using mypy==1.4.1), the error messages are not very useful in debugging the problem. I have included the Pyright error message for comparison:

"""A test pipeline"""
from __future__ import annotations

from typing import Callable, Generic, TypeVar

from pydantic import BaseModel

from filter_base.filters.base_filter import BaseFilter

ModelT = TypeVar("ModelT", bound=BaseModel)


class TestFilter(BaseFilter, Generic[ModelT]):
    """A filter for loading a JSON file."""

    def __init__(self, model_type: type[ModelT]):
        """Test filter."""
        self.model_type: type[ModelT] = model_type

    def output(self) -> ModelT:
        """Output the loaded model"""
        return self.model_type()

    def input(self, obj: ModelT) -> None:
        """Input the model"""
        pass


T = TypeVar("T")


def connect(
    connect_signal: Callable[[], T],
    connect_slot: Callable[[T], None],
) -> None:
    """Connect a signal to a slot"""

    # TODO: this is a bit silly - we're just immedicately calling the signal/slot
    # however - it'll do for the purposes of type checking
    connect_slot(connect_signal())


class SimpleModel(BaseModel):
    """A simple model"""

    a: int
    b: str


class SimpleModel2(BaseModel):
    """A simple model"""

    c: int
    d: str


def main() -> None:
    a = TestFilter(SimpleModel)
    b = TestFilter(SimpleModel2)

    connect(a.output, b.input)

The diagnostics from mypy and Pyright are as follows (error is on the final line of code):

Diagnostics:
1. mypy: Cannot infer type argument 1 of "connect" [misc]
2. Pyright: Argument of type "(obj: SimpleModel2) -> None" cannot be assigned to parameter "connect_slot" of type "(T@connect) -> None" in function "connect"
     Type "(obj: SimpleModel2) -> None" cannot be assigned to type "(SimpleModel) -> None"
       Parameter 1: type "SimpleModel" cannot be assigned to type "SimpleModel2"
         "SimpleModel" is incompatible with "SimpleModel2" [reportGeneralTypeIssues]

Pitch

Having the error messages of mypy more in-line with Pyright's reporting would mean that it is not essential to use Pyright's typechecking system when developing these sorts of generic systems.

tomhampshire avatar Jun 26 '23 13:06 tomhampshire