← index #269PR #18416
Likely Duplicate · high · value 5.194
QUERY · ISSUE

Request for package: micropython-enum

openby desowinopened 2018-04-04updated 2025-03-05
enhancement

I would like micropython to have support for IntEnum class. Base Enum would be nice to have, although just bare IntEnum would be enough in my opinion.

11 comments
stlehmann · 2018-04-04

Enums are especially useful when it comes to static type-checking. So it would be great if the implementation of this enum type allowed type-checking via mypy. This means all values need to be an instance of the defined enum-type.

>>> class MyEnum(enum.IntEnum):
...    A = 1
...    B = 2

>>> isinstance(MyEnum.A, MyEnum)
True
lypwig · 2022-02-20

I'm also interested by enum in MicroPython.

In the meantime, I found here this workaround:

def enum(**enums: int):
    return type('Enum', (), enums)

Number = enum(ONE=1, TWO=2, THREE=3)

numbers = (Number.ONE, Number.TWO)
matejcik · 2022-02-20

for type-checking, I'm using the following trick:

if TYPE_CHECKING:
    from enum import IntEnum
else:
    IntEnum = object

class Fruit(IntEnum):
    APPLE = 1
    PEAR = 2

def print_fruit(fruit: Fruit):
    if fruit == Fruit.APPLE:
         print("apple")

print_fruit(Fruit.APPLE)
brotherdust · 2022-10-14

This workaround is excellent! I combined it with const for my purposes:

OP_RW = enum(
        READ = const(0b1),
        WRITE = const(0b1)
    )
esologic · 2022-12-11

+1 for a real implementation of this

i33l · 2023-05-26
class State(int):
    pass

State.OFF = State(0)
State.ON = State(1)

But when have been imported getting "Unresolved attribute reference" warning.

andrewleech · 2023-05-26

+1 for a real implementation of this

The cpython implementation is surprisingly very complicated and relies heavily on metaclasses which aren't supported in micropython:

https://github.com/python/cpython/blob/f585ed19ad00f78ed99ba44be5e333c056076160/Lib/enum.py#L1051

As such any micropython implementation will need to be completely custom really, at which point we need to clearly define which aspects of Enum we want to support first, before figuring out how to implement them!

andrewleech · 2023-05-26
class State(int):
    pass

State.OFF = State(0)
State.ON = State(1)

But when have been imported getting "Unresolved attribute reference" warning.

There are a number of limitations when subclassing builtins in micropython, especially int because behind the scenes it's particularly optimised. Eg. https://docs.micropython.org/en/latest/genrst/builtin_types.html#no-int-conversion-for-int-derived-types-available

bredbord · 2024-03-07

+1 for an implementation of this as well.

CANDIDATE · PULL REQUEST

py: Add enum support and minimal metaclass features

openby andrewleechopened 2025-11-14updated 2025-12-12
py-core

Summary

Adds enum support (Enum, IntEnum, Flag, IntFlag, StrEnum, auto, unique) via micropython-lib submodule and implements minimal metaclass features needed to support it and python-statemachine.

Built on dpgeorge's b31c1de89a metaclass branch from 2020. Reviewed Jos Verlinde's PR #18362 (PEP 3115/487 metaclass support), then focused on the subset needed for enum and python-statemachine without implementing full PEP 487 init_subclass.

Metaclass Features

Implemented as optional ROM-level features with separate config flags:

Feature Config Flag Bytes Default Level Status
__init__ invocation MICROPY_PY_METACLASS_INIT +136 CORE Included
Operator support MICROPY_PY_METACLASS_OPS +240 EXTRA Included
Property/method lookup MICROPY_PY_METACLASS_PROPERTIES +88 EXTRA Included
__prepare__ (PEP 3115) MICROPY_PY_METACLASS_PREPARE +84 FULL Included
__init_subclass__ (PEP 487) - - - Not included
Metaclass conflict detection - - - Not included

Total C overhead: 540 bytes when all features enabled (FULL level).

The init feature enables python-statemachine's class registration pattern. Properties enable accessing .events and .states on the class. Operators enable len(EnumClass) and member in EnumClass. prepare enables enum's auto() value generation.

Enum Features

