-
-
Notifications
You must be signed in to change notification settings - Fork 32.9k
Description
Consider the following set of classes:
class Superclass:
def __init_subclass__(cls):
print('Called __init_subclass__')
class Metaclass(type):
def mro(cls):
return [Superclass, cls, object]
class Subclass(metaclass=Metaclass):
pass
Then the creation of the last class should lead to Superclass.__init_subclass__
being called; however, it is not, because it is earlier in the mro than the class itself. Note that issubclass(Subclass, Superclass)
returns True
, so clearly it is a subclass, just a very unusual one.
The method would normally have been called during type.__new__
. However, to avoid looking for and potentially calling an __init_subclass__
method defined by Subclass
itself, currently type.__new__
instead calls super(Subclass, Subclass).__init_subclass__
. This causes it to skip over Superclass
in the mro. (This call to super
also leads to bug #83846.) A possible fix for this would be to avoid calling super
and instead read the whole mro, ignoring Subclass
if it finds it; however, this would require some thought about what happens if Superclass.__init_subclass__
itself calls super
.
It might be argued that the metaclass should not be allowed to create an mro like this, and an error should be raised instead if it does this. This would be an alternative solution, but may not be entirely backward compatible.