You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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)
The text was updated successfully, but these errors were encountered:
/home/classic/dev/sqlalchemy/test3.py
/home/classic/dev/sqlalchemy/test3.py:21:18 - warning: Instance methods should take a "self" parameter (reportSelfClsParameterName)
It's not that dataclasses discern between "Callable" and "FunctionType", it's just that anything that quacks like a descriptor triggers the behavior described here.
Note the __get__ is only called a couple times, with instance=None, meaning that it's not useful to e.g. bind a method to an instance. Maybe what you're hoping to do isn't even possible?
It looks to me like accidental behavior that got documented, given how it's a mere side-effect of how the default is represented (as a class variable's value), and how changing from Python syntax = d to = field(default=d) eliminates this behavior:
class Descriptor:
def __get__(self, instance, owner):
return 42
d = Descriptor()
@dataclass
class C:
- desc: Descriptor = d+ desc: Descriptor = field(default=d)
c = C()
-assert c.desc == 42+assert isinstance(c.desc, Descriptor)
Right now the plugin does not checks for field's type vs. default's type — it kinda happens on it own (due to typeshed annotations), thought it might be doable.
But is it even worthwhile to replicate given how odd and accidental this feature seems?
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 aCallable
type.Actual Behavior
Mypy succeeds, rather than reporting the type errors.
Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: