On 5 May 2013 11:22, Tim Delaney <timothy.c.dela...@gmail.com> wrote:
> On 5 May 2013 10:49, Eli Bendersky <eli...@gmail.com> wrote: > >> >> On Sat, May 4, 2013 at 4:27 PM, Tim Delaney >> <timothy.c.dela...@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
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com