micropython-lib/python-stdlib/enum/enum.py

212 wiersze
5.4 KiB
Python

# enum.py
_Err = "no such attribute: "
class int_value(int):
@property
def value(self) -> int:
return self
def __call__(self) -> int:
return self
class str_value(str):
@property
def value(self) -> str:
return self
def __call__(self) -> str:
return self
class bool_value(bool):
@property
def value(self) -> bool:
return self
def __call__(self) -> bool:
return self
class float_value(float):
@property
def value(self) -> float:
return self
def __call__(self) -> float:
return self
def get_class_value(value):
if type(value) is int:
return int_value(value)
elif type(value) is bool:
return bool_value(value)
elif type(value) is float:
return float_value(value)
elif type(value) is str:
return str_value(value)
else:
return value
def enum(**kw_args): # `**kw_args` kept backwards compatible as in the Internet examples
return Enum(kw_args)
class Enum(dict):
def __init__(self, arg=None): # `arg` is dict() compatible
super().__init__()
self._arg = None
if not arg is None:
self.append(arg)
self._is_enums_from_class = False
self._get_enums_from_class()
def _update(self, key, value):
self.update({key: get_class_value(value)})
def append(self, arg=None, **kw_args):
if len(kw_args):
for key, value in kw_args.items():
self._update(key, value)
if type(arg) == type(dict()):
for key, value in arg.items():
self._update(key, value)
else:
self._arg = arg # for __str__()
return self
def __repr__(self):
d = self.copy()
try:
d.pop("_arg")
except:
pass
return str(d)
def __str__(self):
value = None
try:
value = self._arg
except:
pass
if not value is None:
if self.is_value(value):
self._arg = None
return value
raise ValueError(_Err + f"{value}")
return self.__qualname__ + "(" + self.__repr__() + ")"
def is_value(self, value):
if value in self.values():
return True
return False
def key_from_value(self, value):
for key in self:
if self.get(key) == value:
return self.__qualname__ + "." + key
raise ValueError(_Err + f"{value}")
def __call__(self, value):
if self.is_value(value):
return value
raise ValueError(_Err + f"{value}")
def __getattr__(self, key):
try:
if key in self:
return self[key]
else:
raise KeyError(_Err + f"{key}")
except:
raise KeyError(_Err + f"{key}")
def __setattr__(self, key, value):
if key == "_arg":
self[key] = value
return
try:
self[key] = get_class_value(value)
except:
raise KeyError(_Err + f"{key}")
def __delattr__(self, key):
try:
if key in self:
del self[key]
else:
raise KeyError(_Err + f"{key}")
except:
raise KeyError(_Err + f"{key}")
def __len__(self):
return len(tuple(self.keys()))
def __dir__(self):
return dir(Enum)
def _get_enums_from_class(self):
## Class XX(Enum):
## X1 = 1
## X2 = 2
if not self._is_enums_from_class:
keys = dir(eval(self.__qualname__))
def try_remove(item):
try:
keys.remove(item)
except:
pass
for item in dir(dict):
try_remove(item)
_list = [
"__init__",
"__class__init__",
"__call__",
"__Errases__",
"__module__",
"__qualname__",
"__len__",
"__lt__",
"__le__",
"__eq__",
"__ne__",
"__gt__",
"__ge__",
"__dir__",
"__delattr__",
"__getattr__",
"__setattr__",
"__str__",
"__repr__",
"_get_enums_from_class",
"_arg",
"_update",
"is_value",
"key_from_value",
"append",
]
for item in _list:
try_remove(item)
module = ""
if self.__module__ != "__main__":
module = self.__module__ + "."
for key in keys:
try:
value = eval(f"{module}{self.__qualname__}.{key}")
except:
value = eval(f"{self.__qualname__}.{key}")
self._update(key, value)
keys.clear()
del keys
self._is_enums_from_class = True # 1 !!!
self.pop("_is_enums_from_class") # 2 !!!
return self