(original) (raw)
Split off from the PEP 435 - requesting pronouncement thread.
Think I've come up with a system that works for my auto-numbering case without knowing the internals of enum\_type. Patch passes all existing test cases. The patch does two things:
1\. Finds the first non-Enum class on the MRO of the new class and uses that as the enum type.
2\. Instead of directly setting the \_name and \_value of the enum\_item, it lets the Enum class do it via Enum.\_\_init\_\_(). Subclasses can override this. This gives Enums a 2-phase construction just like other classes.
diff -r 758d43b9f732 ref435.py
--- a/ref435.py Fri May 03 18:59:32 2013 -0700
+++ b/ref435.py Sun May 05 13:43:56 2013 +1000
@@ -116,7 +116,17 @@
if bases\[-1\] is Enum:
obj\_type = bases\[0\]
else:
- obj\_type = bases\[-1\].\_\_mro\_\_\[1\] # e.g. (IntEnum, int, Enum, object)
+ obj\_type = None
+
+ for base in bases:
+ for c in base.\_\_mro\_\_:
+ if not issubclass(c, Enum):
\+ obj\_type = c
+ break
+
+ if obj\_type is not None:
+ break
+
else:
obj\_type = object
# save enum items into separate mapping so they don't get baked into
@@ -143,8 +153,7 @@
enum\_item = object.\_\_new\_\_(enum\_class)
else:
enum\_item = obj\_type.\_\_new\_\_(enum\_class, value)
- enum\_item.\_value = value
- enum\_item.\_name = e
+ enum\_item.\_\_init\_\_(e, value)
enum\_map\[e\] = enum\_item
enum\_class.\_\_aliases\_\_ = aliases # non-unique enums names
enum\_class.\_enum\_names = enum\_names # enum names in definition order
@@ -232,6 +241,10 @@
return enum
raise ValueError("%s is not a valid %s" % (value, cls.\_\_name\_\_))
+ def \_\_init\_\_(self, name, value):
+ self.\_name = name
+ self.\_value = value
+
def \_\_repr\_\_(self):
return "<%s.%s: %r>" % (self.\_\_class\_\_.\_\_name\_\_, self.\_name, self.\_value)
Auto-int implementation:
class AutoInt(int):
\_\_slots\_\_ = ()
def \_\_new\_\_(cls, value):
if value is Ellipsis:
try:
i = cls.\_auto\_number
except AttributeError:
i = cls.\_auto\_number = 0
else:
i = cls.\_auto\_number = value
cls.\_auto\_number += 1
return int.\_\_new\_\_(cls, i)
class AutoIntEnum(AutoInt, IntEnum):
def \_\_init\_\_(self, name, value):
super(AutoIntEnum, self).\_\_init\_\_(name, int(self))
class TestAutoIntEnum(AutoIntEnum):
a = ...
b = 3
c = ...
class TestAutoIntEnum2(AutoIntEnum):
a = ...
b = ...
c = ...
print(TestAutoIntEnum, list(TestAutoIntEnum))
print(TestAutoIntEnum2, list(TestAutoIntEnum2))
---------- Run ----------
\[, , \]
\[, , \]
Tim Delaney