New submission from Ethan Furman <et...@stoneleaf.us>:
PEP 487 introduced __init_subclass__ and __set_name__, and both of those were wins for the common cases of metaclass usage. Unfortunately, the implementation of PEP 487 with regards to __init_subclass__ has made the writing of correct metaclasses significantly harder, if not impossible. The cause is that when a metaclass calls type.__new__ to actually create the class, type.__new__ calls the __init_subclass__ methods of the new class' parents, passing it the newly created, but incomplete, class. In code: ``` class Meta(type): # def __new__(mcls, name, bases, namespace, **kwds): # create new class, which will call __init_subclass__ and __set_name__ new_class = type.__new__(mcls, name, bases, namespace, **kwds) # finish setting up class new_class.some_attr = 9 ``` As you can deduce, when the parent __init_subclass__ is called with the new class, `some_attr` has not been added yet -- the new class is incomplete. For Enum, this means that __init_subclass__ doesn't have access to the new Enum's members (they haven't beet added yet). For ABC, this means that __init_subclass__ doesn't have access to __abstract_methods__ (it hasn't been created yet). Because Enum is pure Python code I was able to work around it: - remove new __init_subclass__ (if it exists) - insert dummy class with a no-op __init_subclass__ - call type.__new__ - save any actual __init_subclass__ - add back any new __init_subclass__ - rewrite the new class' __bases__, removing the no-op dummy class - finish creating the class - call the parent __init_subclass__ with the now complete Enum class I have not been able to work around the problem for ABC. The solution would seem to be to move the calls to __init_subclass__ and __set_names__ to type.__init__. ---------- assignee: ethan.furman components: Interpreter Core messages: 383946 nosy: ethan.furman, serhiy.storchaka priority: high severity: normal stage: needs patch status: open title: __init_subclass__ should be called in __init__ type: behavior versions: Python 3.10 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue42775> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com