I needed to convert an enum to python so that I could decode some responses from C code. Here is an example of quickly converting a C enum to python.
The C code I am working with has several enum structures, one is a long list of error types:
enum LadybugError
{
LADYBUG_OK,
LADYBUG_FAILED,
LADYBUG_INVALID_ARGUMENT,
...
LADYBUG_INVALID_FRAMERATE,
LADYBUG_INVALID_OFFSCREEN_BUFFER_SIZE,
LADYBUG_INVALID_JPEG_IMAGE_STRUCTURE,
LADYBUG_NUM_LADYBUG_ERRORS,
LADYBUG_ERROR_FORCE_QUADLET = 0x7FFFFFFF,
}
There are about 70 items in this list.
Here is the conversion using namedtuple:
LadybugError = namedtuple('Enum', '''
LADYBUG_OK,
LADYBUG_FAILED,
LADYBUG_INVALID_ARGUMENT,
...
LADYBUG_INVALID_FRAMERATE,
LADYBUG_INVALID_OFFSCREEN_BUFFER_SIZE,
LADYBUG_INVALID_JPEG_IMAGE_STRUCTURE,
LADYBUG_NUM_LADYBUG_ERRORS''')
LadybugError = LadybugError._make(range(len(LadybugError._fields)))
What is nice about namedtuple is that the keywords can be given as one long string. It parses the string for you by spaces and commas. This saves me the trouble adding quotes around each item, just add quotes around the whole list. I overwrite the original ‘LadybugError’ string with the enumeration because it is no longer needed.
When a program returns an integer representing an error, it can be passed to _fields[] to get the error string.
err = libc.ladybugGetStreamHeader( pContext, streamHeaderInfo, None ) print err, LadybugError._fields[err]
The output from this is:
20 LADYBUG_NOT_INITIALIZED
The value of err is 20 and ‘LADYBUG_NOT_INITIALIZED’ is the 21st item in the LadybugError enumeration.
Because I only need to interpret numerical feedback, I can drop the “_make(range” line and just take advantage of namedtuple’s builtin parsing:
LadybugError = namedtuple('Enum', '''
LADYBUG_OK,
LADYBUG_FAILED,
LADYBUG_INVALID_ARGUMENT,
...
LADYBUG_INVALID_FRAMERATE,
LADYBUG_INVALID_OFFSCREEN_BUFFER_SIZE,
LADYBUG_INVALID_JPEG_IMAGE_STRUCTURE,
LADYBUG_NUM_LADYBUG_ERRORS''')
This helps me easily find out what an error of 12 means:
print error, LadybugError._fields[error]
prints
12 LADYBUG_COULD_NOT_OPEN_FILE
This works smoothly if the enumeration starts with zero. Otherwise, getting the name through _fields[i] will not be correct. Also, remember that exceptions can be added using ._replace(field=new_value). Here’s an example:
LadybugBusSpeed = LadybugBusSpeed._replace(LADYBUG_SPEED_UNKNOWN=-1) err = -1 print LadybugBusSpeed._fields[LadybugBusSpeed.index(err)]
