Skip to content

Commit 609b8aa

Browse files
committed
enum: Add graceful error handling for auto() without __prepare__.
Previously, using auto() when MICROPY_PY_METACLASS_PREPARE was disabled would silently create broken enum members with auto() objects as values instead of integers. Changes: - Improved __prepare__ detection to actually test if it's called (not just check if running on MicroPython) - Added clear error message when auto() is used without __prepare__ support, guiding users to either enable the feature or use explicit values - All other enum features (Enum, IntEnum, Flag, IntFlag, StrEnum, @unique) continue to work correctly without any C features The error provides actionable guidance: "auto() in enum Status.PENDING requires MICROPY_PY_METACLASS_PREPARE to be enabled in py/mpconfig.h. Either enable this feature, or use explicit integer values instead of auto()." This prevents silent failures and provides better user experience on minimal builds. Signed-off-by: Andrew Leech <[email protected]>
1 parent 1fb5654 commit 609b8aa

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

lib/enum/enum.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,29 @@
1010
comparison operations work correctly.
1111
"""
1212

13-
try:
14-
# Check if __prepare__ is supported
15-
import sys
16-
_prepare_supported = hasattr(type, '__prepare__') or sys.implementation.name == 'micropython'
17-
except:
18-
_prepare_supported = False
13+
def _check_prepare_support():
14+
"""
15+
Check if __prepare__ metaclass method is actually functional.
16+
Returns True only if __prepare__ is called during class creation.
17+
"""
18+
try:
19+
class _TestMeta(type):
20+
_prepare_called = False
21+
22+
@classmethod
23+
def __prepare__(mcs, name, bases):
24+
_TestMeta._prepare_called = True
25+
return {}
26+
27+
class _Test(metaclass=_TestMeta):
28+
pass
29+
30+
return _TestMeta._prepare_called
31+
except:
32+
return False
33+
34+
35+
_prepare_supported = _check_prepare_support()
1936

2037

2138
# Global counter for auto() to track creation order
@@ -120,6 +137,15 @@ def __new__(mcs, name, bases, namespace):
120137
for key, value in auto_members:
121138
namespace[key] = auto_value
122139
auto_value += 1
140+
else:
141+
# __prepare__ not supported - check if auto() was used
142+
for key, value in namespace.items():
143+
if not key.startswith("_") and isinstance(value, auto):
144+
raise RuntimeError(
145+
f"auto() in enum {name}.{key} requires MICROPY_PY_METACLASS_PREPARE "
146+
f"to be enabled in py/mpconfig.h. Either enable this feature, or use "
147+
f"explicit integer values instead of auto()."
148+
)
123149

124150
# Extract enum members (non-callable, non-dunder attributes)
125151
member_names = []

0 commit comments

Comments
 (0)