python / mypy

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

classmethod decorator transforms callable into callable rather than producing a classmethod? #12673

Open NeilGirdhar opened 2 years ago

NeilGirdhar commented 2 years ago

At the point at which the decorator is applied, the class method isn't a callable yet. It's a classmethod object that replies to __get__ to produce the bound method. Yet, MyPy already thinks it's a callable:

from __future__ import annotations
from typing import Callable

def decorate(c: classmethod[None]) -> Callable[[X], None]:
    def g(x: X) -> None:
        return c.__func__(type(x))
    return g

class X:
    @decorate  # error: Argument 1 to "decorate" has incompatible type "Callable[[Type[X]], None]"; expected "classmethod[None]"
    @classmethod
    def f(cls) -> None:
        print("okay")

x = X()
x.f()  # error: Invalid self argument "Type[X]" to class attribute function "f" with type "Callable[[X], None]"
NeilGirdhar commented 2 years ago

Pyright won't fix the first problem, so I can just ignore it. But is the second problem fixable? The decorator changes the class method into an ordinary method, so why is x.f() passing the type?

NeilGirdhar commented 1 year ago

This would be solved by https://github.com/python/typing/issues/1372