[Twisted-Python] A Python enum library with a Twist

Jonathan Jacobs jonathan+twisted at jsphere.com
Mon Jan 31 05:31:17 EST 2011


Hi,

First off there isn't actually a twist, it's just for Twisted
addressing the points in #4671 [1]. Sorry to disappoint. Secondly I
realise there are already at least a thousand Python enum libraries,
most of which I haven't explored, feel free to mention these with
supporting arguments.

My point of view is that a great many number of these enum libraries
go to long lengths to make stuff too "cute". While having less
not-networking-related code in Twisted may be a more desirable route,
Twisted makes enough use of enum-esque things in the current code base
that it may be easier (maybe even warranted)  to have our own
implementation that can cater directly to the needs of Twisted without
being subjected to the usual irritations of third-party software; also
Twisted's high-qualilty coding and testing standards are only a good
thing.

The current code is hosted on Launchpad [2] and the source code is
viewable on the web [3]. I am aware that there are currently no
unittests or any kind of useful documentation, hopefully the examples
are good enough for now. I'm hoping for some feedback to decide
whether to press ahead or turn back. I've tried to look at as many
Twisted enum use-cases as possible, without trying to cater to every
one individually, however I do still have a few questions:

1. #4671 uses an "asInt" method in the examples, this is obviously
going to require changing all code that uses these enums (of which
there is plenty.) Is this a good idea? It seems easy to forget that
"F_FOO | F_BAR" is not giving you a number.

2. I use "__int__", I don't know if this is horrible or not and
whether I should just use the "asInt" method proposed in the ticket.

3. It seems to me that there are two general cases:
   1. The enum just holds values that have an interesting meaning on
their own (e.g. AMP special keys (ASK, ANSWER, etc.), IRC status codes
(RPL_WHOIS, etc.)) and combining them makes no sense.
   2. The enum holds values that are intended to be combined. i.e. flags.

   Does it make sense to try and combine this behaviour into the same
type? Currently it is and you get an exception when doing certain
things (none of which make any sense, in this context):

>>> (Words.AYE | Words.BEE)
<EnumValueGroup '|': [<EnumValue Words.AYE: 'a'>, <EnumValue Words.BEE: 'b'>]>
>>> (Words.AYE | Words.BEE).value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "enum.py", line 77, in value
    return reduce(self.op, values)
TypeError: unsupported operand type(s) for |: 'str' and 'str'

>>> Words.fromValue('a')
<EnumValue Words.AYE: 'a'>
>>> Words.fromValue('c') # This value is not in the enumeration and ORing values to get it is impossible.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "enum.py", line 133, in fromValue
    if target - v < 0:
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Comments appreciated.

[1] <http://twistedmatrix.com/trac/ticket/4671>
[2] <http://code.launchpad.net/~jjacobs/+junk/twistedenum>
[3] <http://bazaar.launchpad.net/~jjacobs/+junk/twistedenum/view/head:/enum.py>

-- 
Jonathan



More information about the Twisted-Python mailing list