Bug Report
If you declare an attribute on a dataclass to be Callable, Mypy assumes that its __get__ will not be called, even on a default attribute. But this is only true if the default is a FunctionType, not some other type of callable.
Similarly, the inverse is true: an abstract type (such as a callable Protocol) will tell mypy that __get__ will be called, even though if the concrete default value is a FunctionType, it won't be.
Specifically, the following program contains 2 type errors, but MyPy does not think so:
To Reproduce
from __future__ import annotations
from typing import Callable, Protocol, ParamSpec, TypeVar, Generic
from dataclasses import dataclass
def f() -> None:
print("hello world")
def f2(self: object) -> None:
print("bound self", self)
P = ParamSpec("P")
T = TypeVar("T")
R = TypeVar("R", covariant=True)
T_con = TypeVar("T_con", contravariant=True)
class BindableMethod(Protocol[T_con, R]):
def __get__(self, instance: T_con, owner: None | type[object]) -> Callable[[], R]:
...
def __call__(me, self: T_con) -> R:
...
class UnboundNonFunction(Generic[P, R]):
def __call__(self) -> int:
print("unbound")
return 3
def __get__(self, instance: object, owner: type | None) -> BoundNonFunction:
print("binding", instance, owner)
return BoundNonFunction(instance)
@dataclass(frozen=True)
class BoundNonFunction:
instance: object
def __call__(self) -> str:
print("bound", self.instance)
return "wat"
@dataclass
class FuncHolder():
func: Callable[[], None] = f
func2: BindableMethod[FuncHolder, None] = f2
func3: Callable[[], int] = UnboundNonFunction()
FuncHolder().func()
try:
FuncHolder().func2()
except Exception as e:
print("whoops", str(e))
try:
print(FuncHolder().func3() + 4)
except Exception as e:
print("whoops 2", str(e))
https://mypy-play.net/?mypy=latest&python=3.11&gist=1ac4e7c090774489207dfbc737de2d61
Expected Behavior
I would expect runtime and type-time behavior to be consistent here. Specifically I just don't expect __get__ to be called on things with a Callable type.
Actual Behavior
Mypy succeeds, rather than reporting the type errors.
Your Environment
- Mypy version used: mypy 1.1.1 (compiled: yes)
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini (and other config files): none
- Python version used: 3.11.2 (python.org, macOS, aarch64)
Bug Report
If you declare an attribute on a dataclass to be
Callable, Mypy assumes that its__get__will not be called, even on a default attribute. But this is only true if the default is aFunctionType, not some other type of callable.Similarly, the inverse is true: an abstract type (such as a callable
Protocol) will tell mypy that__get__will be called, even though if the concrete default value is aFunctionType, it won't be.Specifically, the following program contains 2 type errors, but MyPy does not think so:
To Reproduce
https://mypy-play.net/?mypy=latest&python=3.11&gist=1ac4e7c090774489207dfbc737de2d61
Expected Behavior
I would expect runtime and type-time behavior to be consistent here. Specifically I just don't expect
__get__to be called on things with aCallabletype.Actual Behavior
Mypy succeeds, rather than reporting the type errors.
Your Environment
mypy.ini(and other config files): none