Skip to content

Commit fb5bcae

Browse files
committed
python-stdlib\enum\enum.py: Add Enum class.
Signed-off-by: Ihor Nehrutsa <[email protected]>
1 parent b379e4f commit fb5bcae

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed

python-stdlib/enum/enum.py

+211
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# enum.py
2+
3+
_Err = "no such attribute: "
4+
5+
6+
class int_value(int):
7+
@property
8+
def value(self) -> int:
9+
return self
10+
11+
def __call__(self) -> int:
12+
return self
13+
14+
15+
class str_value(str):
16+
@property
17+
def value(self) -> str:
18+
return self
19+
20+
def __call__(self) -> str:
21+
return self
22+
23+
24+
class bool_value(bool):
25+
@property
26+
def value(self) -> bool:
27+
return self
28+
29+
def __call__(self) -> bool:
30+
return self
31+
32+
33+
class float_value(float):
34+
@property
35+
def value(self) -> float:
36+
return self
37+
38+
def __call__(self) -> float:
39+
return self
40+
41+
42+
def get_class_value(value):
43+
if type(value) is int:
44+
return int_value(value)
45+
elif type(value) is bool:
46+
return bool_value(value)
47+
elif type(value) is float:
48+
return float_value(value)
49+
elif type(value) is str:
50+
return str_value(value)
51+
else:
52+
return value
53+
54+
55+
def enum(**kw_args): # `**kw_args` kept backwards compatible as in the Internet examples
56+
return Enum(kw_args)
57+
58+
59+
class Enum(dict):
60+
def __init__(self, arg=None): # `arg` is dict() compatible
61+
super().__init__()
62+
self._arg = None
63+
if not arg is None:
64+
self.append(arg)
65+
self._is_enums_from_class = False
66+
self._get_enums_from_class()
67+
68+
def _update(self, key, value):
69+
self.update({key: get_class_value(value)})
70+
71+
def append(self, arg=None, **kw_args):
72+
if len(kw_args):
73+
for key, value in kw_args.items():
74+
self._update(key, value)
75+
if type(arg) == type(dict()):
76+
for key, value in arg.items():
77+
self._update(key, value)
78+
else:
79+
self._arg = arg # for __str__()
80+
return self
81+
82+
def __repr__(self):
83+
d = self.copy()
84+
try:
85+
d.pop("_arg")
86+
except:
87+
pass
88+
return str(d)
89+
90+
def __str__(self):
91+
value = None
92+
try:
93+
value = self._arg
94+
except:
95+
pass
96+
if not value is None:
97+
if self.is_value(value):
98+
self._arg = None
99+
return value
100+
raise ValueError(_Err + f"{value}")
101+
return self.__qualname__ + "(" + self.__repr__() + ")"
102+
103+
def is_value(self, value):
104+
if value in self.values():
105+
return True
106+
return False
107+
108+
def key_from_value(self, value):
109+
for key in self:
110+
if self.get(key) == value:
111+
return self.__qualname__ + "." + key
112+
raise ValueError(_Err + f"{value}")
113+
114+
def __call__(self, value):
115+
if self.is_value(value):
116+
return value
117+
raise ValueError(_Err + f"{value}")
118+
119+
def __getattr__(self, key):
120+
try:
121+
if key in self:
122+
return self[key]
123+
else:
124+
raise KeyError(_Err + f"{key}")
125+
except:
126+
raise KeyError(_Err + f"{key}")
127+
128+
def __setattr__(self, key, value):
129+
if key == "_arg":
130+
self[key] = value
131+
return
132+
try:
133+
self[key] = get_class_value(value)
134+
except:
135+
raise KeyError(_Err + f"{key}")
136+
137+
def __delattr__(self, key):
138+
try:
139+
if key in self:
140+
del self[key]
141+
else:
142+
raise KeyError(_Err + f"{key}")
143+
except:
144+
raise KeyError(_Err + f"{key}")
145+
146+
def __len__(self):
147+
return len(tuple(self.keys()))
148+
149+
def __dir__(self):
150+
return dir(Enum)
151+
152+
def _get_enums_from_class(self):
153+
## Class XX(Enum):
154+
## X1 = 1
155+
## X2 = 2
156+
157+
if not self._is_enums_from_class:
158+
keys = dir(eval(self.__qualname__))
159+
160+
def try_remove(item):
161+
try:
162+
keys.remove(item)
163+
except:
164+
pass
165+
166+
for item in dir(dict):
167+
try_remove(item)
168+
169+
_list = [
170+
"__init__",
171+
"__class__init__",
172+
"__call__",
173+
"__Errases__",
174+
"__module__",
175+
"__qualname__",
176+
"__len__",
177+
"__lt__",
178+
"__le__",
179+
"__eq__",
180+
"__ne__",
181+
"__gt__",
182+
"__ge__",
183+
"__dir__",
184+
"__delattr__",
185+
"__getattr__",
186+
"__setattr__",
187+
"__str__",
188+
"__repr__",
189+
"_get_enums_from_class",
190+
"_arg",
191+
"_update",
192+
"is_value",
193+
"key_from_value",
194+
"append",
195+
]
196+
for item in _list:
197+
try_remove(item)
198+
module = ""
199+
if self.__module__ != "__main__":
200+
module = self.__module__ + "."
201+
for key in keys:
202+
try:
203+
value = eval(f"{module}{self.__qualname__}.{key}")
204+
except:
205+
value = eval(f"{self.__qualname__}.{key}")
206+
self._update(key, value)
207+
keys.clear()
208+
del keys
209+
self._is_enums_from_class = True # 1 !!!
210+
self.pop("_is_enums_from_class") # 2 !!!
211+
return self

