metaclass
I see that MP does not (yet) support metaclasses (per item #6 on https://github.com/micropython/micropython/wiki/Differences#differences-by-design). It sounds like the MP developers would like to add this feature some day, but it's not clear to me how strongly they feel about that.
Obviously, people do not directly make use of this feature very often. Nevertheless, it is very powerful, and people DO benefit from libraries that do use it directly. I am working on a library that works in CPython, but because it hinges on a metaclass, I was disappointed to find that it doesn't work on MP.
My hopes in posting this are to
a) Solicit the thoughts of the MP developers on where this feature lies in their priority queue.
b) Let others provide "me too!" feedback.
c) Vent my frustration.
PS: Thank you for MP! Being able to use (u)asyncio is truly a godsend.
py/objtype: Add basic __init_subclass__ metaclass support.
Summary
This PR adds partial support for the __init_subclass__ data model method defined in PEP487, and gates this added features behind a new feature flag, MICROPY_PY_METACLASSES.
While this PR does not implement "full" metaclasses, it does implement the main mechanism used in practice for most types of meta-class-like class customization.
The behavior implemented here varies from the CPython behavior for two reasons:
- Due to #15509, user-written
__init_subclass__implementations are not able to recursively callsuper().__init_subclass__()the way PEP487 specifies. Therefore, this implementation applies a workaround: instead of invoking__init_subclass__only for the last base class, it invokes it on all direct base classes. - Micropython does not support passing kwargs as bases of a class, therefore
__init_subclass__currently has no kwargs functionality.
This PR uses #15503 as its base to ensure the __init_subclass__ code remains in the correct order with __set_name__ in order to match CPython. It also adds MICROPY_PY_METACLASSES as an alternative condition for enabling #15503's functionality, for the rare cases of metaclass code that relies on __set_name__ class customization but doesn't need the per-lookup overhead of descriptors.
Testing
This PR includes a test verifying this feature, and three cpydiff's precisely outlining the mismatch with CPython. I've also manually verified the functionality using the unix port.
Trade-offs and Alternatives
This increases code size, but only when the corresponding feature flag is enabled.