Skip to content

Commit 5925854

Browse files
committed
Sync CPPEnum
1 parent 5b2ea74 commit 5925854

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

src/CPPEnum.cxx

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "CPyCppyy.h"
33
#include "CPPEnum.h"
44
#include "PyStrings.h"
5+
#include "TypeManip.h"
56
#include "Utility.h"
67

78

@@ -18,9 +19,9 @@ static PyObject* pytype_from_enum_type(const std::string& enum_type)
1819
}
1920

2021
//----------------------------------------------------------------------------
21-
PyObject* CPyCppyy::pyval_from_enum(const std::string& enum_type, PyObject* pytype,
22-
PyObject* btype, Cppyy::TCppScope_t enum_constant) {
23-
long long llval = Cppyy::GetEnumDataValue(enum_constant);
22+
static PyObject* pyval_from_enum(const std::string& enum_type, PyObject* pytype,
23+
PyObject* btype, Cppyy::TCppEnum_t etype, Cppyy::TCppIndex_t idata) {
24+
long long llval = Cppyy::GetEnumDataValue(etype, idata);
2425

2526
if (enum_type == "bool") {
2627
PyObject* result = (bool)llval ? Py_True : Py_False;
@@ -37,13 +38,11 @@ PyObject* CPyCppyy::pyval_from_enum(const std::string& enum_type, PyObject* pyty
3738
else
3839
bval = PyLong_FromLongLong(llval);
3940

40-
if (pytype && btype) {
4141
PyObject* args = PyTuple_New(1);
4242
PyTuple_SET_ITEM(args, 0, bval);
43-
bval = ((PyTypeObject*)btype)->tp_new((PyTypeObject*)pytype, args, nullptr);
43+
PyObject* result = ((PyTypeObject*)btype)->tp_new((PyTypeObject*)pytype, args, nullptr);
4444
Py_DECREF(args);
45-
}
46-
return bval;
45+
return result;
4746
}
4847

4948

@@ -60,8 +59,6 @@ static PyObject* enum_repr(PyObject* self)
6059
{
6160
using namespace CPyCppyy;
6261

63-
PyObject* kls_scope = PyObject_GetAttr((PyObject*)Py_TYPE(self), PyStrings::gThisModule);
64-
if (!kls_scope) PyErr_Clear();
6562
PyObject* kls_cppname = PyObject_GetAttr((PyObject*)Py_TYPE(self), PyStrings::gCppName);
6663
if (!kls_cppname) PyErr_Clear();
6764
PyObject* obj_cppname = PyObject_GetAttr(self, PyStrings::gCppName);
@@ -70,7 +67,7 @@ static PyObject* enum_repr(PyObject* self)
7067

7168
PyObject* repr = nullptr;
7269
if (kls_cppname && obj_cppname && obj_str) {
73-
const std::string resolved = Cppyy::ResolveEnum(PyLong_AsVoidPtr(kls_scope));
70+
const std::string resolved = Cppyy::ResolveEnum(CPyCppyy_PyText_AsString(kls_cppname));
7471
repr = CPyCppyy_PyText_FromFormat("(%s::%s) : (%s) %s",
7572
CPyCppyy_PyText_AsString(kls_cppname), CPyCppyy_PyText_AsString(obj_cppname),
7673
resolved.c_str(), CPyCppyy_PyText_AsString(obj_str));
@@ -140,12 +137,12 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco
140137

141138
CPPEnum* pyenum = nullptr;
142139

143-
Cppyy::TCppScope_t etype = scope;
144-
const std::string& ename = Cppyy::GetScopedFinalName(scope);
140+
const std::string& ename = scope == Cppyy::gGlobalScope ? name : Cppyy::GetScopedFinalName(scope)+"::"+name;
141+
Cppyy::TCppEnum_t etype = Cppyy::GetEnum(scope, name);
145142
if (etype) {
146143
// create new enum type with labeled values in place, with a meta-class
147144
// to make sure the enum values are read-only
148-
const std::string& resolved = Cppyy::ResolveEnum(etype);
145+
const std::string& resolved = Cppyy::ResolveEnum(ename);
149146
PyObject* pyside_type = pytype_from_enum_type(resolved);
150147
PyObject* pymetabases = PyTuple_New(1);
151148
PyObject* btype = (PyObject*)Py_TYPE(pyside_type);
@@ -173,6 +170,14 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco
173170
PyDict_SetItem(dct, PyStrings::gUnderlying, pyresolved);
174171
Py_DECREF(pyresolved);
175172

173+
// add the __module__ to allow pickling
174+
std::string modname = TypeManip::extract_namespace(ename);
175+
TypeManip::cppscope_to_pyscope(modname); // :: -> .
176+
if (!modname.empty()) modname = "."+modname;
177+
PyObject* pymodname = CPyCppyy_PyText_FromString(("cppyy.gbl"+modname).c_str());
178+
PyDict_SetItem(dct, PyStrings::gModule, pymodname);
179+
Py_DECREF(pymodname);
180+
176181
// create the actual enum class
177182
args = Py_BuildValue((char*)"sOO", name.c_str(), pybases, dct);
178183
Py_DECREF(pybases);
@@ -186,10 +191,10 @@ CPyCppyy::CPPEnum* CPyCppyy::CPPEnum_New(const std::string& name, Cppyy::TCppSco
186191
((PyTypeObject*)pyenum)->tp_str = ((PyTypeObject*)pyside_type)->tp_repr;
187192

188193
// collect the enum values
189-
std::vector<Cppyy::TCppScope_t> econstants = Cppyy::GetEnumConstants(etype);
190-
for (auto *econstant : econstants) {
191-
PyObject* val = pyval_from_enum(resolved, pyenum, pyside_type, econstant);
192-
PyObject* pydname = CPyCppyy_PyText_FromString(Cppyy::GetFinalName(econstant).c_str());
194+
Cppyy::TCppIndex_t ndata = Cppyy::GetNumEnumData(etype);
195+
for (Cppyy::TCppIndex_t idata = 0; idata < ndata; ++idata) {
196+
PyObject* val = pyval_from_enum(resolved, pyenum, pyside_type, etype, idata);
197+
PyObject* pydname = CPyCppyy_PyText_FromString(Cppyy::GetEnumDataName(etype, idata).c_str());
193198
PyObject_SetAttr(pyenum, pydname, val);
194199
PyObject_SetAttr(val, PyStrings::gCppName, pydname);
195200
Py_DECREF(pydname);

0 commit comments

Comments
 (0)