Created
March 23, 2025 19:05
-
-
Save tritao/1951ce1fb58dcc641b995f85ee475e05 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static PyObject* createMyConstantsEnum() | |
{ | |
// Import the Python 'enum' module. | |
PyObject* enumModule = PyImport_ImportModule("enum"); | |
if (!enumModule) { | |
PyErr_SetString(PyExc_ImportError, "Failed to import the enum module"); | |
return nullptr; | |
} | |
// Try to get StrEnum from the enum module (Python 3.11 and above). | |
PyObject* strEnumType = PyObject_GetAttrString(enumModule, "StrEnum"); | |
PyObject* bases = nullptr; | |
if (strEnumType) { | |
// If StrEnum is available, use it as the sole base. | |
bases = PyTuple_New(1); | |
if (!bases) { | |
Py_DECREF(strEnumType); | |
Py_DECREF(enumModule); | |
return nullptr; | |
} | |
// PyTuple_SET_ITEM steals the reference to strEnumType. | |
PyTuple_SET_ITEM(bases, 0, strEnumType); | |
} else { | |
// Fallback for Python 3.10: clear the error and use (str, Enum) as bases. | |
PyErr_Clear(); | |
// Get Enum from the enum module. | |
PyObject* enumType = PyObject_GetAttrString(enumModule, "Enum"); | |
if (!enumType) { | |
Py_DECREF(enumModule); | |
PyErr_SetString(PyExc_AttributeError, "Failed to get 'Enum' from the enum module"); | |
return nullptr; | |
} | |
// Get built-in str type. | |
PyObject* strType = (PyObject*)&PyUnicode_Type; | |
Py_INCREF(strType); | |
// Create a tuple with two bases: (str, Enum). Order is important. | |
bases = PyTuple_New(2); | |
if (!bases) { | |
Py_DECREF(enumType); | |
Py_DECREF(strType); | |
Py_DECREF(enumModule); | |
return nullptr; | |
} | |
PyTuple_SET_ITEM(bases, 0, strType); // steals reference to strType. | |
PyTuple_SET_ITEM(bases, 1, enumType); // steals reference to enumType. | |
} | |
Py_DECREF(enumModule); | |
// Create a dictionary for the enum members. | |
PyObject* enumDict = PyDict_New(); | |
if (!enumDict) { | |
Py_DECREF(bases); | |
return nullptr; | |
} | |
// Define constant members: | |
// CONSTANT_ONE = "one" | |
// CONSTANT_TWO = "two" | |
// CONSTANT_THREE = "three" | |
PyObject* one = PyUnicode_FromString("one"); | |
PyObject* two = PyUnicode_FromString("two"); | |
PyObject* three = PyUnicode_FromString("three"); | |
if (!one || !two || !three) { | |
Py_XDECREF(one); | |
Py_XDECREF(two); | |
Py_XDECREF(three); | |
Py_DECREF(enumDict); | |
Py_DECREF(bases); | |
return nullptr; | |
} | |
PyDict_SetItemString(enumDict, "CONSTANT_ONE", one); | |
PyDict_SetItemString(enumDict, "CONSTANT_TWO", two); | |
PyDict_SetItemString(enumDict, "CONSTANT_THREE", three); | |
Py_DECREF(one); | |
Py_DECREF(two); | |
Py_DECREF(three); | |
// Create the name for the new enum type. | |
PyObject* name = PyUnicode_FromString("MyConstants"); | |
if (!name) { | |
Py_DECREF(bases); | |
Py_DECREF(enumDict); | |
return nullptr; | |
} | |
// Create the new type by calling the metatype (PyType_Type). | |
// The arguments are: name, bases tuple, and the dictionary of attributes. | |
PyObject* newEnumType = PyObject_CallFunctionObjArgs( | |
(PyObject*)&PyType_Type, // the metatype 'type' | |
name, | |
bases, | |
enumDict, | |
nullptr | |
); | |
Py_DECREF(name); | |
Py_DECREF(bases); | |
Py_DECREF(enumDict); | |
return newEnumType; // This new type is either based on enum.StrEnum or (str, Enum). | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment