51#include <unordered_map>
224 const char*
name()
const;
225 const char*
doc()
const;
226 PyObject*
type()
const;
264 virtual TPyObjPtr doValueObject(PyObject* obj)
const;
311 template <
typename EnumType>
315 using TEnum = EnumType;
316 using TBase =
typename std::underlying_type<EnumType>::type;
348 enumerators_(enumerators)
359 enumerators_(enumerators)
369 enumerators_.emplace_back(std::move(
name), value);
378 TPyObjPtr args = makeTuple(
static_cast<TBase
>(value));
379 return PyObject_Call(
type(), args.get(),
nullptr);
385 int get(PyObject* obj, TEnum& value)
const
394 if (PyExportTraits<TBase>::get(o.get(), v) != 0)
399 value =
static_cast<TEnum
>(v);
409 const Py_ssize_t n =
static_cast<Py_ssize_t
>(enumerators_.size());
415 for (Py_ssize_t i = 0; i < n; ++i)
417 const Enumerator& enumerator = enumerators_[
static_cast<size_t>(i)];
425 return this->
doMakeEnumType(std::move(pyEnumerators), std::move(kwargs));
434 if (PyObject_TypeCheck(obj, (PyTypeObject*)
type))
436 return TPyObjPtr(PyObject_GetAttrString(obj,
"value"));
440 if (!PyLong_Check(obj))
442 PyErr_Format(PyExc_TypeError,
"Expected %S or int, got %S",
type, obj);
445 TPyObjPtr o(PyObject_CallFunctionObjArgs(
type, obj,
nullptr));
450 return TPyObjPtr(PyObject_GetAttrString(o.get(),
"value"));
462 std::vector<Enumerator> enumerators_;
507 template <
typename EnumType>
511 using TEnum =
typename IntFlagDefinition<EnumType>::TEnum;
512 using TBase =
typename IntFlagDefinition<EnumType>::TBase;
578 template <
typename EnumType,
typename ValueType>
582 using TEnum = EnumType;
583 using TValue = ValueType;
616 enumerators_(enumerators)
627 enumerators_(enumerators)
638 enumerators_.emplace_back(std::move(
name), enumerator, std::move(value));
647 auto val = this->getValue(value);
650 PyErr_Format(PyExc_ValueError,
"%lld is not a valid C++ value for %S",
651 static_cast<PY_LONG_LONG
>(value),
type());
655 return PyObject_Call(
type(), args.get(),
nullptr);
661 int get(PyObject* obj, TEnum& value)
const
670 if (PyExportTraits<TValue>::get(o.get(), v) != 0)
676 auto val = getEnum(v);
680 PyErr_Format(PyExc_ValueError,
"%S is not a valid value for %S", o.get(),
type());
687 std::optional<TValue> getValue(TEnum enumerator)
const
689 auto it = enumToValue_.find(enumerator);
690 if (it == enumToValue_.end())
697 std::optional<TEnum> getEnum(
const TValue& value)
const
699 auto it = valueToEnum_.find(value);
700 if (it == valueToEnum_.end())
713 const Py_ssize_t n =
static_cast<Py_ssize_t
>(enumerators_.size());
719 for (Py_ssize_t i = 0; i < n; ++i)
721 const Enumerator& enumerator = enumerators_[
static_cast<size_t>(i)];
722 assert(!enumToValue_.contains(enumerator.
enumerator));
724 assert(!valueToEnum_.contains(enumerator.
value));
732 return pyEnumerators;
749 std::vector<Enumerator> enumerators_;
794 template <
typename EnumType,
typename ValueType=std::
string>
815 if (PyObject_TypeCheck(obj, (PyTypeObject*)
type))
817 return TPyObjPtr(PyObject_GetAttrString(obj,
"value"));
822 if (!PyUnicode_Check(obj))
824 PyErr_Format(PyExc_TypeError,
"Expected %S or str, got %S",
type, obj);
827 TPyObjPtr o(PyObject_CallFunctionObjArgs(
type, obj,
nullptr));
832 return TPyObjPtr(PyObject_GetAttrString(o.get(),
"value"));
853#define PY_SHADOW_INT_ENUM(dllInterface, t_cppEnum)\
859 struct PyExportTraits<t_cppEnum> \
861 using TEnum = t_cppEnum; \
862 using TEnumDefinition = IntEnumDefinition<TEnum>; \
863 static dllInterface TEnumDefinition enumDefinition; \
864 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
865 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
877#define PY_DECLARE_INT_ENUM_NAME(t_cppEnum, s_name) \
878 ::lass::python::IntEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
887#define PY_DECLARE_INT_ENUM_NAME_DOC(t_cppEnum, s_name, s_doc) \
888 ::lass::python::IntEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
896#define PY_DECLARE_INT_ENUM_EX(t_cppEnum) \
897 ::lass::python::IntEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
917#define PY_SHADOW_INT_FLAG(dllInterface, t_cppEnum)\
923 struct PyExportTraits<t_cppEnum> \
925 using TEnum = t_cppEnum; \
926 using TEnumDefinition = IntFlagDefinition<TEnum>; \
927 static dllInterface TEnumDefinition enumDefinition; \
928 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
929 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
941#define PY_DECLARE_INT_FLAG_NAME(t_cppEnum, s_name) \
942 ::lass::python::IntFlagDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
951#define PY_DECLARE_INT_FLAG_NAME_DOC(t_cppEnum, s_name, s_doc) \
952 ::lass::python::IntFlagDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
961#define PY_DECLARE_INT_FLAG_EX(t_cppEnum) \
962 ::lass::python::IntFlagDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
982#define PY_SHADOW_ENUM(dllInterface, t_cppEnum, t_valueType)\
988 struct PyExportTraits<t_cppEnum> \
990 using TEnum = t_cppEnum; \
991 using TEnumDefinition = EnumDefinition<TEnum, t_valueType>; \
992 static dllInterface TEnumDefinition enumDefinition; \
993 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
994 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
1007#define PY_DECLARE_ENUM_NAME(t_cppEnum, t_valueType, s_name) \
1008 ::lass::python::EnumDefinition<t_cppEnum, t_valueType> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
1018#define PY_DECLARE_ENUM_NAME_DOC(t_cppEnum, t_valueType, s_name, s_doc) \
1019 ::lass::python::EnumDefinition<t_cppEnum, t_valueType> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
1028#define PY_DECLARE_ENUM_EX(t_cppEnum, t_valueType) \
1029 ::lass::python::EnumDefinition<t_cppEnum, t_valueType> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
1048#define PY_SHADOW_STR_ENUM(dllInterface, t_cppEnum)\
1054 struct PyExportTraits<t_cppEnum> \
1056 using TEnum = t_cppEnum; \
1057 using TEnumDefinition = StrEnumDefinition<TEnum>; \
1058 static dllInterface TEnumDefinition enumDefinition; \
1059 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
1060 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
1071#define PY_DECLARE_STR_ENUM_NAME(t_cppEnum, s_name) \
1072 ::lass::python::StrEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
1081#define PY_DECLARE_STR_ENUM_NAME_DOC(t_cppEnum, s_name, s_doc) \
1082 ::lass::python::StrEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
1090#define PY_DECLARE_STR_ENUM_EX(t_cppEnum) \
1091 ::lass::python::StrEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
1124#define PY_MODULE_ENUM( i_module, t_cppEnum ) \
1125 LASS_EXECUTE_BEFORE_MAIN_EX\
1126 ( LASS_CONCATENATE( lassExecutePyModuleEnum_, i_module ),\
1127 i_module.addEnum( &::lass::python::PyExportTraits<t_cppEnum>::enumDefinition ); \
1151#define PY_CLASS_ENUM( i_cppClass, t_cppEnum ) \
1152 LASS_EXECUTE_BEFORE_MAIN_EX\
1153 ( LASS_CONCATENATE( lassExecutePyClassEnum_, i_cppClass ),\
1154 i_cppClass ::_lassPyClassDef.addInnerEnum( &::lass::python::PyExportTraits<t_cppEnum>::enumDefinition ); \
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.
EnumDefinition(const char *name, const char *doc, std::initializer_list< Enumerator > enumerators)
Construct with name, documentation, and enumerators list.
int get(PyObject *obj, TEnum &value) const
Extracts a C++ enum value from a Python object.
EnumDefinition(const char *name)
Construct with enum name only.
TPyObjPtr freezeEnumerators()
Converts stored enumerators to Python tuple format and builds lookup tables.
PyObject * build(TEnum value) const
Creates a Python enum instance from a C++ enum value.
TPyObjPtr doFreezeDefinition(TPyObjPtr &&kwargs) override
Creates a generic enum.Enum-derived type.
void addEnumerator(std::string name, TEnum enumerator, TValue value)
Add an enumerator to the definition.
EnumDefinition(const char *name, std::initializer_list< Enumerator > enumerators)
Construct with name and enumerators list.
EnumDefinition(const char *name, const char *doc)
Construct with name and documentation.
IntEnumDefinition(const char *name, const char *doc)
Construct with name and documentation.
IntEnumDefinition(const char *name, std::initializer_list< Enumerator > enumerators)
Construct with name and enumerators list.
void addEnumerator(std::string name, TEnum value)
Add an enumerator member to the definition.
TPyObjPtr doFreezeDefinition(TPyObjPtr &&kwargs) override
Creates an enum.IntEnum-derived type.
TPyObjPtr doValueObject(PyObject *obj) const override
Extracts integer values from enum instances or integer objects.
IntEnumDefinition(const char *name, const char *doc, std::initializer_list< Enumerator > enumerators)
Construct with name, documentation, and enumerators list.
PyObject * build(TEnum value) const
Creates a Python enum instance from a C++ enum value.
int get(PyObject *obj, TEnum &value) const
Extracts a C++ enum value from a Python object.
IntEnumDefinition(const char *name)
Construct with enum name only.
virtual TPyObjPtr doMakeEnumType(TPyObjPtr &&enumerators, TPyObjPtr &&kwargs)
Creates the actual enum.IntEnum type object.
IntFlagDefinition(const char *name, const char *doc, FlagBoundary boundary, std::initializer_list< Enumerator > enumerators)
Construct with name, documentation, boundary behavior, and enumerators.
TPyObjPtr doMakeEnumType(TPyObjPtr &&enumerators, TPyObjPtr &&kwargs) override
Creates an enum.IntFlag-derived type with boundary behavior.
acquire the GIL for the current scope.
Definition of an enum.StrEnum-derived enum type in Python.
TPyObjPtr doValueObject(PyObject *obj) const override
Extracts string values from enum instances or string objects.
TPyObjPtr doFreezeDefinition(TPyObjPtr &&kwargs) override
Creates an enum.StrEnum-derived type.
a map-like container built on a sorted vector (write-rarely, read-many)
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)
@ Strict
Only allow exact flag combinations.
@ Conform
Mask to defined bits only.
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
PyObject * fromSharedPtrToNakedCast(const util::SharedPtr< T, PyObjectStorage, PyObjectCounter > &object)
fromSharedPtrToNakedCast.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.
Represents a single enumerator with name, C++ enum value, and Python value.
TEnum enumerator
Corresponding C++ enum value.
std::string name
Python name for the enumerator.
TValue value
Python value for the enumerator.
Represents a single enumerator member with name and C++ enum value.
TEnum enumerator
Corresponding C++ enum value.
std::string name
Python name for the member.