[Python-Dev] PEP 435 - reference implementation discussion

Tim Delaney timothy.c.delaney at gmail.com
Sun May 5 05:50:25 CEST 2013


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 ----------
<Enum 'TestAutoIntEnum'> [<TestAutoIntEnum.a: 0>, <TestAutoIntEnum.b: 3>,
<TestAutoIntEnum.c: 4>]
<Enum 'TestAutoIntEnum2'> [<TestAutoIntEnum2.a: 0>, <TestAutoIntEnum2.b:
1>, <TestAutoIntEnum2.c: 2>]

Tim Delaney
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20130505/a7fbdabd/attachment.html>


More information about the Python-Dev mailing list