Add exception to descriptor protocol for MethodType().__func__. - #3484
Add exception to descriptor protocol for MethodType().__func__.#3484carljm wants to merge 1 commit into
Conversation
e4e3b7a to
4a38240
Compare
|
This fix feels grossly specific and special-case-y, but I've so far not found a more general approach. I guess the ideal might be some way to annotate an attribute in a stub file as "does not respect the descriptor protocol". Very open to suggestions of better / more general ways to fix this. |
|
I guess the descriptor protocol is invoked by the class' I'm still reluctant to admit such a blatant custom exception. Where did this cause a problem for you? Was there just one instance or are there a whole bunch? |
|
I share your aversion to this special case. We only ran into this once, in introspection code. It certainly is no problem to just cast in that case (it's what we're doing now). It just seemed that since a) mypy is clearly inferring the wrong type and b) it's fixable, it might still be preferable to have an ugly fix than continue to be wrong. There are probably other cases of types implemented in C that bypass Does python/typeshed#1383 feel any better? It's not exactly beautiful, but at least it keeps the workaround in typeshed, with the specific type that has the issue, rather than as a special case in mypy. |
|
Yeah, I am inclined to accept the hackery in typeshed, so closing this one. |
See python/mypy#3484 for background.
types.FunctionTypeis annotated as a descriptor returningtypes.MethodType. In general, this is correct: if you access aFunctionTypeas an attribute of some instance, you get back aMethodType.But
MethodTypehas an attribute__func__, which is aFunctionType. And this attribute does not obey the descriptor protocol; it really does give you aFunctionType, not aMethodType.(I think in general
MethodType, as a type implemented in C, doesn't obey the descriptor protocol: e.g. this is true of its__self__attribute too, even if the self-object of a method is a descriptor, if you accessmymethod.__self__you get the object, not the return value of its__get__method. But__self__does not currently require special-casing here, because mypy just considers it to be of typeobject, which isn't a descriptor; mypy doesn't track the type of the actual__self__of a given method.)This pull request fixes mypy's type inference so it knows that
mymethod.__func__is aFunctionType, not aMethodType.