diff --git a/tests/cpydiff/core_class_initsubclass.py b/tests/cpydiff/core_class_initsubclass.py new file mode 100644 index 0000000000..8683271dcb --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass.py @@ -0,0 +1,21 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` isn't automatically called. +cause: MicroPython does not currently implement PEP 487. +workaround: Manually call ``__init_subclass__`` after class creation if needed. e.g.:: + + class A(Base): + pass + A.__init_subclass__() + +""" + + +class Base: + @classmethod + def __init_subclass__(cls): + print(f"Base.__init_subclass__({cls.__name__})") + + +class A(Base): + pass diff --git a/tests/cpydiff/core_class_initsubclass_autoclassmethod.py b/tests/cpydiff/core_class_initsubclass_autoclassmethod.py new file mode 100644 index 0000000000..b2f7628976 --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_autoclassmethod.py @@ -0,0 +1,31 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` isn't an implicit classmethod. +cause: MicroPython does not currently implement PEP 487. ``__init_subclass__`` is not currently in the list of special-cased class/static methods. +workaround: Decorate declarations of ``__init_subclass__`` with ``@classmethod``. +""" + + +def regularize_spelling(text, prefix="bound_"): + # for regularizing across the CPython "method" vs MicroPython "bound_method" spelling for the type of a bound classmethod + if text.startswith(prefix): + return text[len(prefix) :] + return text + + +class A: + def __init_subclass__(cls): + pass + + @classmethod + def manual_decorated(cls): + pass + + +a = type(A.__init_subclass__).__name__ +b = type(A.manual_decorated).__name__ + +print(regularize_spelling(a)) +print(regularize_spelling(b)) +if a != b: + print("FAIL") diff --git a/tests/cpydiff/core_class_initsubclass_kwargs.py b/tests/cpydiff/core_class_initsubclass_kwargs.py new file mode 100644 index 0000000000..ed5157afea --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_kwargs.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: MicroPython doesn't support parameterized ``__init_subclass__`` class customization. +cause: MicroPython does not currently implement PEP 487. The MicroPython syntax tree does not include a kwargs node after the class inheritance list. +workaround: Use class variables or another mechanism to specify base-class customizations. +""" + + +class Base: + @classmethod + def __init_subclass__(cls, arg=None, **kwargs): + cls.init_subclass_was_called = True + print(f"Base.__init_subclass__({cls.__name__}, {arg=!r}, {kwargs=!r})") + + +class A(Base, arg="arg"): + pass + + +# Regularize across MicroPython not automatically calling __init_subclass__ either. +if not getattr(A, "init_subclass_was_called", False): + A.__init_subclass__() diff --git a/tests/cpydiff/core_class_initsubclass_super.py b/tests/cpydiff/core_class_initsubclass_super.py new file mode 100644 index 0000000000..d18671a74b --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_super.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` can't be defined a cooperatively-recursive way. +cause: MicroPython does not currently implement PEP 487. The base object type does not have an ``__init_subclass__`` implementation. +workaround: Omit the recursive ``__init_subclass__`` call unless it's known that the grandparent also defines it. +""" + + +class Base: + @classmethod + def __init_subclass__(cls, **kwargs): + cls.init_subclass_was_called = True + super().__init_subclass__(**kwargs) + + +class A(Base): + pass + + +# Regularize across MicroPython not automatically calling __init_subclass__ either. +if not getattr(A, "init_subclass_was_called", False): + A.__init_subclass__()