Как я могу Cythonize класс смешивания Python Enum? - PullRequest
1 голос
/ 12 мая 2019

У меня есть тип Enum mixin (serde_enum.py), который добавляет методы дампа / загрузки в Enum для сериализации / десериализации, который выглядит примерно так:

from enum import Enum

class Primitive:

    def load(self):
        pass

    def dump(self):
        pass

Я могу создать Enum Apple, например, с дополнительными load() и dump() методами:

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)

Теперь, если я попытаюсь цитонизировать класс mixin (чтобы ускорить медленный код загрузки / выгрузки), он нарушит перечисление. Вот мой код Cython (serde_enum.pyx):

# cython: language_level=3
from enum import Enum

cdef class Primitive:

    cpdef load(self):
        pass

    cpdef dump(self):
        pass


class SerDeEnum(Primitive, Enum):
    pass

но сейчас:

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

То же самое происходит, если я создаю перечисление с классом mixin по наследству, используя SerDeEnum класс I, определенный выше, как Apple = serde_enum.SerDeEnum('Apple', ['RED', 'GREEN', 'BLUE'])

...