Skip to content

__init_subclass__ not handled correctly for classes with unusual mros #105038

@plokmijnuhby

Description

@plokmijnuhby

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions