Repository navigation
Expand file tree
/
Copy pathenum.py
More file actions
196 lines (166 loc) · 6.94 KB
/
Copy pathenum.py
File metadata and controls
196 lines (166 loc) · 6.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# enum.py
# Enum implementation without metaclasses
# version="1.4.0"
# ==============================================================================
# Variable & Abbreviation Definitions:
# ==============================================================================
# Functions & Helper Methods:
# _c(e, n, v, v_t) -> create_enum_item: Helper function to construct a typed enum instance.
# _l(v) -> lookup: Internal classmethod to find an enum member by name or value.
# _i() -> items: Internal classmethod to initialize/retrieve tuple of enum instances.
# _s(s, k, v) -> __setattr__: Inner setter guard raising AttributeError on enum instances.
#
# Helper Arguments & Local Variables:
# e - enum_name / class_name: String representing the Enum class name (e.g., "Color").
# n - name: String representing the enum member key (e.g., "RED").
# v - value: Actual value assigned to the enum member (e.g., 1, "pending").
# v_t - value_type: Target constraint type (`int`, `str`, or `None` for generic Enum).
# l - names_list: List of parsed string keys from comma/space-separated inputs.
# d - dict / mapping: Temporary dictionary for parsed enum members or dump serialization.
# i, __i - items: List or tuple containing initialized enum member instances.
# c - class / new_class: Dynamically created Enum class object via `type()`.
# s, k, o - self, key/attribute_name, other_object (standard short parameters).
# ==============================================================================
def _c(e, n, v, v_t=None):
# Create enum item
def _s(s, k, v):
raise AttributeError("cannot set attribute")
# Type checks for IntEnum and StrEnum
if v_t is int and not isinstance(v, int):
raise TypeError(f"IntEnum member {n!r} value must be int, got {type(v).__name__}")
elif v_t is str and not isinstance(v, str):
raise TypeError(f"StrEnum member {n!r} value must be str, got {type(v).__name__}")
# Ensure 'e' is a clean class name string, even if a class type object was passed
e = e.__name__ if hasattr(e, "__name__") else str(e)
# Create class: type(name, bases, dict), which inherits a base type (int, str, etc.)
return type(
f"{e}.{n}",
(type(v),),
{
"name": n,
"value": v,
"__str__": lambda s: str(v) if v_t in (int, str) else f"{e}.{n}",
"__repr__": lambda s: f"<{e}.{n}: {v!r}>",
"__call__": lambda s: v,
"__setattr__": _s,
},
)(v)
class Enum:
_v_t = None # value type
def __new__(cls, value=None, names=None, *, start=1):
# Functional API: dynamic creation of a new Enum class
if value is not None and names is not None:
is_str_enum = cls._v_t is str
# Parse 'names' parameter into a key-value dictionary:
if isinstance(names, dict):
d = names
elif isinstance(names, str):
# Strings (comma/space-separated)
l = names.replace(",", " ").split() # names_list
d = (
{k: k for k in l}
if is_str_enum
else {k: v for v, k in enumerate(l, start=start)}
)
elif isinstance(names, (list, tuple)):
# Lists or tuples (flat or key-value pairs)
if names and isinstance(names[0], (list, tuple)):
d = dict(names)
else:
d = (
{k: k for k in names}
if is_str_enum
else {k: v for v, k in enumerate(names, start=start)}
)
else:
# For sets and other iterables
d = (
{k: k for k in names}
if is_str_enum
else {k: v for v, k in enumerate(names, start=start)}
)
# Construct and return a new class type
c = type(str(value), (cls,), {})
i = []
for k, v in d.items():
e = _c(value, k, v, v_t=cls._v_t)
setattr(c, k, e)
i.append(e)
if i:
c.__i = tuple(i)
return c
# Lookup existing member by value or name: e.g., Color(1) or Color("RED")
if value is not None and cls not in (Enum, IntEnum, StrEnum):
return cls._l(value)
return super().__new__(cls)
def __init__(self, *args, **kwargs):
# Trigger lazy items initialization for class syntax declarations
if "__i" not in self.__class__.__dict__:
self._i()
def __str__(self):
if hasattr(self, "value") and self.value is not None:
return f"{type(self).__name__}.{self.name}"
return type(self).__name__
def __repr__(self):
if hasattr(self, "value") and self.value is not None:
return f"<{type(self).__name__}.{self.name}: {self.value!r}>"
return f"<enum '{type(self).__name__}'>"
def __call__(self, v):
return self._l(v)
def __getitem__(self, k):
# Instance-level container lookup: Color()["RED"]
for i in self._i():
if i.name == k:
return i
raise KeyError(k)
def __eq__(self, o):
return isinstance(o, Enum) and self._i() == o._i()
@classmethod
def __iter__(cls):
return iter(cls._i())
@classmethod
def __len__(cls):
return len(cls._i())
@classmethod
def __setattr__(cls, k, v):
raise AttributeError("cannot set attribute")
@classmethod
def __delattr__(cls, k):
raise AttributeError("cannot delete attribute")
@classmethod
def items(cls):
return cls._i()
@classmethod
def dump(cls):
# Serialize enum members to string representation for eval compatibility
# obj == eval(dump(obj))
if cls._v_t is None:
e = "Enum"
else:
e = cls._v_t.__name__[0].upper() + cls._v_t.__name__[1:] + "Enum"
d = {i.name: i.value for i in cls._i()}
return f"{e}('{cls.__name__}', {d})"
@classmethod
def _i(cls):
# Get enum items
if "__i" not in cls.__dict__:
# Convert raw class attributes into typed enum instances
i = [] # items
for k, v in list(cls.__dict__.items()):
if not k.startswith("_") and not callable(v):
e = _c(cls.__name__, k, v, v_t=cls._v_t)
setattr(cls, k, e)
i.append(e)
cls.__i = tuple(i)
return cls.__i
@classmethod
def _l(cls, v):
# Lookup by value or name
for i in cls._i():
if i.value == v or i.name == v:
return i
raise ValueError(f"{v!r} is not a valid {cls.__name__}")
class IntEnum(Enum):
_v_t = int
class StrEnum(Enum):
_v_t = str