Often I've started with a boolean variable (can_access = True|False) but then later needed to replace it with something more nuanced (can_access = True|False|'only_superuser'|'unless_leapday')
In your own code, it's easy to change this, but when you've released a public library people will have already written code expecting a boolean here. The problem of course is that in a boolean context, both 'only_superuser' and 'unless_leapday' will evaluate to True, but presumably 'only_superuser' should be False for naïve/existing implementations (and probably unless_leapday should be True).
So I wrote BooleanEnum which allows for a drop-in replacement for previous Boolean variables. If a value is a tuple, it is expected to be
(BooleanValue, NormalLabel):
class CanAccess(BooleanEnum):
TRUE = True
FALSE = False
ONLY_SUPERUSER = (False, 'only_superuser')
UNLESS_LEAPDAY = (True, 'unless_leapday')
It becomes a drop-in replacement for if can_access: type of checks. Unfortunately, there's no way to do a drop-in for if can_access is True: types of checks.
The code is part of the music21 library under music21.common.enums.BooleanEnum, but you don't want that whole library as a dependency just for it, so here's the code (minus comments):
class BooleanEnum(Enum):
@staticmethod
def is_bool_tuple(v):
if isinstance(v, tuple) and len(v) == 2 and isinstance(v[0], bool):
return True
else:
return False
def __eq__(self, other):
if isinstance(other, self.__class__):
return super().__eq__(other)
v = self.value
if v == other:
return True
elif self.is_bool_tuple(v):
if v[0] is other:
return True
return v[1] == other
return False
def __bool__(self):
v = self.value
if self.is_bool_tuple(v):
return v[0]
return bool(self.value)
def __repr__(self):
return f'<{self.__class__.__name__}.{self.name}>'