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());
715 for (Py_ssize_t i = 0; i < n; ++i)
717 const Enumerator& enumerator = enumerators_[
static_cast<size_t>(i)];
718 assert(!enumToValue_.contains(enumerator.
enumerator));
720 assert(!valueToEnum_.contains(enumerator.
value));
725 return pyEnumerators;
742 std::vector<Enumerator> enumerators_;
787 template <
typename EnumType,
typename ValueType=std::
string>
808 if (PyObject_TypeCheck(obj, (PyTypeObject*)
type))
810 return TPyObjPtr(PyObject_GetAttrString(obj,
"value"));
815 if (!PyUnicode_Check(obj))
817 PyErr_Format(PyExc_TypeError,
"Expected %S or str, got %S",
type, obj);
820 TPyObjPtr o(PyObject_CallFunctionObjArgs(
type, obj,
nullptr));
825 return TPyObjPtr(PyObject_GetAttrString(o.get(),
"value"));
846#define PY_SHADOW_INT_ENUM(dllInterface, t_cppEnum)\
852 struct PyExportTraits<t_cppEnum> \
854 using TEnum = t_cppEnum; \
855 using TEnumDefinition = IntEnumDefinition<TEnum>; \
856 static dllInterface TEnumDefinition enumDefinition; \
857 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
858 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
870#define PY_DECLARE_INT_ENUM_NAME(t_cppEnum, s_name) \
871 ::lass::python::IntEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
880#define PY_DECLARE_INT_ENUM_NAME_DOC(t_cppEnum, s_name, s_doc) \
881 ::lass::python::IntEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
889#define PY_DECLARE_INT_ENUM_EX(t_cppEnum) \
890 ::lass::python::IntEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
910#define PY_SHADOW_INT_FLAG(dllInterface, t_cppEnum)\
916 struct PyExportTraits<t_cppEnum> \
918 using TEnum = t_cppEnum; \
919 using TEnumDefinition = IntFlagDefinition<TEnum>; \
920 static dllInterface TEnumDefinition enumDefinition; \
921 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
922 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
934#define PY_DECLARE_INT_FLAG_NAME(t_cppEnum, s_name) \
935 ::lass::python::IntFlagDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
944#define PY_DECLARE_INT_FLAG_NAME_DOC(t_cppEnum, s_name, s_doc) \
945 ::lass::python::IntFlagDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
954#define PY_DECLARE_INT_FLAG_EX(t_cppEnum) \
955 ::lass::python::IntFlagDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
975#define PY_SHADOW_ENUM(dllInterface, t_cppEnum, t_valueType)\
981 struct PyExportTraits<t_cppEnum> \
983 using TEnum = t_cppEnum; \
984 using TEnumDefinition = EnumDefinition<TEnum, t_valueType>; \
985 static dllInterface TEnumDefinition enumDefinition; \
986 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
987 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
1000#define PY_DECLARE_ENUM_NAME(t_cppEnum, t_valueType, s_name) \
1001 ::lass::python::EnumDefinition<t_cppEnum, t_valueType> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
1011#define PY_DECLARE_ENUM_NAME_DOC(t_cppEnum, t_valueType, s_name, s_doc) \
1012 ::lass::python::EnumDefinition<t_cppEnum, t_valueType> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
1021#define PY_DECLARE_ENUM_EX(t_cppEnum, t_valueType) \
1022 ::lass::python::EnumDefinition<t_cppEnum, t_valueType> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
1041#define PY_SHADOW_STR_ENUM(dllInterface, t_cppEnum)\
1047 struct PyExportTraits<t_cppEnum> \
1049 using TEnum = t_cppEnum; \
1050 using TEnumDefinition = StrEnumDefinition<TEnum>; \
1051 static dllInterface TEnumDefinition enumDefinition; \
1052 static PyObject* build(TEnum value) { return enumDefinition.build(value); } \
1053 static int get(PyObject* obj, TEnum& value) { return enumDefinition.get(obj, value); } \
1064#define PY_DECLARE_STR_ENUM_NAME(t_cppEnum, s_name) \
1065 ::lass::python::StrEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name);
1074#define PY_DECLARE_STR_ENUM_NAME_DOC(t_cppEnum, s_name, s_doc) \
1075 ::lass::python::StrEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition(s_name, s_doc);
1083#define PY_DECLARE_STR_ENUM_EX(t_cppEnum) \
1084 ::lass::python::StrEnumDefinition<t_cppEnum> lass::python::PyExportTraits<t_cppEnum>::enumDefinition
1117#define PY_MODULE_ENUM( i_module, t_cppEnum ) \
1118 LASS_EXECUTE_BEFORE_MAIN_EX\
1119 ( LASS_CONCATENATE( lassExecutePyModuleEnum_, i_module ),\
1120 i_module.addEnum( &::lass::python::PyExportTraits<t_cppEnum>::enumDefinition ); \
1144#define PY_CLASS_ENUM( i_cppClass, t_cppEnum ) \
1145 LASS_EXECUTE_BEFORE_MAIN_EX\
1146 ( LASS_CONCATENATE( lassExecutePyClassEnum_, i_cppClass ),\
1147 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.