-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[WIP] PEP 3115 metaclass and PEP 487 __init_subclass__
#18362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Code size report: |
bb681e6 to
d27c14d
Compare
- Support metaclass - Support __init_subclass Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
These have become redundant as PEP 478 is now implemented. Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
d27c14d to
ef37d7c
Compare
Implements the __prepare__ metaclass method which allows metaclasses to customize the namespace dictionary before class body execution. This is required for enum.auto() support and other advanced metaclass patterns. Changes: - py/mpconfig.h: Add MICROPY_PY_METACLASS_PREPARE configuration flag - py/modbuiltins.c: Reorder __build_class__ to call __prepare__ before class body execution - tests/basics/class_metaclass_prepare.py: Add comprehensive tests Size impact: ~152 bytes when enabled (measured on Unix port) Follows the implementation approach from PR micropython#18362. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #18362 +/- ##
==========================================
- Coverage 98.38% 98.35% -0.03%
==========================================
Files 171 171
Lines 22294 22320 +26
==========================================
+ Hits 21933 21953 +20
- Misses 361 367 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
metaclass and PEP 487 __init_subclass__ metaclass and PEP 487 __init_subclass__
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
1e692bf to
cf3e30c
Compare
|
@andrewleech , I need to add some tests for |
This PR aims to adds optional support for two Python features to MicroPython.
metaclass=keyword syntax__init_subclass__automatic hook with full **kwargs supportThe goal of this PR is to discuss if either or both of the PEPs are worth the trade-off of features versus firmware size.
These would enable:
@dataclass_transformdecoratorAll features are intended to be optional, guarded by configuration flags, and designed for minimal code size impact while maintaining near full CPython compatibility.
Modified Files
py/mpconfig.h
MICROPY_METACLASS,MICROPY_METACLASS_PREPARE,MICROPY_INIT_SUBCLASSflagspy/modbuiltins.c
__build_class__to accept keyword arguments__prepare__method support__init_subclass__py/objtype.c
mp_obj_new_typeto accept metaclass and kw_args parameters__init_subclass__invocation logic (PEP 487)py/vm.c
py/runtime.c
Code Size Impact (Unix standard variant)
Comprehensive measurements across all configuration permutations:
⭐ Recommended configuration for dataclass_transform support
Features by Configuration
Details
Configuration 1: METACLASS Only (+672 bytes)
Features:
class C(metaclass=Meta):syntax__init__customization__prepare__method__init_subclass__supportUse Case: Applications that need custom metaclasses but not dataclass patterns.
Configuration 2: METACLASS + PREPARE (800 bytes)
Additional Features:
__prepare__method support for custom namespace initializationUse Case: Full PEP 3115 compliance (rare requirement in embedded systems).
Configuration 3: INIT_SUBCLASS Only (728 bytes)
Features:
__init_subclass__invocationsuper()chainingmetaclass=keyword syntaxUse Case: Applications needing dataclass_transform but not explicit metaclasses. BEST SIZE/FUNCTIONALITY RATIO for dataclasses.
Configuration 4: METACLASS + INIT_SUBCLASS (+1,152 bytes) ⭐
Features:
__prepare__(rarely needed)Use Case: RECOMMENDED - Full modern Python class features for dataclasses and type systems.
Configuration 5: All Features (+1,248 bytes)
Features:
Use Case: Maximum compatibility, when code size is less critical.
Trade-Off Analysis
Size contributions
Sizes measured on unix standard build using mpbuild :
Size Savings Options
metaclass=syntax, keeps dataclass supportAlternatives:
Several additional optimization strategies were explored:
Remove kwargs support from init_subclass
Simplify metaclass resolution
Stack-based allocation
Additional granular flags
Code Sharing Benefits
The current implementation benefits from significant code sharing:
Configuration Recommendations
Details
Embedded/Resource-Constrained (+728 bytes)
Configuration 3: INIT_SUBCLASS Only
Rationale:
Enables modern dataclass patterns with minimal overhead
Best size-to-functionality ratio
Most embedded applications don't need explicit metaclass syntax
User Defined Generics not possible without METACLASS.
General Purpose (+1,152 bytes)
Configuration 4: METACLASS + INIT_SUBCLASS ⭐
Rationale:
Maximum Compatibility (+1,248 bytes)
Configuration 5: All Features
Rationale:
Minimal (Baseline, +0 bytes)
Configuration: All Disabled (Default)
Rationale:
Usage Examples
Details
Example 1: Metaclass (Requires MICROPY_METACLASS=1)
Example 2: dataclass_transform Pattern (Requires MICROPY_INIT_SUBCLASS=1)
Example 3: Plugin Registry (Requires MICROPY_INIT_SUBCLASS=1)
Example 4: Multiple Inheritance with Chaining (Requires MICROPY_INIT_SUBCLASS=1)
Testing
__prepare__limitationAll tests gracefully skip when features are disabled.
Compatibility
Recommended Adoption Strategy
Technical Notes
PEP 487 Compliance Notes
__init_subclass__is implicitly a classmethod (no decorator needed)__init_subclass__is called (per MRO)super().__init_subclass__(**kwargs)callmetaclass=PEP 3115 Compliance Notes
metaclass=keyword syntax fully supported__prepare__method optional (controlled by separate flag)Known Limitations (by design)
When MICROPY_METACLASS_PREPARE=0:
__prepare__method not calledDecorator behavior:
@classmethodon__init_subclass__not supportedPerformance Impact
Performance Impact Analysis
Runtime performance impact of PEP 3115 (METACLASS) and PEP 487 (INIT_SUBCLASS) features.
Test Platform
Performance Results
Details
All measurements in microseconds (µs). Percentages show runtime change vs baseline.
Analysis
Class Creation Overhead
The overhead is expected as the implementation must check for metaclass resolution and invoke
__init_subclass__hooks during class creation.Inheritance Performance
Method Calls & Attribute Access
Important: These improvements are within measurement noise and should not be considered a performance benefit. The key finding is that method calls and attribute access show no significant performance degradation.
Summary
Performance Impact
Negligible runtime overhead for typical operations
Key Findings
Recommendations
Performance Test Descriptions