7#define PYROOT_INSPECTOR_DBG 0
18#include "TDataMember.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 )
51to_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
116 PyObject *py_str = PyObject_Str(obj);
117 std::string s = py_str && PyUnicode_Check(py_str)
118 ? PyUnicode_AsUTF8(py_str)
129 PyObject *obj = PySequence_List(pylist);
130 PyList_Append(obj, item);
142 if (!TPython::CPPInstance_Check(pyobj)) {
144 PyObject *v0 = pyobj_name; Py_INCREF(v0);
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))
187 PyObject *v0 = pyobj_name; Py_INCREF(v0);
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;
200 PyObject *v0 = pyobj_name; Py_INCREF(v0);
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<")) {
212 PyObject *v0 = PyUnicode_FromString(
"first");
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);
237 PyObject *v0 = pyobj_name; Py_INCREF(v0);
238 PyTuple_SET_ITEM(val, 0, v0);
239 PyTuple_SET_ITEM(val, 1, key);
240 PyTuple_SET_ITEM(val, 2,
index);
241 PyList_Append(pystack, val);
246 if (clsname.starts_with(
"DataLink<")) {
247 PyObject* key = PyObject_CallMethod (pyobj,
"key",
nullptr);
249 PyObject *v0 = pyobj_name; Py_INCREF(v0);
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>" ||
334 clsname ==
"vector<signed char>")
336 for (Py_ssize_t i = 0; i < nelems; ++i) {
337 PyObject *pyidx = PyLong_FromLong(i);
338 PyObject *itr = PySequence_GetItem(pyobj, i);
339 PyObject *itr_name = ::new_pylist(pyobj_name, pyidx);
340 recurse_pyinspect(itr, itr_name, pystack, persistentOnly, retvecs);
341 Py_XDECREF(itr_name);
347 PyObject* iter = PyObject_GetIter(pyobj);
354 while (nelems-- && (item = PyIter_Next(iter))) {
355 PyObject *pyidx = PyLong_FromLong(i++);
356 PyObject *itr_name = ::new_pylist(pyobj_name, pyidx);
357 recurse_pyinspect(item, itr_name, pystack, persistentOnly, retvecs);
358 Py_XDECREF(itr_name);
367#if PYROOT_INSPECTOR_DBG
368 std::cerr <<
"== sequence (" << nelems <<
")... [done]\n";
373 for (Int_t j = 0; j<nmembers; ++j) {
374 TDataMember *mbr = (TDataMember*)(members->At(j));
375 if (mbr->Property() & kIsStatic)
continue;
376 Int_t offset = mbr->GetOffset();
377 char *ptr = (
char*)obj + offset;
379#if PYROOT_INSPECTOR_DBG
380 TClass *mbr_cls = TClass::GetClass(mbr->GetTypeName());
381 std::cerr <<
"==[" << j <<
"] - [" << mbr->GetTypeName() <<
"] "
382 <<
"[" << mbr->GetName()
384 <<
"[" << (mbr_cls ? mbr_cls->GetName() :
"N/A") <<
"]\n";
390 if (persistentOnly && !mbr->IsPersistent())
392 if (mbr->IsaPointer() || std::string(mbr->GetTypeName()).starts_with(
"unique_ptr")
393 || std::string(mbr->GetTypeName()).starts_with(
"shared_ptr") )
395 if (mbr->IsBasic()) {
396 TDataType * mbr_type = mbr->GetDataType();
397 EDataType mbr_dtype = (EDataType)mbr_type->GetType();
398 py_mbr_name = PyUnicode_FromString(mbr->GetName());
399 py_mbr = to_pyobj(ptr, mbr_dtype);
400 }
else if (mbr->IsEnum()) {
401#if PYROOT_INSPECTOR_DBG
402 std::cerr <<
"==[" << mbr->GetTypeName() <<
"]["
403 << mbr->GetDataType()->GetType() <<
"][val="
404 << (*(
int*)ptr) <<
"]["
405 << mbr->GetName() <<
"] is an enum !!\n";
407 py_mbr_name = PyUnicode_FromString(mbr->GetName());
408 py_mbr = to_pyobj(ptr, kInt_t);
410 py_mbr_name = PyUnicode_FromString(mbr->GetName());
411 py_mbr = TPython::CPPInstance_FromVoidPtr((
void*)ptr,
415 if (!py_mbr || !py_mbr_name) {
416 std::cerr <<
"could not create py-object of type ["
417 << mbr->GetTypeName() <<
"] !\n";
419 Py_XDECREF(py_mbr_name);
423 PyObject *this_name = ::new_pylist(pyobj_name, py_mbr_name);
424 recurse_pyinspect(py_mbr, this_name, pystack, persistentOnly, retvecs);
425 Py_DECREF(this_name);
426 Py_DECREF(py_mbr_name);
431#if PYROOT_INSPECTOR_DBG
432 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
433 << nmembers <<
")... [done]\n";
445 bool persistentOnly )
448 if (!TPython::CPPInstance_Check(pyobj)) {
458 void *obj = TPython::CPPInstance_AsVoidPtr(pyobj);
460 if (!strcmp(tcls->GetName(),
"string")) {
461 std::string *
str = (std::string*)obj;
462 return PyUnicode_FromString(
str->c_str());
465 TString tstring = tcls->GetName();
466 if (tstring.BeginsWith(
"pair<") ||
467 tstring.BeginsWith(
"std::pair<")) {
469 PyObject *v0 = PyObject_GetAttrString(pyobj,
"first");
470 PyObject *v1 = PyObject_GetAttrString(pyobj,
"second");
479 if (CPyCppyy::Sequence_Check(pyobj)) {
480 if (!strcmp(tcls->GetName(),
"CLHEP::Hep3Vector")) {
489 TList *members = tcls->GetListOfDataMembers();
490 const Int_t nmembers = members->GetEntries();
492 PyObject *py_members = PyList_New(nmembers+hdr);
493#if PYROOT_INSPECTOR_DBG
494 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
497 <<
" #py-sz:" << PyList_Size(py_members)
503 const Py_ssize_t nelems = PySequence_Size(pyobj);
504#if PYROOT_INSPECTOR_DBG
505 std::cerr <<
"== sequence (" << nelems <<
")...\n";
507 PyObject *py_elems = PyList_New(nelems);
508 for (Py_ssize_t i = 0; i < nelems; ++i) {
509 PyObject *itr = PySequence_GetItem(pyobj, i);
511 PyList_SET_ITEM(py_elems, i, itr_pyroot);
516 PyList_SET_ITEM(py_members, 0, py_elems);
517#if PYROOT_INSPECTOR_DBG
518 std::cerr <<
"== sequence (" << nelems <<
")... content:\n"
519 << ::to_str(py_elems)
521 std::cerr <<
"== sequence (" << nelems <<
")... [done]\n";
526 for (Int_t j = 0; j<nmembers; ++j) {
527 TDataMember *mbr = (TDataMember*)(members->At(j));
528 Int_t offset = mbr->GetOffset();
529 char *ptr = (
char*)obj + offset;
531#if PYROOT_INSPECTOR_DBG
532 TClass *mbr_cls = TClass::GetClass(mbr->GetTypeName());
533 std::cerr <<
"==[" << j <<
"] - [" << mbr->GetTypeName() <<
"] "
534 <<
"[" << mbr->GetName()
536 <<
"[" << (mbr_cls ? mbr_cls->GetName() :
"N/A") <<
"]\n";
541 if (persistentOnly && !mbr->IsPersistent())
543 if (mbr->IsaPointer())
545 if (mbr->IsBasic()) {
546 TDataType * mbr_type = mbr->GetDataType();
547 EDataType mbr_dtype = (EDataType)mbr_type->GetType();
548 py_mbr = to_pyobj(ptr, mbr_dtype);
549 }
else if (mbr->IsEnum()) {
550#if PYROOT_INSPECTOR_DBG
551 std::cerr <<
"==[" << mbr->GetTypeName() <<
"]["
552 << mbr->GetDataType()->GetType() <<
"][val="
553 << (*(
int*)ptr) <<
"]["
554 << mbr->GetName() <<
"] is an enum !!\n";
556 py_mbr = to_pyobj(ptr, kInt_t);
558 PyObject *pyroot_obj = TPython::CPPInstance_FromVoidPtr
564 Py_XDECREF(pyroot_obj);
567 std::cerr <<
"could not create py-object of type ["
568 << mbr->GetTypeName() <<
"] !\n";
569 Py_DECREF(py_members);
574 PyTuple_SET_ITEM(py_item, 0,
575 PyUnicode_FromString(mbr->GetName()));
576 PyTuple_SET_ITEM(py_item, 1, py_mbr);
577 PyList_SET_ITEM(py_members, j+hdr, py_item);
579#if PYROOT_INSPECTOR_DBG
580 std::cerr <<
"==[" << tcls->GetName() <<
"]== (#mbrs:"
581 << nmembers <<
")... [done]\n";
589 bool persistentOnly ,
593 ::recurse_pyinspect(pyobj, pyobj_name, pystack, persistentOnly, retvecs);
Utility code originally from pyroot.
Define macros for attributes used to control the static checker.
#define ATLAS_NO_CHECK_FILE_THREAD_SAFETY
static PyObject * pyroot_inspect(PyObject *obj, bool persistentOnly=false)
static PyObject * pyroot_inspect2(PyObject *obj, PyObject *obj_name, bool persistentOnly=false, bool retvecs=false)
std::vector< std::string > split(const std::string &s, const std::string &t=":")
CPyCppyy::PyException PyException
TClass * objectIsA(PyObject *obj)