[Python-Dev] backported Enum
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