How do I Cythonize a Python Enum mixin class?

98 views
Skip to first unread message

Uri Okrent

unread,
May 12, 2019, 1:17:08 PM5/12/19
to cython-users

I have a Enum mixin (serde_enum.py) type that adds dump/load methods to the Enum for serialization/deserialization, that looks something like this:
from enum import Enum

class Primitive:

   
def load(self):
       
pass

   
def dump(self):
       
pass



I can create an Enum `Apple` like so that has the extra `load()` and `dump()` methods:

In [1]: import serde_enum                                                                                                        

In [2]: from enum import Enum                                                                                                    

In [3]: Apple = Enum('Apple', ['RED', 'GREEN', 'BLUE'], type=serde_enum.Primitive)                                              

In [4]: Apple.__members__                                                                                                        
Out[4]:
mappingproxy
({'RED': <Apple.RED: 1>,
             
'GREEN': <Apple.GREEN: 2>,
             
'BLUE': <Apple.BLUE: 3>})

In [5]: Apple.RED.dump                                                                                                          
Out[5]: <bound method Primitive.dump of <Apple.RED: 1>>

In [6]: r = Apple(1)


Now, if I try to cythonize the mixin class (to speed up the slow load/dump code), it breaks the enum.  Here is my cython code (serde_enum.pyx):

# cython: language_level=3
from enum import Enum

cdef
class Primitive:

   
def load(self):
       
pass

   
def dump(self):
       
pass


class SerDeEnum(Primitive, Enum):
   
pass


but now:
In [1]: from enum import Enum                                                                                                    

In [2]: import serde_enum                                                                                                        

In [3]: Apple = Enum('Apple', ['RED', 'GREEN', 'BLUE'], type=serde_enum.Primitive)                                              

In [4]: Apple.__members__                                                                                                        
Out[4]:
mappingproxy
({'RED': <Apple.RED: <serde_enum.Primitive object at 0x7ff91adc2ea0>>,
             
'GREEN': <Apple.GREEN: <serde_enum.Primitive object at 0x7ff91adc2eb0>>,
             
'BLUE': <Apple.BLUE: <serde_enum.Primitive object at 0x7ff91adc2ec0>>})

In [5]: Apple.RED.dump                                                                                                          
Out[5]: <function Apple.dump>

In [6]: r = Apple(1)                                                                                                            
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-670cfcdec304> in <module>
----> 1 r = Apple(1)

/usr/lib/python3.6/enum.py in __call__(cls, value, names, module, qualname, type, start)
   
291         """
    292         if names is None:  # simple value lookup
--> 293             return cls.__new__(cls, value)
    294         # otherwise, functional API: we're creating a new Enum type
    295         return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)

/usr/lib/python3.6/enum.py in __new__(cls, value)
    533                     return member
    534         # still not found -- try _missing_ hook
--> 535         return cls._missing_(value)
    536
    537     def _generate_next_value_(name, start, count, last_values):

/usr/lib/python3.6/enum.py in _missing_(cls, value)
    546     @classmethod
    547     def _missing_(cls, value):
--> 548         raise ValueError("
%r is not a valid %s" % (value, cls.__name__))
    549
    550     def __repr__(self):

ValueError: 1 is not a valid Apple


The same thing happens if I create the enum with the mixin class by inheritance using the `SerDeEnum` class I defined above, like `Apple = serde_enum.SerDeEnum('Apple', ['RED', 'GREEN', 'BLUE'])`
Reply all
Reply to author
Forward
0 new messages