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
The target of an invocation of __new__ is an explicit class, but mypy erroneously believes it is another class.
To Reproduce
Create a file test.py with this content:
from typing import Any
class C(str):
def __new__(cls, value: str) -> Any:
return str.__new__(cls, value)
Then run mypy test.py
Side note # 1: this is a stripped down version to reproduce the issue, the original case has more real interest.
Side note # 2: __new__ should return C but the name C is not defined during class creation, so __new__ is declared to return Any, instead.
Expected Behavior
There should be no error, as one can check this way:
>>> import test
>>> s = test.C("abc")
# No exception raised
>>> type(s)
<class 'test.C'>
Actual Behavior
mypy complains:
test.py:4: error: Too many arguments for "__new__" of "object"
Found 1 error in 1 file (checked 1 source file)
It erroneously believes the target of __new__ is object while it is str
Your Environment
Mypy version used: mypy 0.782
Mypy command-line flags: none (just the file name)
Mypy configuration options from mypy.ini (and other config files): none (no config file)
I think this could actually be fixed in typeshed -- the problem seems to be that no __new__ method is declared for class str.
But another interpretation would be that we ought to automatically derive a signature for __new__ if one is given for __init__. That would not be a simple feature to add, and I suspect there's already some other issue open for it. (Maybe #5647 is related?)
I’m not good at Python insides, anyway, my understanding is that the two issues are not that much related. The other issue as I understand it, is about __new__ vs __init__ to infer the type returned by a class constructor (I agree __new__ is the reference for that).
Indeed, no __new__ is defined. But I was believing the arguments to __new__ and __init__, except for cls and self, are typically the same. If I’m not too wrong, when no __new__ is defined, what about relying on __init__ to infer its expected arguments? In that case, __new__(cls, o: object) could be inferred and would match the invocation.
That said, I wonder if the error is finally in typeshed: I believe that’s a __new__ which should be declared for str, not an __init__ (and if so, probably the same for others like int, float, bool). There seems to be no __init__ for str.
We tried this before in python/typeshed#1352 and terrible things happened (see python/typeshed#1464). Perhaps the enum issue I found back then got solved some other way since then, though.
Activity
[-]Wrong inference of the type of the target of `__new__`[/-][+]Wrong inference of the target of `__new__`[/+]gvanrossum commentedon Sep 3, 2020
I think this could actually be fixed in typeshed -- the problem seems to be that no
__new__method is declared for classstr.But another interpretation would be that we ought to automatically derive a signature for
__new__if one is given for__init__. That would not be a simple feature to add, and I suspect there's already some other issue open for it. (Maybe #5647 is related?)Hibou57 commentedon Sep 3, 2020
I’m not good at Python insides, anyway, my understanding is that the two issues are not that much related. The other issue as I understand it, is about
__new__vs__init__to infer the type returned by a class constructor (I agree__new__is the reference for that).I did not knew about typeshed, so just had a look: https://github.com/python/typeshed/blob/master/stdlib/2and3/builtins.pyi#L443
Indeed, no
__new__is defined. But I was believing the arguments to__new__and__init__, except forclsandself, are typically the same. If I’m not too wrong, when no__new__is defined, what about relying on__init__to infer its expected arguments? In that case,__new__(cls, o: object)could be inferred and would match the invocation.Hibou57 commentedon Sep 6, 2020
That said, I wonder if the error is finally in typeshed: I believe that’s a
__new__which should be declared forstr, not an__init__(and if so, probably the same for others likeint,float,bool). There seems to be no__init__forstr.gvanrossum commentedon Sep 6, 2020
JelleZijlstra commentedon Sep 6, 2020
We tried this before in python/typeshed#1352 and terrible things happened (see python/typeshed#1464). Perhaps the enum issue I found back then got solved some other way since then, though.
AlexWaygood commentedon Mar 25, 2022
Cannot be reproduced on mypy 0.800+