[Python-Dev] PEP 435 - requesting pronouncement

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


On 5 May 2013 11:22, Tim Delaney <timothy.c.delaney at gmail.com> wrote:

> On 5 May 2013 10:49, Eli Bendersky <eliben at gmail.com> wrote:
>
>>
>> On Sat, May 4, 2013 at 4:27 PM, Tim Delaney <timothy.c.delaney at gmail.com>wrote:
>>
>>> Typo line 171: <Colro.blue: 3>
>>>
>>>
>> Fixed, thanks.
>>
>>
>>
>>> One thing I'd like to be clear in the PEP about is whether enum_type and
>>> _EnumDict._enum_names should be documented, or whether they're considered
>>> implementation details.
>>>
>>>
>> No, they should not. Not only are they implementation details, they are
>> details of the *reference implementation*, not the actual stdlib module.
>> The reference implementation will naturally serve as a basis for the stdlib
>> module, but it still has to undergo a review in which implementation
>> details can change. Note that usually we do not document implementation
>> details of stdlib modules, but this doesn't prevent some people from using
>> them if they really want to.
>>
>
> I think it would be useful to have some guaranteed method for a
> sub-metaclass to get the list of enum keys before calling the base class
> __new__. Not being able to do so removes a large number of possible
> extensions (like auto-numbering).
>

 I've been able to achieve the auto-numbering without relying on the
internal implementation at all (with a limitation), with a single change to
enum_type.__new__. My previous patch was slightly wrong - fix below as
well. All existing tests pass. BTW, for mix-ins it's required that they
have __slots__ = () - might want to mention that in the PEP.

diff -r 758d43b9f732 ref435.py
--- a/ref435.py Fri May 03 18:59:32 2013 -0700
+++ b/ref435.py Sun May 05 13:10:11 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
@@ -142,6 +152,7 @@
                 if obj_type in (object, Enum):
                     enum_item = object.__new__(enum_class)
                 else:
+                    value = obj_type.__new__(obj_type, value)
                     enum_item = obj_type.__new__(enum_class, value)
                 enum_item._value = value
                 enum_item._name = e

Implementation:

class AutoInt(int):
    __slots__ = ()  # Required

    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):
    pass

class TestAutoIntEnum(AutoIntEnum):
    a = ...
    b = 3
    c = ...

print(TestAutoIntEnum, list(TestAutoIntEnum))

---------- Run ----------
<Enum 'TestAutoIntEnum'> [<TestAutoIntEnum.a: 0>, <TestAutoIntEnum.b: 3>,
<TestAutoIntEnum.c: 4>]

The implementation is not quite as useful - there's no immediately-obvious
way to have an auto-numbered enum that is not also an int enum e.g. if you
define class AutoNumberedEnum(AutoInt, Enum) it's still an int subclass.

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


More information about the Python-Dev mailing list