-
-
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 itsobject
version, the other determines the signature. - If both override their corresponding
object
versions, they must match -- even if they don't come from the same class (say, if one comes fromC
and the other fromB
).
test-data/unit/check-classes.test
Outdated
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.