How to extend Python Enum? How to extend Python Enum? python python

How to extend Python Enum?


Subclassing an enumeration is allowed only if the enumeration does not define any members.

Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances.

https://docs.python.org/3/library/enum.html#restricted-enum-subclassing

So no, it's not directly possible.


While uncommon, it is sometimes useful to create an enum from many modules. The aenum1 library supports this with an extend_enum function:

from aenum import Enum, extend_enumclass Index(Enum):    DeviceType    = 0x1000    ErrorRegister = 0x1001for name, value in (        ('ControlWord', 0x6040),        ('StatusWord', 0x6041),        ('OperationMode', 0x6060),        ):    extend_enum(Index, name, value)assert len(Index) == 5assert list(Index) == [Index.DeviceType, Index.ErrorRegister, Index.ControlWord, Index.StatusWord, Index.OperationMode]assert Index.DeviceType.value == 0x1000assert Index.StatusWord.value == 0x6041

1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.


Calling the Enum class directly and making use of chain allows the extension (joining) of an existing enum.

I came upon the problem of extending enums while working on a CANopen implementation. Parameter indices in the range from 0x1000 to 0x2000 are generic to all CANopen nodes while e.g. the range from 0x6000 onwards depends open whether the node is a drive, io-module, etc.

nodes.py:

from enum import IntEnumclass IndexGeneric(IntEnum):    """ This enum holds the index value of genric object entrys    """    DeviceType    = 0x1000    ErrorRegister = 0x1001Idx = IndexGeneric

drives.py:

from itertools import chainfrom enum import IntEnumfrom nodes import IndexGenericclass IndexDrives(IntEnum):    """ This enum holds the index value of drive object entrys    """    ControlWord   = 0x6040    StatusWord    = 0x6041    OperationMode = 0x6060Idx= IntEnum('Idx', [(i.name, i.value) for i in chain(IndexGeneric,IndexDrives)])