python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.42k stars 2.82k forks source link

Typing with ClassVar[Optional[Callable]] doesn't work if the callable has arguments #15026

Open karamanolev opened 1 year ago

karamanolev commented 1 year ago

Typing an attribute in a base class with ClassVar[Optional[Callable]] results in a type error even though the typing is seemingly sound.

To Reproduce

Playground: https://mypy-play.net/?mypy=master&python=3.11&gist=4f52f561801eeb053b6d0a47c9afbc15

class BaseClass:
    attr: ClassVar[Optional[Callable]] = None

class ChildClass2(BaseClass):
    @staticmethod
    def attr(s: str):
        pass

Expected Behavior

Mypy shouldn't return any errors.

Additionally, the same should happen when Callable is also typed itself, e.g. Callable[[str], None]. Right now both fail when they shouldn't.

Actual Behavior

test.py:10: error: Signature of "attr" incompatible with supertype "BaseClass"  [override]

Your Environment

Additional information

Interestingly, if the callable doesn't have any arguments, mypy doesn't fail:

class BaseClass:
    attr: ClassVar[Optional[Callable]] = None

class ChildClass2(BaseClass):
    @staticmethod
    def attr():
        pass
erictraut commented 1 year ago

I think mypy's behavior here is correct (at least for the top code sample) because attr will be treated as an instance method in the base class, but it's overridden as a static method in the child class. It's proper and useful for mypy to flag those as incompatible.

That doesn't explain why the error disappears in your second code sample. That looks like a bug (a false negative). Pyright flags both of these code samples as incompatible overrides.