56 TPyObjPtr enumMod(PyImport_ImportModule(
"enum"));
61 TPyObjPtr intEnumType(PyObject_GetAttrString(enumMod.get(),
"Enum"));
67 TPyObjPtr args = makeTuple(name, std::move(enumerators));
72 TPyObjPtr type{ PyObject_Call(intEnumType.get(), args.get(), kwargs.get()) };
78 TPyObjPtr enumMod(PyImport_ImportModule(
"enum"));
83 TPyObjPtr intEnumType(PyObject_GetAttrString(enumMod.get(), enumType));
89 TPyObjPtr args = makeTuple(name, std::move(enumerators));
94 TPyObjPtr type{ PyObject_Call(intEnumType.get(), args.get(), kwargs.get()) };
96#if PY_VERSION_HEX < 0x030b0000
104 PyObject* intType =
reinterpret_cast<PyObject*
>(&PyLong_Type);
105 TPyObjPtr intRepr{ PyObject_GetAttrString(intType,
"__repr__") };
106 if (!intRepr || PyObject_SetAttrString(type.get(),
"__str__", intRepr.get()) != 0)
117 return makeIntEnumTypeImpl(
"IntEnum", name, std::move(enumerators), std::move(kwargs));
122#if PY_VERSION_HEX < 0x030b0000
125 PyErr_SetString(PyExc_ValueError,
"FlagBoundary other than KEEP is only supported on Python 3.11 and later");
129 using TInt = std::underlying_type<FlagBoundary>::type;
130 constexpr TInt numBoundaries = 3;
131 const char* boundaries[numBoundaries] = {
"KEEP",
"STRICT",
"CONFORM" };
132 LASS_ENFORCE(
static_cast<TInt
>(boundary) >= 0 &&
static_cast<TInt
>(boundary) < numBoundaries);
133 const char* boundariesStr = boundaries[
static_cast<TInt
>(boundary)];
144 if (PyDict_SetItemString(kwargs.get(),
"boundary", boundaryObj.get()) != 0)
149 return makeIntEnumTypeImpl(
"IntFlag", name, std::move(enumerators), std::move(kwargs));
154#if PY_VERSION_HEX < 0x030b0000
156 PyObject* strType =
reinterpret_cast<PyObject*
>(&PyUnicode_Type);
157 if (PyDict_SetItemString(kwargs.get(),
"type", strType) != 0)
170 TPyObjPtr strStr{ PyObject_GetAttrString(strType,
"__str__") };
171 if (!strStr || PyObject_SetAttrString(type.get(),
"__str__", strStr.get()) != 0)
189 TPyObjPtr args = makeTuple(name, std::move(enumerators));
194 TPyObjPtr type{ PyObject_Call(strEnumType.get(), args.get(), kwargs.get()) };
211 EnumDefinitionBase::~EnumDefinitionBase()
232 return doValueObject(obj);
235 TPyObjPtr EnumDefinitionBase::doValueObject(PyObject* obj)
const
238 if (PyObject_TypeCheck(obj, (PyTypeObject*)
type))
240 return TPyObjPtr(PyObject_GetAttrString(obj,
"value"));
243 PyErr_Format(PyExc_TypeError,
"Expected %S, got %S",
type, obj);
258 TPyObjPtr moduleNameObj(pyBuildSimpleObject(moduleName));
259 if (!moduleNameObj || PyDict_SetItemString(kwargs.get(),
"module", moduleNameObj.get()) != 0)
266 std::string qualName = stde::safe_format(
"%s.%s", scopeName, name_);
267 TPyObjPtr qualNameObj(pyBuildSimpleObject(std::move(qualName)));
268 if (!qualNameObj || PyDict_SetItemString(kwargs.get(),
"qualname", qualNameObj.get()) != 0)
273 type_ = doFreezeDefinition(std::move(kwargs));
282 TPyObjPtr docStr(pyBuildSimpleObject(doc_));
283 if (!docStr || PyObject_SetAttrString(type_.get(),
"__doc__", docStr.get()) != 0)
EnumDefinitionBase(const char *name)
Construct enum definition with name only.
PyObject * type() const
The Python enum type object, after freezeDefinition() has been called.
const char * doc() const
Optional docstring for the Python enum type.
const char * name() const
The name of the Python enum type.
TPyObjPtr valueObject(PyObject *obj) const
Returns the value of an enum instances as a Python object.
PyObject * freezeDefinition(const char *moduleName, const char *scopeName)
Freeze the enum definition and create the Python enum type.
TPyObjPtr makeEnumType(const char *name, TPyObjPtr &&enumerators, TPyObjPtr &&kwargs)
Creates a basic enum.Enum type.
TPyObjPtr makeIntEnumType(const char *name, TPyObjPtr &&enumerators, TPyObjPtr &&kwargs)
Creates an enum.IntEnum type.
TPyObjPtr makeIntFlagType(const char *name, TPyObjPtr &&enumerators, TPyObjPtr &&kwargs, FlagBoundary boundary)
Creates an enum.IntFlag type.
FlagBoundary
Defines the boundary behavior for enum.IntFlag-derived enums.
TPyObjPtr makeStrEnumType(const char *name, TPyObjPtr &&enumerators, TPyObjPtr &&kwargs)
Creates an enum.StrEnum type (or equivalent for Python < 3.11).
@ Keep
Allow any integer value (most permissive)
#define PY_ENFORCE_POINTER(pointer)
Enforce that a Python pointer is not null.
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.