8 #define PYROOT_INSPECTOR_DBG 0
18 #include "TClassRef.h"
19 #include "TDataMember.h"
20 #include "TDataType.h"
21 #include "TVirtualCollectionProxy.h"
22 #include "TClassEdit.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 auto item = PySequence_Size(
obj) > 0 ? PySequence_GetItem(
obj, 0) :
nullptr;
159 if (!TPython::CPPInstance_Check(pyobj)) {
162 PyObject *v1 = pyobj; Py_XINCREF(pyobj);
163 PyTuple_SET_ITEM(
val, 0,
v0);
164 PyTuple_SET_ITEM(
val, 1, v1);
165 PyList_Append(pystack,
val);
170 static const std::unordered_set<std::string> vecnames {
172 "std::vector<float>",
174 "std::vector<double>",
177 "vector<unsigned int>",
178 "std::vector<unsigned int>",
180 "std::vector<short>",
181 "vector<unsigned short>",
182 "std::vector<unsigned short>",
185 "vector<unsigned char>",
186 "std::vector<unsigned char>",
189 "vector<unsigned long>",
190 "std::vector<unsigned long>",
192 "std::vector<long long>",
193 "vector<unsigned long long>",
194 "std::vector<unsigned long long>",
197 std::string clsname = tcls ? tcls->GetName() :
"";
199 (tcls->IsTObject() && clsname !=
"TLorentzVector") ||
200 (retvecs && vecnames.count (clsname) > 0))
204 PyObject *v1 = pyobj; Py_XINCREF(pyobj);
205 PyTuple_SET_ITEM(
val, 0,
v0);
206 PyTuple_SET_ITEM(
val, 1, v1);
207 PyList_Append(pystack,
val);
211 void *
obj = TPython::CPPInstance_AsVoidPtr(pyobj);
213 if (clsname ==
"string") {
214 std::string *
str = (std::string*)
obj;
218 PyTuple_SET_ITEM(
val, 0,
v0);
219 PyTuple_SET_ITEM(
val, 1, v1);
220 PyList_Append(pystack,
val);
225 if (clsname.starts_with(
"pair<") ||
226 clsname.starts_with(
"std::pair<")) {
229 PyObject *v1 = PyObject_GetAttrString(pyobj,
"first");
230 PyObject *v1_name = ::new_pylist(pyobj_name,
v0);
231 recurse_pyinspect(v1, v1_name, pystack, persistentOnly, retvecs);
238 PyObject *
v0 = PyUnicode_FromString(
"second");
239 PyObject *v1 = PyObject_GetAttrString(pyobj,
"second");
240 PyObject *v1_name = ::new_pylist(pyobj_name,
v0);
241 recurse_pyinspect(v1, v1_name, pystack, persistentOnly, retvecs);
252 if (clsname.starts_with(
"DataVector<xAOD::")) {
253 TClassEdit::TSplitType
split (clsname.c_str());
254 if (
split.fElements.size() > 1) {
255 TClass* eltcls = TClass::GetClass (
split.fElements[1].c_str());
257 TList *members = eltcls->GetListOfDataMembers();
258 const Int_t nmembers = members ? members->GetEntries() : 0;
260 for (Int_t j = 0; j<nmembers; ++j) {
261 TDataMember *mbr = (TDataMember*)(members->At(j));
262 if (!persistentOnly || mbr->IsPersistent()) {
275 if (is_sequence(pyobj)) {
276 if (clsname ==
"CLHEP::Hep3Vector" ||
277 clsname ==
"TLorentzVector" ||
278 clsname ==
"TVector3")
288 TList *members = tcls->GetListOfDataMembers();
290 const Int_t nmembers = members ? members->GetEntries() : 0;
292 #if PYROOT_INSPECTOR_DBG
293 std::cerr <<
"==[" << clsname <<
"]== (#mbrs:"
301 #if PYROOT_INSPECTOR_DBG
303 const Py_ssize_t nelems = PySequence_Size(pyobj);
304 std::cerr <<
"== sequence (" << nelems <<
")...\n";
316 Py_ssize_t nelems = PySequence_Size(pyobj);
317 if (clsname ==
"TileCellVec" ||
318 clsname ==
"vector<char>")
320 for (Py_ssize_t
i = 0;
i < nelems; ++
i) {
322 PyObject *itr = PySequence_GetItem(pyobj,
i);
323 PyObject *itr_name = ::new_pylist(pyobj_name, pyidx);
324 recurse_pyinspect(itr, itr_name, pystack, persistentOnly, retvecs);
325 Py_XDECREF(itr_name);
331 PyObject* iter = PyObject_GetIter(pyobj);
338 while (nelems-- && (
item = PyIter_Next(iter))) {
340 PyObject *itr_name = ::new_pylist(pyobj_name, pyidx);
341 recurse_pyinspect(
item, itr_name, pystack, persistentOnly, retvecs);
342 Py_XDECREF(itr_name);
350 #if PYROOT_INSPECTOR_DBG
351 std::cerr <<
"== sequence (" << nelems <<
")... [done]\n";
356 for (Int_t j = 0; j<nmembers; ++j) {
357 TDataMember *mbr = (TDataMember*)(members->At(j));
358 if (mbr->Property() & kIsStatic)
continue;
359 Int_t
offset = mbr->GetOffset();
362 #if PYROOT_INSPECTOR_DBG
363 TClass *mbr_cls = TClass::GetClass(mbr->GetTypeName());
364 std::cerr <<
"==[" << j <<
"] - [" << mbr->GetTypeName() <<
"] "
365 <<
"[" << mbr->GetName()
367 <<
"[" << (mbr_cls ? mbr_cls->GetName() :
"N/A") <<
"]\n";
373 if (persistentOnly && !mbr->IsPersistent())
375 if (mbr->IsaPointer() || std::string(mbr->GetTypeName()).starts_with(
"unique_ptr")
376 || std::string(mbr->GetTypeName()).starts_with(
"shared_ptr") )
378 if (mbr->IsBasic()) {
379 TDataType * mbr_type = mbr->GetDataType();
380 EDataType mbr_dtype = (EDataType)mbr_type->GetType();
381 py_mbr_name = PyUnicode_FromString(mbr->GetName());
382 py_mbr = to_pyobj(
ptr, mbr_dtype);
383 }
else if (mbr->IsEnum()) {
384 #if PYROOT_INSPECTOR_DBG
385 std::cerr <<
"==[" << mbr->GetTypeName() <<
"]["
386 << mbr->GetDataType()->GetType() <<
"][val="
387 << (*(
int*)
ptr) <<
"]["
388 << mbr->GetName() <<
"] is an enum !!\n";
390 py_mbr_name = PyUnicode_FromString(mbr->GetName());
391 py_mbr = to_pyobj(
ptr, kInt_t);
393 py_mbr_name = PyUnicode_FromString(mbr->GetName());
394 py_mbr = TPython::CPPInstance_FromVoidPtr((
void*)
ptr,
398 if (!py_mbr || !py_mbr_name) {
399 std::cerr <<
"could not create py-object of type ["
400 << mbr->GetTypeName() <<
"] !\n";
402 Py_XDECREF(py_mbr_name);
406 PyObject *this_name = ::new_pylist(pyobj_name, py_mbr_name);
407 recurse_pyinspect(py_mbr, this_name, pystack, persistentOnly, retvecs);
408 Py_DECREF(this_name);
409 Py_DECREF(py_mbr_name);
414 #if PYROOT_INSPECTOR_DBG
415 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
416 << nmembers <<
")... [done]\n";
428 bool persistentOnly )
431 if (!TPython::CPPInstance_Check(pyobj)) {
441 void *
obj = TPython::CPPInstance_AsVoidPtr(pyobj);
443 if (!strcmp(tcls->GetName(),
"string")) {
444 std::string *
str = (std::string*)
obj;
445 return PyUnicode_FromString(
str->c_str());
448 TString tstring = tcls->GetName();
449 if (tstring.BeginsWith(
"pair<") ||
450 tstring.BeginsWith(
"std::pair<")) {
452 PyObject *
v0 = PyObject_GetAttrString(pyobj,
"first");
453 PyObject *v1 = PyObject_GetAttrString(pyobj,
"second");
462 if (is_sequence(pyobj)) {
463 if (!strcmp(tcls->GetName(),
"CLHEP::Hep3Vector")) {
472 TList *members = tcls->GetListOfDataMembers();
473 const Int_t nmembers = members->GetEntries();
475 PyObject *py_members = PyList_New(nmembers+hdr);
476 #if PYROOT_INSPECTOR_DBG
477 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
480 <<
" #py-sz:" << PyList_Size(py_members)
486 const Py_ssize_t nelems = PySequence_Size(pyobj);
487 #if PYROOT_INSPECTOR_DBG
488 std::cerr <<
"== sequence (" << nelems <<
")...\n";
490 PyObject *py_elems = PyList_New(nelems);
491 for (Py_ssize_t
i = 0;
i < nelems; ++
i) {
492 PyObject *itr = PySequence_GetItem(pyobj,
i);
494 PyList_SET_ITEM(py_elems,
i, itr_pyroot);
499 PyList_SET_ITEM(py_members, 0, py_elems);
500 #if PYROOT_INSPECTOR_DBG
501 std::cerr <<
"== sequence (" << nelems <<
")... content:\n"
502 << ::to_str(py_elems)
504 std::cerr <<
"== sequence (" << nelems <<
")... [done]\n";
509 for (Int_t j = 0; j<nmembers; ++j) {
510 TDataMember *mbr = (TDataMember*)(members->At(j));
511 Int_t
offset = mbr->GetOffset();
514 #if PYROOT_INSPECTOR_DBG
515 TClass *mbr_cls = TClass::GetClass(mbr->GetTypeName());
516 std::cerr <<
"==[" << j <<
"] - [" << mbr->GetTypeName() <<
"] "
517 <<
"[" << mbr->GetName()
519 <<
"[" << (mbr_cls ? mbr_cls->GetName() :
"N/A") <<
"]\n";
524 if (persistentOnly && !mbr->IsPersistent())
526 if (mbr->IsaPointer())
528 if (mbr->IsBasic()) {
529 TDataType * mbr_type = mbr->GetDataType();
530 EDataType mbr_dtype = (EDataType)mbr_type->GetType();
531 py_mbr = to_pyobj(
ptr, mbr_dtype);
532 }
else if (mbr->IsEnum()) {
533 #if PYROOT_INSPECTOR_DBG
534 std::cerr <<
"==[" << mbr->GetTypeName() <<
"]["
535 << mbr->GetDataType()->GetType() <<
"][val="
536 << (*(
int*)
ptr) <<
"]["
537 << mbr->GetName() <<
"] is an enum !!\n";
539 py_mbr = to_pyobj(
ptr, kInt_t);
541 PyObject *pyroot_obj = TPython::CPPInstance_FromVoidPtr
547 Py_XDECREF(pyroot_obj);
550 std::cerr <<
"could not create py-object of type ["
551 << mbr->GetTypeName() <<
"] !\n";
552 Py_DECREF(py_members);
557 PyTuple_SET_ITEM(py_item, 0,
558 PyUnicode_FromString(mbr->GetName()));
559 PyTuple_SET_ITEM(py_item, 1, py_mbr);
560 PyList_SET_ITEM(py_members, j+hdr, py_item);
562 #if PYROOT_INSPECTOR_DBG
563 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
564 << nmembers <<
")... [done]\n";
572 bool persistentOnly ,
576 ::recurse_pyinspect(pyobj, pyobj_name, pystack, persistentOnly, retvecs);