Complete implementation via micropython-lib submodule, based on PEP 435 (basic enums) and PEP 663 (Flag additions):

  • Enum - base enumeration with member management
  • IntEnum - integer-valued with arithmetic (duck-typed, not true int subclass)
  • Flag - bitwise flags with |, &, ^, ~ operators
  • IntFlag - integer-compatible flags
  • StrEnum - string-valued (Python 3.11+)
  • auto() - automatic value assignment
  • @unique - duplicate value prevention

Frozen as bytecode: ~5,428 bytes.

Modular structure with lazy loading:

  • core.py - Enum, IntEnum, EnumMeta (~1.5KB frozen)
  • flags.py - Flag, IntFlag (~500 bytes frozen, loaded on demand)
  • extras.py - StrEnum, auto, unique (~450 bytes frozen, loaded on demand)

Total implementation: 540 bytes C + 5,428 bytes Python = 5,968 bytes (1.6% increase on STM32 PYBV10).

CPython Compatibility

Tested against CPython 3.13's official enum test suite:

  • 448 tests run
  • 445 passed (99.3%)
  • 3 failed (Flag combination membership edge case, now fixed)

Works:

  • All class-based enum definitions
  • auto() value generation
  • Explicit and mixed values
  • Iteration, lookup, comparison, repr
  • Flag bitwise operations
  • @unique decorator
  • Type mixins (int, str, float, date)
  • Pickling/unpickling
  • members, dir(), introspection
  • Thread-safe enum creation

Not implemented:

  • Functional API (Enum('Name', 'A B C')) - use class syntax instead
  • missing(), ignore(), generate_next_value() hooks
  • Boundary modes (STRICT, CONFORM, EJECT, KEEP)

Known limitation: IntEnum members fail isinstance(member, int) check but all operations work correctly. Documented in tests/cpydiff/types_enum_isinstance.py.

STM32 Size Measurements (PYBV10)

Individual feature costs:

Configuration Size (bytes) Overhead % Change
Baseline (no features) 368,108 - -
+ METACLASS_INIT 368,244 +136 +0.037%
+ METACLASS_OPS 368,348 +240 +0.065%
+ METACLASS_PROPERTIES 368,196 +88 +0.024%
+ METACLASS_PREPARE 368,192 +84 +0.023%

Cumulative by ROM level:

ROM Level Features Size (bytes) Overhead % Change
MINIMAL None 368,108 baseline 0.000%
CORE INIT 368,244 +136 +0.037%
EXTRA INIT+OPS+PROPERTIES 368,572 +464 +0.126%
FULL All metaclass 368,648 +540 +0.147%

With enum module frozen:

Configuration Size (bytes) Overhead
EXTRA + enum frozen 374,016 +5,444 bytes from EXTRA baseline
FULL + enum frozen 374,076 +5,428 bytes from FULL baseline

Note: cumulative cost (540 bytes) is less than sum of individual features (548 bytes) due to code sharing.

Testing

Unix port coverage variant:

  • 1053 tests passed
  • 22 tests skipped
  • 2 pre-existing failures unrelated to these changes (extmod/select_poll_fd.py, misc/sys_settrace_features.py)

Tests added:

  • tests/basics/enum_auto.py - auto() value generation
  • tests/basics/enum_flag.py - Flag and IntFlag operations
  • tests/basics/enum_strenum.py - StrEnum functionality
  • tests/basics/class_metaclass_init.py - metaclass init
  • tests/basics/class_metaclass_prepare.py - prepare support
  • tests/basics/class_metaclass_property.py - property lookup
  • tests/cpydiff/types_enum_isinstance.py - documents IntEnum limitation

Tests fixed:

  • tests/basics/metaclass.py - now passes with new .exp file (was failing before due to missing init support)

Implementation Details

Core C files modified:

  • py/mpconfig.h - ROM level config flags
  • py/objtype.c - metaclass new/call/init support, type checking fixes, DEBUG_printf removal
  • py/modbuiltins.c - prepare integration in build_class
  • py/objobject.c - object.new custom metaclass support
  • py/vm.c - LOAD_ATTR fast path fix for type objects

Enum module:

  • lib/micropython-lib - submodule updated to include enum package
  • ports/unix/variants/standard/manifest.py - require("enum")
  • ports/unix/variants/coverage/manifest.py - require("enum")

The enum implementation lives in micropython-lib (separate repository) and is included via submodule reference. Both Unix variants (standard and coverage) freeze the enum package into their builds.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied