class BrokenEnumBase:
@classmethod
@functools.lru_cache()
def get(cls, /, value: Union[str, enum.Enum, Any], default: Any=None) -> Optional[Self]:
"""Get enum members from their value, name or themselves"""
# Value is already a member of the enum
if isinstance(value, cls):
return value
# Attempt to get by value
with contextlib.suppress(ValueError):
return cls(value)
# Attempt to get by key
with contextlib.suppress(KeyError):
return cls[value]
return default
# Values
@classmethod
def options(cls) -> tuple[enum.Enum]:
"""Get all options (Class.A, Class.B, ...) of the enum"""
return tuple(cls)
@classmethod
def values(cls) -> tuple[Any]:
"""Get all 'values' of the enum (name=value)"""
return tuple(member.value for member in cls)
# Key/names properties
@classmethod
def keys(cls) -> tuple[str]:
"""Get all 'keys' of the enum (key=value)"""
return tuple(member.name for member in cls)
# Items and dict-like
@classmethod
def items(cls) -> tuple[tuple[str, Any]]:
"""Get the tuple of (name, value) of all members of the enum"""
return tuple((member.name, member.value) for member in cls)
@classmethod
def as_dict(cls) -> dict[str, Any]:
"""Get the dictionary of all key=value of the enum"""
return dict(cls.items())
def __getitem__(self, index: int) -> enum.Enum:
return self.members[index]
# # Smart methods
@functools.lru_cache()
def next(self, value: Union[str, enum.Enum]=None, *, offset: int=1) -> Self:
"""Get the next enum member defined in the class"""
cls = type(self)
value = cls.get(value or self)
return cls.options()[(cls.options().index(value) + offset) % len(cls)]
def __next__(self) -> Self:
return self.next()
@functools.lru_cache()
def previous(self, value: Union[str, enum.Enum]=None, *, offset: int=1) -> Self:
"""Get the previous enum member defined in the class"""
cls = type(self)
value = cls.get(value or self)
return cls.options()[(cls.options().index(value) - offset) % len(cls)]
# # Advanced functions
def field(self, **kwargs: dict[str, Any]) -> attrs.Attribute:
"""Get an attrs.field() with this option as default and Enum.get as converter"""
return attrs.field(
default=self,
converter=type(self).get,
**kwargs
)
@classmethod
def extend(cls, name: str, value: Any) -> Self:
"""Dynamically extend the enum with a new member (name=value)"""
raise NotImplementedError("This method is not implemented yet")