C enums revisited

Just found an easy way to make enums.

(LADYBUG_DISABLE,
   LADYBUG_EDGE_SENSING,
   LADYBUG_NEAREST_NEIGHBOR,
   LADYBUG_NEAREST_NEIGHBOR_FAST,
   LADYBUG_RIGOROUS,
   LADYBUG_DOWNSAMPLE4,
   LADYBUG_MONO,
   LADYBUG_HQLINEAR) = xrange(8)

This is a simple way to make enums. Overriden values need to be added separately.
Unless a method to retrieve the enum name from the integer is needed, in that case you make another list (or dict for unordered values) to retrieve the enum word. The namedtuple is the best way if you don’t want to put quotes around each word in a long list.
For a ctypes version, you can use map()

(...) = map(c_int, xrange(8))

I guess there really isn’t a need to go the reverse direction unless you want to read the value for debugging. In my novice understanding when first learning ctypes I thought it would be necessary to have this option. Here how to make a list and then enumerate from that list:

LadybugColorProcessingMethod = '''
   LADYBUG_DISABLE
   LADYBUG_EDGE_SENSING
   LADYBUG_NEAREST_NEIGHBOR
   LADYBUG_NEAREST_NEIGHBOR_FAST
   LADYBUG_RIGOROUS
   LADYBUG_DOWNSAMPLE4
   LADYBUG_MONO
   LADYBUG_HQLINEAR
   '''.split()
for n, v in zip( LadybugColorProcessingMethod, range(8) ):
    exec( n + ' = ' + str(v) )

A namedtuple implementation might be preferred if the same name might be used for different values in different enums.

C++ enum to Python namedtuple (cont.)

Here is a way to convert a C++ enum with values to Python.
C++ code:

typedef enum
{
   LADYBUG_RAW_CAM0           = ( 0x1 << 0 ),
   LADYBUG_RAW_CAM1           = ( 0x1 << 1 ),
   LADYBUG_RAW_CAM2           = ( 0x1 << 2 ),
   LADYBUG_RAW_CAM3           = ( 0x1 << 3 ),
   LADYBUG_RAW_CAM4           = ( 0x1 << 4 ),
   LADYBUG_RAW_CAM5           = ( 0x1 << 5 ),
   LADYBUG_ALL_RAW_IMAGES     =  0x0000003F,

   ...

   LADYBUG_PANORAMIC          = ( 0x1 << 12 ),

   LADYBUG_DOME               = ( 0x1 << 13 ),

   LADYBUG_SPHERICAL          = ( 0x1 << 14 ),

   LADYBUG_ALL_CAMERAS_VIEW   = ( 0x1 << 15 ),

   LADYBUG_ALL_OUTPUT_IMAGE   = 0x7FFFFFFF,

} LadybugOutputImage

The Python version:

LadybugOutputImage = dict(
   LADYBUG_RAW_CAM0           = ( 0x1 << 0 ),
   LADYBUG_RAW_CAM1           = ( 0x1 << 1 ),
   LADYBUG_RAW_CAM2           = ( 0x1 << 2 ),
   LADYBUG_RAW_CAM3           = ( 0x1 << 3 ),
   LADYBUG_RAW_CAM4           = ( 0x1 << 4 ),
   LADYBUG_RAW_CAM5           = ( 0x1 << 5 ),
   LADYBUG_ALL_RAW_IMAGES     =  0x0000003F,

   ...

   LADYBUG_PANORAMIC          = ( 0x1 << 12 ),

   LADYBUG_DOME               = ( 0x1 << 13 ),

   LADYBUG_SPHERICAL          = ( 0x1 << 14 ),

   LADYBUG_ALL_CAMERAS_VIEW   = ( 0x1 << 15 ),

   LADYBUG_ALL_OUTPUT_IMAGE   = 0x7FFFFFFF  )
LadybugOutputImage = namedtuple('Enum',
                       LadybugOutputImage.keys() )(**LadybugOutputImage)

Or even better, just get rid of all the packaging and commas on this type if it’s not too long and you have the patience. But you will also have to correct the indenting. Maybe there is a program out there that can do this editing for you.

   LADYBUG_RAW_CAM0           = ( 0x1 << 0 )
   LADYBUG_RAW_CAM1           = ( 0x1 << 1 )
   LADYBUG_RAW_CAM2           = ( 0x1 << 2 )
   LADYBUG_RAW_CAM3           = ( 0x1 << 3 )
   ...
   LADYBUG_ALL_CAMERAS_VIEW   = ( 0x1 << 15 )
   LADYBUG_ALL_OUTPUT_IMAGE   = 0x7FFFFFFF

Python Enum continued

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)]

Python Enum with namedtuple

I saw a question asking how to do enum in Python and because I just learned about namedtuple I thought it should be an easy thing to do.

For an enum starting with 0, you can write it like this:

from collections import namedtuple as ntup

animalnames = 'Dog','Cat','Mouse','Horse','Bunny'

Animal = ntup('Enum', animalnames)._make(range(len(animalnames)))

Then you can

print Animal.Horse

and get 3 returned.
Also, because it is also a tuple, you can access it by the index:

Animal.Horse == Animal[3]

For an enum starting at 1 or higher there are a few ways.
You can use arange and add an offset:

from numpy import arange
animalnames = 'Dog','Cat','Mouse','Horse','Bunny'
Animal = ntup('Enum', animalnames)._make(3+arange(len(animalnames)))

Or stay with range:

animalnames = 'Dog','Cat','Mouse','Horse','Bunny'
Animal = ntup('Enum', animalnames)._make(range(3,3+len(animalnames)))

What is be nice about using this method is that it is still a tuple. Here are few lines and their output:

print Animal
print Animal._fields
print Animal[:]
print list(Animal)
print zip(Animal._fields, Animal)
Enum(Dog=3, Cat=4, Mouse=5, Horse=6, Bunny=7)
('Dog', 'Cat', 'Mouse', 'Horse', 'Bunny')
(3, 4, 5, 6, 7)
[3, 4, 5, 6, 7]
[('Dog', 3), ('Cat', 4), ('Mouse', 5), ('Horse', 6), ('Bunny', 7)]