Skip to main content

Lib/enum.py (part 4)

Source:

cpython 3.14 @ ab2d84fe1023/Lib/enum.py

This annotation covers mixin enum types and the Flag class. See lib_enum3_detail for EnumType.__new__, Enum.__new__, and _EnumDict.

Map

LinesSymbolRole
1-80IntEnumEnum whose members are also int values
81-160StrEnumEnum whose members are also str values
161-240auto() / _generate_next_value_Automatic value generation
241-360FlagEnum with bitwise combination support
361-500Flag.__or__ / __and__ / __xor__Bitwise operations on flags

Reading

IntEnum

# CPython: Lib/enum.py:1620 IntEnum
class IntEnum(int, ReprEnum):
"""Enum where members are also ints and int operations apply."""

IntEnum inherits from both int and ReprEnum. Members are true int values: Color.RED + 1 works without explicit casting. ReprEnum (not Enum) means str(Color.RED) returns '1', not 'Color.RED'.

StrEnum

# CPython: Lib/enum.py:1660 StrEnum
class StrEnum(str, ReprEnum):
"""Enum where members are also strs."""

@staticmethod
def _generate_next_value_(name, start, count, last_values):
return name.lower()

StrEnum members are strings. _generate_next_value_ defaults to name.lower() so auto() generates lowercase member names: class Color(StrEnum): RED = auto() gives Color.RED == 'red'.

auto() / _generate_next_value_

# CPython: Lib/enum.py:220 auto
class auto(int):
_value_ = EJECT
def __new__(cls):
obj = int.__new__(cls, 0)
obj._auto_ = True
return obj

# CPython: Lib/enum.py:180 _generate_next_value_ (default)
@staticmethod
def _generate_next_value_(name, start, count, last_values):
for last_value in reversed(last_values):
try:
return last_value + 1
except TypeError:
pass
return start

auto() creates a placeholder; _EnumDict.__setitem__ detects it and calls _generate_next_value_. The default increments the last numeric value. StrEnum overrides to use the lowercased name.

Flag

# CPython: Lib/enum.py:940 Flag
class Flag(Enum):
@classmethod
def _missing_(cls, value):
# For compound values not in the enum, create a pseudo-member
result = cls._create_pseudo_member_(value)
return result

@classmethod
def _create_pseudo_member_(cls, value):
# Build a new member from the decomposition of value into defined flags
pseudo_member = cls._value2member_map_.get(value)
if pseudo_member is None:
need_to_create = [value]
# Decompose into power-of-2 components
...
return pseudo_member

Flag allows combining members with |: Perm.R | Perm.W creates a new pseudo-member. _missing_ decomposes unknown values into their constituent defined flags.

Flag.__or__

# CPython: Lib/enum.py:1020 Flag.__or__
def __or__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self.__class__(self._value_ | other._value_)

def __and__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self.__class__(self._value_ & other._value_)

def __xor__(self, other):
...
return self.__class__(self._value_ ^ other._value_)

def __invert__(self):
# Invert within the defined mask of all flags
result = self._value_ ^ self.__class__._flag_mask_
return self.__class__(result)

Perm.R | Perm.W returns a new Perm with value = R._value_ | W._value_. ~Perm.R returns all defined flags except R. The _flag_mask_ is the OR of all defined member values.

gopy notes

IntEnum is module/enum.IntEnum in module/enum/module.go, with Go's int as the backing type. StrEnum uses string. Flag.__or__ creates a new member via objects.EnumType.NewPseudoMember(value). auto() is detected in _EnumDict.setItem and resolved by calling _generate_next_value_.