-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix type object signature when both __new__ and __init__ present #5642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Currently mypy will prefer __init__ to __new__ for determining the signature of a type object if there exists any __init__ other than object's. Instead, prefer the closest definition in the MRO, so that subclass __new__ can override parent __init__. Fixes #1435.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that only the first example fails in CPython -- the others are OK.
The rule CPython uses is this (for a class C with superclass B, where B is not object):
- If both
C.__new__andC.__init__refer to their versions inobject, the signature isdef () -> C. - If exactly one of
C.__new__andC.__object__refers to itsobjectversion, the other determines the signature. - If both override their corresponding
objectversions, they must match -- even if they don't come from the same class (say, if one comes fromCand the other fromB).
| def __new__(cls) -> 'B': | ||
| ... | ||
|
|
||
| B() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But at runtime in CPython this is an error:
$ Traceback (most recent call last):
File "_.py", line 9, in <module>
b = B()
TypeError: __init__() missing 1 required positional argument: 'x'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, hm:
The original bug example had the __new__ call return an int, which works because __init__ isn't called if it isn't a subclass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's merge this and open a new issue for the remaining nits:
- should prefer
__new__over__init__ - should check
__new__against__init__(using the full rules I specified)
Fixes python#5647 See also python#5642
Fixes python#5647 See also python#5642
Fixes python#5647 See also python#5642
Fixes python#5647 See also python#5642
Currently mypy will prefer
__init__to__new__for determiningthe signature of a type object if there exists any
__init__other than object's.
Instead, prefer the closest definition in the MRO, so that
subclass
__new__can override parent__init__.Fixes #1435.