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
{{ message }}
Repository navigation
Mypy is expecting type[Never] in context when it shouldn't #18968
I have written (well, copied, from here) a class classproperty to handle implementing class properties. It works perfectly fine, however when I try and type it as follows (which I think is valid), mypy raises the below error
I don't think this is correct, based on my understanding of descriptors and __get__. I asked a question on stackoverflow about this and it was suggested that this is caused by incorrect assumptions about how __get__ is called
Never there is mypy telling you "I don't know what to put here!"
In this case, I think it's because mypy thinks my_property is a method, so the cls attribute is annotated as taking Test, which isn't a type[...], so there's nothing mypy can put in the type that makes things pass.
I guess mypy could guess the first argument's type based on __get__ and decorators but that seems... a bit tough to generalize. For now you could use def my_property(cls: type[Test]): instead. nevermind, this doesn't work. I guess this stuff is more hardcoded than you would like, e.g. detecting specifically @classmethod.
mypy looks specifically for builtins.classmethod and builtins.staticmethod to identify binding target for the first argument of a method - instance, class or no binding at all.
Your decorator is a descriptor, yes, but it doesn't mean it takes a classmethod in - there's no such decorator below it, right? For a static analyzer, you take something that looks like an instance method and wrap it with some decorator, returning a descriptor. Solving this for a general case sounds borderline impossible - you can only tell whether the instance is actually used by looking at __get__ body. There's no simple "rule of thumb" to identify classmethod-like descriptors.
There's a trivial approach to this problem (~50 LOC + tests, I believe) - we could introduce --extra-classmethod-decorator-fullnames (and perhaps --extra-staticmethod-decorator-fullnames for symmetry) flags that would simply be treated exactly like @classmethod and @staticmethod, resp. (shorter name ideas are welcome!). Would this solve your problem? It works for third-party code as well, even though consumers will have to copy those flags to all dependent configs.
One alternative approach is providing a {class,static}method_like decorator resembling @dataclass_transform, but that would be more complicated - we need to recognise class and static methods early during semanal phase.
hey @sterliakov, thanks for the reply. the flags sound cool, though i'm not sure i understand their usage? you would pass them in your config (or as a cli arg) and they would change how these methods are analysed? or you would pass them alongside the relevant lines of code somehow? thanks :)
Yes, I mean config/CLI flags, so that invoking mypy --extra-classmethod-decorator-fullnames yourlib.classproperty would make your code work (the decorated method will be treated as classmethod).
Activity
A5rocks commentedon Apr 25, 2025
Neverthere is mypy telling you "I don't know what to put here!"In this case, I think it's because mypy thinks
my_propertyis a method, so theclsattribute is annotated as takingTest, which isn't atype[...], so there's nothing mypy can put in thetypethat makes things pass.I guess mypy could guess the first argument's type based on
__get__and decorators but that seems... a bit tough to generalize.For now you could usenevermind, this doesn't work. I guess this stuff is more hardcoded than you would like, e.g. detecting specificallydef my_property(cls: type[Test]):instead.@classmethod.sterliakov commentedon Apr 25, 2025
mypylooks specifically forbuiltins.classmethodandbuiltins.staticmethodto identify binding target for the first argument of a method - instance, class or no binding at all.Your decorator is a descriptor, yes, but it doesn't mean it takes a
classmethodin - there's no such decorator below it, right? For a static analyzer, you take something that looks like an instance method and wrap it with some decorator, returning a descriptor. Solving this for a general case sounds borderline impossible - you can only tell whether the instance is actually used by looking at__get__body. There's no simple "rule of thumb" to identify classmethod-like descriptors.There's a trivial approach to this problem (~50 LOC + tests, I believe) - we could introduce
--extra-classmethod-decorator-fullnames(and perhaps--extra-staticmethod-decorator-fullnamesfor symmetry) flags that would simply be treated exactly like@classmethodand@staticmethod, resp. (shorter name ideas are welcome!). Would this solve your problem? It works for third-party code as well, even though consumers will have to copy those flags to all dependent configs.One alternative approach is providing a
{class,static}method_likedecorator resembling@dataclass_transform, but that would be more complicated - we need to recognise class and static methods early during semanal phase.aidangallagher4 commentedon Apr 26, 2025
hey @sterliakov, thanks for the reply. the flags sound cool, though i'm not sure i understand their usage? you would pass them in your config (or as a cli arg) and they would change how these methods are analysed? or you would pass them alongside the relevant lines of code somehow? thanks :)
sterliakov commentedon Apr 26, 2025
Yes, I mean config/CLI flags, so that invoking
mypy --extra-classmethod-decorator-fullnames yourlib.classpropertywould make your code work (the decorated method will be treated as classmethod).A5rocks commentedon Apr 27, 2025
Could we maybe infer the
selftype from the type in the decorator signature? Is there a reason that doesn't work?(Is that information too late to use? Or some gotcha...)
aidangallagher4 commentedon Apr 28, 2025
hey @sterliakov -- that sounds good to me!
Move self argument checks to a later phase - after decorator applicat…