Skip to content

Instantly share code, notes, and snippets.

@rindeal
Last active November 1, 2021 04:35
Show Gist options
  • Save rindeal/1d669669b798d679baae3d8d9035bb16 to your computer and use it in GitHub Desktop.
Save rindeal/1d669669b798d679baae3d8d9035bb16 to your computer and use it in GitHub Desktop.
python enum
import typing
from sys import _getframe
class Enum(int):
__slots__ = []
"""type: typing.FrozenSet[str]"""
names2values = dict() # TODO: make it FrozenBimap
"""type: typing.Dict[str, int]"""
values2names = dict()
"""type: typing.Dict[int, str]"""
_counter = -1
def __new__(cls, value):
cls._counter = value
return int.__new__(cls, int(value))
enumcls_t = typing.Type[Enum]
def _no_new_instances(*a, **d):
raise Exception("no new instances permitted")
def _lock_enum_type(cls: typing.Type[Enum]):
cls.__new__ = _no_new_instances
def begin_enum(cls: typing.Type[Enum]):
cls._snap_before = frozenset(_getframe(1).f_globals.keys())
def end_enum(cls: typing.Type[Enum]):
cls_globals = _getframe(1).f_globals
names = frozenset(cls_globals.keys()) - cls._snap_before
del cls._snap_before
cls.names2values = {name: cls_globals[name] for name in names}
cls.values2names = {cls_globals[name]: name for name in names}
_lock_enum_type(cls)
def next(cls: typing.Type[Enum]):
return cls(cls._counter + 1)
from . import _meta
class enum1(_meta.enum):
pass
_meta.begin_enum(enum1)
VALUE0 = _meta.next(enum1)
VALUE1 = _meta.next(enum1)
VALUE2 = _meta.next(enum1)
VALUE50 = enum1(50)
VALUE51 = _meta.next(enum1)
VALUE52 = _meta.next(enum1)
_meta.end_enum(enum1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment