Spaces:
Build error
Build error
#################### EnumBase #################### | |
cimport cython | |
cdef extern from *: | |
int PY_VERSION_HEX | |
cdef object __Pyx_OrderedDict | |
if PY_VERSION_HEX >= 0x03060000: | |
__Pyx_OrderedDict = dict | |
else: | |
from collections import OrderedDict as __Pyx_OrderedDict | |
cdef class __Pyx_EnumMeta(type): | |
def __init__(cls, name, parents, dct): | |
type.__init__(cls, name, parents, dct) | |
cls.__members__ = __Pyx_OrderedDict() | |
def __iter__(cls): | |
return iter(cls.__members__.values()) | |
def __getitem__(cls, name): | |
return cls.__members__[name] | |
# @cython.internal | |
cdef object __Pyx_EnumBase | |
class __Pyx_EnumBase(int, metaclass=__Pyx_EnumMeta): | |
def __new__(cls, value, name=None): | |
for v in cls: | |
if v == value: | |
return v | |
if name is None: | |
raise ValueError("Unknown enum value: '%s'" % value) | |
res = int.__new__(cls, value) | |
res.name = name | |
setattr(cls, name, res) | |
cls.__members__[name] = res | |
return res | |
def __repr__(self): | |
return "<%s.%s: %d>" % (self.__class__.__name__, self.name, self) | |
def __str__(self): | |
return "%s.%s" % (self.__class__.__name__, self.name) | |
if PY_VERSION_HEX >= 0x03040000: | |
from enum import IntEnum as __Pyx_EnumBase | |
cdef object __Pyx_FlagBase | |
class __Pyx_FlagBase(int, metaclass=__Pyx_EnumMeta): | |
def __new__(cls, value, name=None): | |
for v in cls: | |
if v == value: | |
return v | |
res = int.__new__(cls, value) | |
if name is None: | |
# some bitwise combination, no validation here | |
res.name = "" | |
else: | |
res.name = name | |
setattr(cls, name, res) | |
cls.__members__[name] = res | |
return res | |
def __repr__(self): | |
return "<%s.%s: %d>" % (self.__class__.__name__, self.name, self) | |
def __str__(self): | |
return "%s.%s" % (self.__class__.__name__, self.name) | |
if PY_VERSION_HEX >= 0x03060000: | |
from enum import IntFlag as __Pyx_FlagBase | |
#################### EnumType #################### | |
#@requires: EnumBase | |
cdef extern from *: | |
object {{enum_to_pyint_func}}({{name}} value) | |
cdef dict __Pyx_globals = globals() | |
if PY_VERSION_HEX >= 0x03060000: | |
# create new IntFlag() - the assumption is that C enums are sufficiently commonly | |
# used as flags that this is the most appropriate base class | |
{{name}} = __Pyx_FlagBase('{{name}}', [ | |
{{for item in items}} | |
('{{item}}', {{enum_to_pyint_func}}({{item}})), | |
{{endfor}} | |
# Try to look up the module name dynamically if possible | |
], module=__Pyx_globals.get("__module__", '{{static_modname}}')) | |
if PY_VERSION_HEX >= 0x030B0000: | |
# Python 3.11 starts making the behaviour of flags stricter | |
# (only including powers of 2 when iterating). Since we're using | |
# "flag" because C enums *might* be used as flags, not because | |
# we want strict flag behaviour, manually undo some of this. | |
{{name}}._member_names_ = list({{name}}.__members__) | |
{{if enum_doc is not None}} | |
{{name}}.__doc__ = {{ repr(enum_doc) }} | |
{{endif}} | |
{{for item in items}} | |
__Pyx_globals['{{item}}'] = {{name}}.{{item}} | |
{{endfor}} | |
else: | |
class {{name}}(__Pyx_FlagBase): | |
{{ repr(enum_doc) if enum_doc is not None else 'pass' }} | |
{{for item in items}} | |
__Pyx_globals['{{item}}'] = {{name}}({{enum_to_pyint_func}}({{item}}), '{{item}}') | |
{{endfor}} | |
#################### CppScopedEnumType #################### | |
#@requires: EnumBase | |
cdef dict __Pyx_globals = globals() | |
if PY_VERSION_HEX >= 0x03040000: | |
__Pyx_globals["{{name}}"] = __Pyx_EnumBase('{{name}}', [ | |
{{for item in items}} | |
('{{item}}', <{{underlying_type}}>({{name}}.{{item}})), | |
{{endfor}} | |
], module=__Pyx_globals.get("__module__", '{{static_modname}}')) | |
else: | |
__Pyx_globals["{{name}}"] = type('{{name}}', (__Pyx_EnumBase,), {}) | |
{{for item in items}} | |
__Pyx_globals["{{name}}"](<{{underlying_type}}>({{name}}.{{item}}), '{{item}}') | |
{{endfor}} | |
{{if enum_doc is not None}} | |
__Pyx_globals["{{name}}"].__doc__ = {{ repr(enum_doc) }} | |
{{endif}} | |
#################### EnumTypeToPy #################### | |
{{if module_name}} | |
cdef object __pyx_imported_enum_{{funcname}} = None | |
{{endif}} | |
cdef {{funcname}}({{name}} c_val): | |
cdef object __pyx_enum | |
{{if module_name}} | |
global __pyx_imported_enum_{{funcname}} | |
# There's a complication here: the Python enum wrapping is only generated | |
# for enums defined in the same module that they're used in. Therefore, if | |
# the enum was cimported from a different module, we try to import it. | |
# If that fails we return an int equivalent as the next best option. | |
if __pyx_imported_enum_{{funcname}} is None: | |
try: | |
from {{module_name}} import {{name}} as __pyx_imported_enum_{{funcname}} | |
except ImportError: | |
__pyx_imported_enum_{{funcname}} = False # False indicates "don't try again" | |
import warnings | |
warnings.warn( | |
f"enum class {{name}} not importable from {{module_name}}. " | |
"You are probably using a cpdef enum declared in a .pxd file that " | |
"does not have a .py or .pyx file.") | |
if __pyx_imported_enum_{{funcname}} is False: | |
# shortcut - if the import failed there's no point repeating it | |
# (and repeating the warning) | |
return <{{underlying_type}}>c_val | |
__pyx_enum = __pyx_imported_enum_{{funcname}} | |
{{else}} | |
__pyx_enum = {{name}} | |
{{endif}} | |
# TODO - Cython only manages to optimize C enums to a switch currently | |
if 0: | |
pass | |
{{for item in items}} | |
elif c_val == {{name}}.{{item}}: | |
return __pyx_enum.{{item}} | |
{{endfor}} | |
else: | |
underlying_c_val = <{{underlying_type}}>c_val | |
{{if is_flag}} | |
return __pyx_enum(underlying_c_val) | |
{{else}} | |
raise ValueError(f"{underlying_c_val} is not a valid {{name}}") | |
{{endif}} | |