<div dir="ltr">Split off from the PEP 435 - requesting pronouncement thread.<div><br></div><div style>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:</div>
<div style><br></div><div style>1. Finds the first non-Enum class on the MRO of the new class and uses that as the enum type.</div><div style><br></div><div style>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.</div>
<div style><br></div><div style><div><div>diff -r 758d43b9f732 ref435.py</div><div>--- a/ref435.py<span class="" style="white-space:pre"> </span>Fri May 03 18:59:32 2013 -0700</div><div>+++ b/ref435.py<span class="" style="white-space:pre"> </span>Sun May 05 13:43:56 2013 +1000</div>
<div>@@ -116,7 +116,17 @@</div><div> if bases[-1] is Enum:</div><div> obj_type = bases[0]</div><div> else:</div><div>- obj_type = bases[-1].__mro__[1] # e.g. (IntEnum, int, Enum, object)</div>
<div>+ obj_type = None</div><div>+</div><div>+ for base in bases:</div><div>+ for c in base.__mro__:</div><div>+ if not issubclass(c, Enum):</div><div>
+ obj_type = c</div><div>+ break</div><div>+</div><div>+ if obj_type is not None:</div><div>+ break</div><div>+</div><div> else:</div>
<div> obj_type = object</div><div> # save enum items into separate mapping so they don't get baked into</div><div>@@ -143,8 +153,7 @@</div><div> enum_item = object.__new__(enum_class)</div>
<div> else:</div><div> enum_item = obj_type.__new__(enum_class, value)</div><div>- enum_item._value = value</div><div>- enum_item._name = e</div><div>+ enum_item.__init__(e, value)</div>
<div> enum_map[e] = enum_item</div><div> enum_class.__aliases__ = aliases # non-unique enums names</div><div> enum_class._enum_names = enum_names # enum names in definition order</div>
<div>@@ -232,6 +241,10 @@</div><div> return enum</div><div> raise ValueError("%s is not a valid %s" % (value, cls.__name__))</div><div> </div><div>+ def __init__(self, name, value):</div>
<div>+ self._name = name</div><div>+ self._value = value</div><div>+</div><div> def __repr__(self):</div><div> return "<%s.%s: %r>" % (self.__class__.__name__, self._name, self._value)</div>
<div> </div></div><div style>Auto-int implementation:</div><div style><br></div><div style><div><div>class AutoInt(int):</div><div> __slots__ = ()</div><div><br></div><div> def __new__(cls, value):</div><div> if value is Ellipsis:</div>
<div> try:</div><div> i = cls._auto_number</div><div> except AttributeError:</div><div> i = cls._auto_number = 0</div><div><br></div><div> else:</div><div> i = cls._auto_number = value</div>
<div><br></div><div> cls._auto_number += 1</div><div> return int.__new__(cls, i)</div><div><br></div><div>class AutoIntEnum(AutoInt, IntEnum):</div><div> def __init__(self, name, value):</div><div> super(AutoIntEnum, self).__init__(name, int(self))</div>
<div><br></div><div>class TestAutoIntEnum(AutoIntEnum):</div><div> a = ...</div><div> b = 3</div><div> c = ...</div><div><br></div><div>class TestAutoIntEnum2(AutoIntEnum):</div><div> a = ...</div><div> b = ...</div>
<div> c = ...</div><div><br></div><div>print(TestAutoIntEnum, list(TestAutoIntEnum))</div><div>print(TestAutoIntEnum2, list(TestAutoIntEnum2))</div></div><div><br></div></div><div><div>---------- Run ----------</div><div>
<Enum 'TestAutoIntEnum'> [<TestAutoIntEnum.a: 0>, <TestAutoIntEnum.b: 3>, <TestAutoIntEnum.c: 4>]<br></div><div><Enum 'TestAutoIntEnum2'> [<TestAutoIntEnum2.a: 0>, <TestAutoIntEnum2.b: 1>, <TestAutoIntEnum2.c: 2>]</div>
<div><br></div><div>Tim Delaney<br></div></div></div></div>