49 lines
1.5 KiB
Python
49 lines
1.5 KiB
Python
import inspect
|
|
import collections
|
|
import functools
|
|
|
|
|
|
def cached_property(f):
|
|
return property(functools.lru_cache()(f))
|
|
|
|
|
|
class MultiEnumMeta(type):
|
|
@classmethod
|
|
def __prepare__(mcls, name, bases, **kwargs):
|
|
return collections.OrderedDict()
|
|
|
|
def __new__(cls, name, bases, attrs, **kwargs):
|
|
parsers = {}
|
|
used = 0
|
|
for key, value in attrs.copy().items():
|
|
if isinstance(value, tuple):
|
|
if len(value) == 2:
|
|
child, mask = value
|
|
shift = 0
|
|
elif len(value) == 3:
|
|
child, mask, shift = value
|
|
if inspect.isclass(child):
|
|
if mask is None:
|
|
mask = ~used
|
|
parsers[key] = (child, mask, shift)
|
|
used |= mask
|
|
del attrs[key]
|
|
|
|
attrs['_parsers_'] = parsers
|
|
return super().__new__(cls, name, bases, attrs)
|
|
|
|
class MultiEnum(metaclass=MultiEnumMeta):
|
|
def __init__(self, value: int):
|
|
for field, (child, mask, shift) in self._parsers_.items():
|
|
setattr(self, field, child((value & mask) >> shift))
|
|
|
|
def __str__(self):
|
|
return '{}({})'.format(self.__class__.__name__,
|
|
', '.join('{}: {}'.format(n, getattr(self, n)) for n in self._parsers_)
|
|
)
|
|
|
|
def __repr__(self):
|
|
return '<{}({})>'.format(self.__class__.__name__,
|
|
', '.join('{}: {!r}'.format(n, getattr(self, n)) for n in self._parsers_)
|
|
)
|