[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