[Python-Dev] backported Enum

Ethan Furman ethan at stoneleaf.us
Fri Jun 28 22:30:14 CEST 2013

On 06/28/2013 01:07 PM, Jim J. Jewett wrote:
> (On June 19, 2013) Barry Warsaw wrote about porting mailman from
> flufl.enum to the stdlib.enum:
>> Switching from call syntax to getitem syntax for looking up an
>> enum member by name, e.g.
>>     -        delivery_mode = DeliveryMode(data['delivery_mode'])
>>     +        delivery_mode = DeliveryMode[data['delivery_mode']]
>> Switching from getitem syntax to call syntax for looking up an
>> enum member by value, e.g.
>>     -        return self._enum[value]
>>     +        return self._enum(value)
>> Interesting that these two were exactly opposite from flufl.enum.
> Is there a reason why these were reversed?

Originally the call syntax was used for both value and name lookup.  Various folks were unhappy with that arrangement, 
and since the use-case that I was thinking of at the time was getting enum members back from databases, etc., I went 
with EnumClass(value); I still wanted to be able to use name lookups, so lobbied for getitem syntax for that.  Nobody 
noticed this was the opposite of flufl.enum.

Oh, I say "I", and it is certainly my reasons, but I no longer remember if was me that initially proposed those specific 
ideas, and there were certainly many others that agreed.

>> Switching from int() to .value to get the integer value of an
>> enum member, e.g.
>>     -    return (member.list_id, member.address.email, int(member.role))
>>     +    return (member.list_id, member.address.email, member.role.value)
> Is just this a style preference?

Nope.  If you want the exact value, accessing `.value` is the way to get it.

> Using a .value attribute certainly makes sense, but I don't see it
> mentioned in the PEP as even optional, let alone recommended.

I'll look again at the PEP and the docs and make sure that point is clear.

> If you care that the value be specifically an int (as opposed to any
> object), then a int constructor may be better.

Not entirely sure what you mean by this?

Had it been me, I would have subclassed Enum (as, say, FluflEnum) and added `__int__` to it so that those lines would 
have remained the same.

>> [Some additional changes that mean there will be *some* changes,
>> which does reduce the pressure for backwards compatibility.] ...
>> An unexpected difference is that failing name lookups raise a
>> KeyError instead of a ValueError.
> I could understand either, as well as AttributeError, since the
> instance that would represent that value isn't a class attribute.
> Looking at Enum creation, I think ValueError would be better than
> TypeError for complaints about duplicate names.  Was TypeError
> chosen because it should only happen during setup?

Yes.  That particular error can only happen during setup.

> I would also not be shocked if some people expect failed value
> lookups to raise an IndexError, though I expect they would
> adapt if they get something else that makes sense.
> Would it be wrong to create an EnumError that subclasses
> (ValueError, KeyError, AttributeError) and to raise that
> subclass from everything but _StealthProperty and _get_mixins?

Wouldn't bother me; I'm not sure what the bar is for adding new exceptions, though.


More information about the Python-Dev mailing list