python-stdlib/enum/enum_test.py

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# enum_test.py
2+
3+
from enum import Enum, enum
4+
5+
6+
class Direction(Enum):
7+
CW = "CW"
8+
CCW = "CCW"
9+
10+
11+
class State(Direction):
12+
Stop = 1
13+
Run = 2
14+
Ready = 3
15+
Disabled = False
16+
Enabled = True
17+
18+
19+
state = Enum()
20+
print(state)
21+
state = Direction()
22+
print(state)
23+
state = State()
24+
print(state)
25+
state = State({"X": 1.0, "Y": 2.0})
26+
print(state)
27+
state.Idle = 10
28+
state.Triggered = 20
29+
state.Lockout = 30
30+
print(state)
31+
32+
print("Direction(Direction.CCW):", Direction(Direction.CCW))
33+
print("Direction('CW'):", Direction("CW"))
34+
print("state(10):", state(10))
35+
36+
print("state('CW'):", state("CW"))
37+
print("type(state('CW')):", type(state("CW")))
38+
39+
print("state.key_from_value(20):", state.key_from_value(20))
40+
print("len(state):", len(state))
41+
42+
print("state.Idle:", state.Idle)
43+
print("type(state.Idle):", type(state.Idle))
44+
45+
current_state = state.Idle
46+
print("current_state:", current_state)
47+
if current_state == state.Idle:
48+
print(" Idle state")
49+
if current_state != state.Triggered:
50+
print(" Not a triggered state")
51+
current_state = state.Idle
52+
print("current_state:", current_state)
53+
print("state.key_from_value(current_state):", state.key_from_value(current_state))
54+
55+
state2 = eval(str(state))
56+
print(state2)
57+
print("state == state2:", state == state2)
58+
59+
del state.Triggered
60+
print(state)
61+
print("state == state2:", state == state2)
62+
63+
print("state.keys():", state.keys())
64+
print("state.values():", state.values())
65+
print("state.items():", state.items())
66+
67+
try:
68+
del state.stop
69+
except Exception as e:
70+
print("Exception:", e)
71+
72+
assert current_state == state.Idle
73+
assert current_state != state.Disabled
74+
assert state.Idle != state.Disabled
75+
print(
76+
"State(State.Ready):",
77+
State(State.Ready),
78+
"type(State.Ready):",
79+
type(State(State.Ready)),
80+
"type(State.Ready):",
81+
type(State.Ready),
82+
)
83+
assert int(str(State(State.Ready))) == State.Ready
84+
assert int(str(State(State.Ready))) != State.Disabled
85+
print("will raise exception")
86+
del state.Triggered

python-stdlib/enum/manifest.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
metadata(version="0.0.1")
2+
3+
module("enum.py")

0 commit comments

Comments
 (0)