7 #define PYROOT_INSPECTOR_DBG 0
17 #include "TClassRef.h"
18 #include "TDataMember.h"
19 #include "TDataType.h"
20 #include "TVirtualCollectionProxy.h"
21 #include "TClassEdit.h"
27 #include "CPyCppyy/API.h"
32 #define Py_True ( (PyObject*)(void*)&_Py_TrueStruct )
36 #define Py_False ( (PyObject*)(void*)&_Py_ZeroStruct )
51 to_pyobj(
void*
ptr, EDataType mbr_dtype)
58 return Py_BuildValue(
"c", ((
char*)
ptr)[0] & 0x7F);
61 return Py_BuildValue(
"i", (*(
bool*)
ptr) ? 1 : 0);
64 return Py_BuildValue(
"h", (*(
short*)
ptr));
67 return Py_BuildValue(
"H", (*(
unsigned short*)
ptr));
71 return Py_BuildValue(
"i", (*(
int*)
ptr));
74 return Py_BuildValue(
"I", (*(
unsigned int*)
ptr));
78 return Py_BuildValue(
"d", (*(
double*)
ptr));
82 return Py_BuildValue(
"f", (*(
float*)
ptr));
85 return Py_BuildValue(
"l", (*(
long*)
ptr));
88 return Py_BuildValue(
"k", (*(
unsigned long*)
ptr));
91 return Py_BuildValue(
"L", (*(Long64_t*)
ptr));
94 return Py_BuildValue(
"K", (*(ULong64_t*)
ptr));
97 return Py_BuildValue(
"s", (*(
char**)
ptr));
103 return PyUnicode_FromString(
"(UNKNOWN)");
112 #if PYROOT_INSPECTOR_DBG
117 std::string
s = py_str && PyUnicode_Check(py_str)
118 ? PyUnicode_AsUTF8(py_str)
142 if (!TPython::CPPInstance_Check(pyobj)) {
145 PyObject *v1 = pyobj; Py_XINCREF(pyobj);
146 PyTuple_SET_ITEM(
val, 0,
v0);
147 PyTuple_SET_ITEM(
val, 1, v1);
148 PyList_Append(pystack,
val);
153 static const std::unordered_set<std::string> vecnames {
155 "std::vector<float>",
157 "std::vector<double>",
160 "vector<unsigned int>",
161 "std::vector<unsigned int>",
163 "std::vector<short>",
164 "vector<unsigned short>",
165 "std::vector<unsigned short>",
168 "vector<unsigned char>",
169 "std::vector<unsigned char>",
172 "vector<unsigned long>",
173 "std::vector<unsigned long>",
175 "std::vector<long long>",
176 "vector<unsigned long long>",
177 "std::vector<unsigned long long>",
180 std::string clsname = tcls ? tcls->GetName() :
"";
182 (tcls->IsTObject() && clsname !=
"TLorentzVector") ||
183 (retvecs && vecnames.count (clsname) > 0))
188 PyObject *v1 = pyobj; Py_XINCREF(pyobj);
189 PyTuple_SET_ITEM(
val, 0,
v0);
190 PyTuple_SET_ITEM(
val, 1, v1);
191 PyList_Append(pystack,
val);
195 void *
obj = TPython::CPPInstance_AsVoidPtr(pyobj);
197 if (clsname ==
"string") {
198 std::string *
str = (std::string*)
obj;
202 PyTuple_SET_ITEM(
val, 0,
v0);
203 PyTuple_SET_ITEM(
val, 1, v1);
204 PyList_Append(pystack,
val);
209 if (clsname.starts_with(
"pair<") ||
210 clsname.starts_with(
"std::pair<")) {
213 PyObject *v1 = PyObject_GetAttrString(pyobj,
"first");
214 PyObject *v1_name = ::new_pylist(pyobj_name,
v0);
215 recurse_pyinspect(v1, v1_name, pystack, persistentOnly, retvecs);
222 PyObject *
v0 = PyUnicode_FromString(
"second");
223 PyObject *v1 = PyObject_GetAttrString(pyobj,
"second");
224 PyObject *v1_name = ::new_pylist(pyobj_name,
v0);
225 recurse_pyinspect(v1, v1_name, pystack, persistentOnly, retvecs);
233 if (clsname.starts_with(
"ElementLink<")) {
234 PyObject*
key = PyObject_CallMethod (pyobj,
"key",
nullptr);
235 PyObject*
index = PyObject_CallMethod (pyobj,
"index",
nullptr);
238 PyTuple_SET_ITEM(
val, 0,
v0);
239 PyTuple_SET_ITEM(
val, 1,
key);
241 PyList_Append(pystack,
val);
246 if (clsname.starts_with(
"DataLink<")) {
247 PyObject*
key = PyObject_CallMethod (pyobj,
"key",
nullptr);
250 PyTuple_SET_ITEM(
val, 0,
v0);
251 PyTuple_SET_ITEM(
val, 1,
key);
252 PyList_Append(pystack,
val);
260 if (clsname.starts_with(
"DataVector<xAOD::")) {
261 TClassEdit::TSplitType
split (clsname.c_str());
262 if (
split.fElements.size() > 1) {
263 TClass* eltcls = TClass::GetClass (
split.fElements[1].c_str());
265 TList *members = eltcls->GetListOfDataMembers();
266 const Int_t nmembers = members ? members->GetEntries() : 0;
268 for (Int_t j = 0; j<nmembers; ++j) {
269 TDataMember *mbr = (TDataMember*)(members->At(j));
270 if (!persistentOnly || mbr->IsPersistent()) {
288 if (CPyCppyy::Sequence_Check(pyobj)) {
289 if (clsname ==
"CLHEP::Hep3Vector" ||
290 clsname ==
"TLorentzVector" ||
291 clsname ==
"TVector3")
301 TList *members = tcls->GetListOfDataMembers();
303 const Int_t nmembers = members ? members->GetEntries() : 0;
305 #if PYROOT_INSPECTOR_DBG
306 std::cerr <<
"==[" << clsname <<
"]== (#mbrs:"
314 #if PYROOT_INSPECTOR_DBG
316 const Py_ssize_t nelems = PySequence_Size(pyobj);
317 std::cerr <<
"== sequence (" << nelems <<
")...\n";
329 Py_ssize_t nelems = PySequence_Size(pyobj);
332 if (clsname ==
"TileCellVec" ||
333 clsname ==
"vector<char>")
335 for (Py_ssize_t
i = 0;
i < nelems; ++
i) {
337 PyObject *itr = PySequence_GetItem(pyobj,
i);
338 PyObject *itr_name = ::new_pylist(pyobj_name, pyidx);
339 recurse_pyinspect(itr, itr_name, pystack, persistentOnly, retvecs);
340 Py_XDECREF(itr_name);
353 while (nelems-- && (
item = PyIter_Next(
iter))) {
355 PyObject *itr_name = ::new_pylist(pyobj_name, pyidx);
356 recurse_pyinspect(
item, itr_name, pystack, persistentOnly, retvecs);
357 Py_XDECREF(itr_name);
366 #if PYROOT_INSPECTOR_DBG
367 std::cerr <<
"== sequence (" << nelems <<
")... [done]\n";
372 for (Int_t j = 0; j<nmembers; ++j) {
373 TDataMember *mbr = (TDataMember*)(members->At(j));
374 if (mbr->Property() & kIsStatic)
continue;
375 Int_t
offset = mbr->GetOffset();
378 #if PYROOT_INSPECTOR_DBG
379 TClass *mbr_cls = TClass::GetClass(mbr->GetTypeName());
380 std::cerr <<
"==[" << j <<
"] - [" << mbr->GetTypeName() <<
"] "
381 <<
"[" << mbr->GetName()
383 <<
"[" << (mbr_cls ? mbr_cls->GetName() :
"N/A") <<
"]\n";
389 if (persistentOnly && !mbr->IsPersistent())
391 if (mbr->IsaPointer() || std::string(mbr->GetTypeName()).starts_with(
"unique_ptr")
392 || std::string(mbr->GetTypeName()).starts_with(
"shared_ptr") )
394 if (mbr->IsBasic()) {
395 TDataType * mbr_type = mbr->GetDataType();
396 EDataType mbr_dtype = (EDataType)mbr_type->GetType();
397 py_mbr_name = PyUnicode_FromString(mbr->GetName());
398 py_mbr = to_pyobj(
ptr, mbr_dtype);
399 }
else if (mbr->IsEnum()) {
400 #if PYROOT_INSPECTOR_DBG
401 std::cerr <<
"==[" << mbr->GetTypeName() <<
"]["
402 << mbr->GetDataType()->GetType() <<
"][val="
403 << (*(
int*)
ptr) <<
"]["
404 << mbr->GetName() <<
"] is an enum !!\n";
406 py_mbr_name = PyUnicode_FromString(mbr->GetName());
407 py_mbr = to_pyobj(
ptr, kInt_t);
409 py_mbr_name = PyUnicode_FromString(mbr->GetName());
410 py_mbr = TPython::CPPInstance_FromVoidPtr((
void*)
ptr,
414 if (!py_mbr || !py_mbr_name) {
415 std::cerr <<
"could not create py-object of type ["
416 << mbr->GetTypeName() <<
"] !\n";
418 Py_XDECREF(py_mbr_name);
422 PyObject *this_name = ::new_pylist(pyobj_name, py_mbr_name);
423 recurse_pyinspect(py_mbr, this_name, pystack, persistentOnly, retvecs);
424 Py_DECREF(this_name);
425 Py_DECREF(py_mbr_name);
430 #if PYROOT_INSPECTOR_DBG
431 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
432 << nmembers <<
")... [done]\n";
444 bool persistentOnly )
447 if (!TPython::CPPInstance_Check(pyobj)) {
457 void *
obj = TPython::CPPInstance_AsVoidPtr(pyobj);
459 if (!strcmp(tcls->GetName(),
"string")) {
460 std::string *
str = (std::string*)
obj;
461 return PyUnicode_FromString(
str->c_str());
464 TString tstring = tcls->GetName();
465 if (tstring.BeginsWith(
"pair<") ||
466 tstring.BeginsWith(
"std::pair<")) {
468 PyObject *
v0 = PyObject_GetAttrString(pyobj,
"first");
469 PyObject *v1 = PyObject_GetAttrString(pyobj,
"second");
478 if (CPyCppyy::Sequence_Check(pyobj)) {
479 if (!strcmp(tcls->GetName(),
"CLHEP::Hep3Vector")) {
488 TList *members = tcls->GetListOfDataMembers();
489 const Int_t nmembers = members->GetEntries();
491 PyObject *py_members = PyList_New(nmembers+hdr);
492 #if PYROOT_INSPECTOR_DBG
493 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
496 <<
" #py-sz:" << PyList_Size(py_members)
502 const Py_ssize_t nelems = PySequence_Size(pyobj);
503 #if PYROOT_INSPECTOR_DBG
504 std::cerr <<
"== sequence (" << nelems <<
")...\n";
506 PyObject *py_elems = PyList_New(nelems);
507 for (Py_ssize_t
i = 0;
i < nelems; ++
i) {
508 PyObject *itr = PySequence_GetItem(pyobj,
i);
510 PyList_SET_ITEM(py_elems,
i, itr_pyroot);
515 PyList_SET_ITEM(py_members, 0, py_elems);
516 #if PYROOT_INSPECTOR_DBG
517 std::cerr <<
"== sequence (" << nelems <<
")... content:\n"
518 << ::to_str(py_elems)
520 std::cerr <<
"== sequence (" << nelems <<
")... [done]\n";
525 for (Int_t j = 0; j<nmembers; ++j) {
526 TDataMember *mbr = (TDataMember*)(members->At(j));
527 Int_t
offset = mbr->GetOffset();
530 #if PYROOT_INSPECTOR_DBG
531 TClass *mbr_cls = TClass::GetClass(mbr->GetTypeName());
532 std::cerr <<
"==[" << j <<
"] - [" << mbr->GetTypeName() <<
"] "
533 <<
"[" << mbr->GetName()
535 <<
"[" << (mbr_cls ? mbr_cls->GetName() :
"N/A") <<
"]\n";
540 if (persistentOnly && !mbr->IsPersistent())
542 if (mbr->IsaPointer())
544 if (mbr->IsBasic()) {
545 TDataType * mbr_type = mbr->GetDataType();
546 EDataType mbr_dtype = (EDataType)mbr_type->GetType();
547 py_mbr = to_pyobj(
ptr, mbr_dtype);
548 }
else if (mbr->IsEnum()) {
549 #if PYROOT_INSPECTOR_DBG
550 std::cerr <<
"==[" << mbr->GetTypeName() <<
"]["
551 << mbr->GetDataType()->GetType() <<
"][val="
552 << (*(
int*)
ptr) <<
"]["
553 << mbr->GetName() <<
"] is an enum !!\n";
555 py_mbr = to_pyobj(
ptr, kInt_t);
557 PyObject *pyroot_obj = TPython::CPPInstance_FromVoidPtr
563 Py_XDECREF(pyroot_obj);
566 std::cerr <<
"could not create py-object of type ["
567 << mbr->GetTypeName() <<
"] !\n";
568 Py_DECREF(py_members);
573 PyTuple_SET_ITEM(py_item, 0,
574 PyUnicode_FromString(mbr->GetName()));
575 PyTuple_SET_ITEM(py_item, 1, py_mbr);
576 PyList_SET_ITEM(py_members, j+hdr, py_item);
578 #if PYROOT_INSPECTOR_DBG
579 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
580 << nmembers <<
")... [done]\n";
588 bool persistentOnly ,
592 ::recurse_pyinspect(pyobj, pyobj_name, pystack, persistentOnly, retvecs);