ATLAS Offline Software
Classes | Typedefs | Functions
RootUtils Namespace Reference

Classes

class  ILogger
 Very simple interface for writing log messages. More...
 
class  InitHist
 Initialize Root's getline history. More...
 
class  PyBytes
 
class  PyGILStateEnsure
 
class  PyLogger
 A concrete implementation of ILogger that calls back to Python. More...
 
class  PyROOTInspector
 
class  PyROOTIteratorFuncs
 Provide functions for iterator comparisons. More...
 
class  PyROOTPickle
 
class  PyROOTTTreePatch
 
class  PyROOTTypePatch
 Work around pyroot problem with __pair_base. More...
 
class  ScatterH2
 A 2-D histogram that can draw a proper scatter plot. More...
 
class  TRandomTLS
 Thread-local TRandom generator. More...
 
class  TreeNotifier
 Tree notification handler. More...
 
class  TSMethodCall
 Helper for making a thread-safe function call. More...
 
class  Type
 Wrapper for ROOT types. More...
 
class  WithRootErrorHandler
 Run a MT piece of code with an alternate root error handler. More...
 

Typedefs

using PyException = CPyCppyy::PyException
 

Functions

std::pair< std::string, bool > PyGetString (PyObject *s)
 Convert python string -> C++ string for py2 and py3. More...
 
PyBytes _pythonize_read_root_file (TFile *f, Int_t len)
 read len bytes from file f More...
 
Long64_t _pythonize_tell_root_file (TFile *f)
 tell the current position in file f More...
 
PyObjectCPPInstanceReduce (PyObject *self, PyObject *)
 PyROOT object proxy pickle support. More...
 
PyObjectCPPInstanceExpand (PyObject *, PyObject *args)
 Helper for (un)pickling of CPPInstance's. More...
 
PyObjecttreeSetNotify (PyObject *, PyObject *args)
 Implementation for pythonization of TTree::SetNotify. More...
 
PyObjecttreeGetNotify (PyObject *, PyObject *args)
 Implementation for pythonization of TTree::SetNotify. More...
 
PyObjectbranchSetAddress (PyObject *, PyObject *args)
 Pythonization of TBranch::SetAddress. More...
 
void installMethod (PyObject *pyclass, PyMethodDef &pdef, const char *name, PyCFunction cfunc)
 Helper to install a method in a Python class. More...
 
int GetBuffer (PyObject *pyobject, char tc, int size, void *&buf, Bool_t check)
 
PyObjectgetRootModule ()
 
PyObjectrootModule ()
 
TClass * objectIsA (PyObject *obj)
 
PyObjectgetSetOwnershipFunc ()
 
PyObjectsetOwnershipFunc ()
 
bool setOwnership (PyObject *obj, bool flag)
 

Typedef Documentation

◆ PyException

using RootUtils::PyException = typedef CPyCppyy::PyException

Definition at line 24 of file Utility.h.

Function Documentation

◆ _pythonize_read_root_file()

PyBytes RootUtils::_pythonize_read_root_file ( TFile *  f,
Int_t  len 
)

read len bytes from file f

Definition at line 60 of file PyROOTTFilePythonize.cxx.

61 {
62  if (!f) {
63  //err
64  return PyBytes(0);
65  }
66 
67  Long64_t totsz = f->GetSize();
68  Long64_t curpos = _pythonize_tell_root_file(f);
69  Long64_t remain = totsz - curpos;
70  remain = (remain>0) ? remain : 0;
71 
72  len = (len>remain) ? remain : len;
73  PyBytes buf(len);
74  if (f->ReadBuffer((char*)buf.buf.data(), buf.sz)) {
75  //err
76  return PyBytes(0);
77  }
78 
79  f->Seek(buf.sz + curpos);
80  return buf;
81 }

◆ _pythonize_tell_root_file()

Long64_t RootUtils::_pythonize_tell_root_file ( TFile *  f)

tell the current position in file f

Definition at line 49 of file PyROOTTFilePythonize.cxx.

50 {
51  if (f) {
52  return f->GetRelOffset();
53  }
54  fprintf (stderr,
55  "::RootUtils::_pythonize_tell_root_file got a NULL TFile ptr!\n");
56  return 0;
57 }

◆ branchSetAddress()

PyObject* RootUtils::branchSetAddress ( PyObject ,
PyObject args 
)

Pythonization of TBranch::SetAddress.

Parameters
argsThe Python arguments.

Definition at line 268 of file PyROOTTTreePatch.cxx.

269 {
270  // Decode arguments --- the branch and the buffer.
271  PyObject* self = 0;
272  PyObject* address = 0;
273  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "OO:SetBranchAddress" ),
274  &self, &address ) )
275  return 0;
276 
277  // The branch as a Root object.
278  TBranch* branch = 0;
279  if (TPython::CPPInstance_Check (self)) {
280  branch = (TBranch*)objectIsA(self)->DynamicCast
281  ( TBranch::Class(),
282  TPython::CPPInstance_AsVoidPtr(self) );
283  }
284 
285  if ( ! branch ) {
286  PyErr_SetString( PyExc_TypeError,
287  "TBranch::SetAddress must be called with a "
288  "TBranch instance as first argument" );
289  return 0;
290  }
291 
292  // Convert the buffer argument to an address.
293  void* buf = 0;
294  if ( TPython::CPPInstance_Check( address ) ) {
295  auto* inst = reinterpret_cast<CPPInstance*>(address);
296  if ( inst->fFlags & CPPInstance::kIsReference )
297  buf = inst->fObject;
298  else
299  buf = &inst->fObject;
300  }
301  else
302  RootUtils::GetBuffer( address, '*', 1, buf, kFALSE );
303 
304  // Make the call and return.
305  if ( buf != 0 )
306  branch->SetAddress( buf );
307 
308  Py_INCREF( Py_None );
309  return Py_None;
310 }

◆ CPPInstanceExpand()

PyObject* RootUtils::CPPInstanceExpand ( PyObject ,
PyObject args 
)

Helper for (un)pickling of CPPInstance's.

Parameters
argsThe Python arguments.

Definition at line 86 of file PyROOTPickle.cxx.

87 {
88  // This method is a helper for (un)pickling of CPPInstance instances.
89  PyObject* pybuf = 0;
90  const char* clname = 0;
91  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!s:__expand__" ),
92  &PyUnicode_Type, &pybuf, &clname ) )
93  return 0;
94 
95  // use the PyString macros to by-pass error checking; do not adopt the buffer,
96  // as the local TBufferFile can go out of scope (there is no copying)
97  TBufferFile buf( TBuffer::kRead,
98  PyUnicode_GET_LENGTH( pybuf ),
99  (char*)PyGetString( pybuf ).first.c_str(),
100  kFALSE );
101 
102  void* result = buf.ReadObjectAny( 0 );
103  return TPython::CPPInstance_FromVoidPtr( result, clname );
104 }

◆ CPPInstanceReduce()

PyObject* RootUtils::CPPInstanceReduce ( PyObject self,
PyObject  
)

PyROOT object proxy pickle support.

Parameters
selfobject proxy instance to be pickled

Definition at line 36 of file PyROOTPickle.cxx.

37 {
38  // Turn the object proxy instance into a character stream and return for
39  // pickle, together with the callable object that can restore the stream
40  // into the object proxy instance.
41 
42  void* vself = TPython::CPPInstance_AsVoidPtr( self ); // checks type
43  if ( ! vself ) {
44  PyErr_SetString( PyExc_TypeError,
45  "__reduce__ requires an object proxy instance as first argument" );
46  return 0;
47  }
48 
49  PyObject* nattr = PyObject_GetAttrString( (PyObject*)self->ob_type, (char*)"__name__" );
50  PyObject* pyname = PyObject_Str( nattr );
51  Py_DECREF( nattr );
52 
53  std::string klassname = PyGetString( pyname ).first;
54  TClass* klass = TClass::GetClass( klassname.c_str() );
55 
56  // no cast is needed, but WriteObject taking a TClass argument is protected,
57  // so use WriteObjectAny()
58  TBufferFile buf( TBuffer::kWrite );
59  if ( buf.WriteObjectAny( vself, klass ) != 1 ) {
60  PyErr_Format( PyExc_IOError,
61  "could not stream object of type %s", klassname.c_str() );
62  Py_DECREF( pyname );
63  return 0;
64  }
65 
66  // use a string for the serialized result, as a python buffer will not copy
67  // the buffer contents; use a string for the class name, used when casting
68  // on reading back in
69  PyObject* res2 = PyTuple_New( 2 );
70  PyTuple_SET_ITEM( res2, 0, PyUnicode_FromStringAndSize( buf.Buffer(), buf.Length() ) );
71  PyTuple_SET_ITEM( res2, 1, pyname );
72 
73  PyObject* result = PyTuple_New( 2 );
74  Py_INCREF( gExpand );
75  PyTuple_SET_ITEM( result, 0, gExpand );
76  PyTuple_SET_ITEM( result, 1, res2 );
77 
78  return result;
79 }

◆ GetBuffer()

int RootUtils::GetBuffer ( PyObject pyobject,
char  tc,
int  size,
void *&  buf,
Bool_t  check 
)

Definition at line 26 of file Utility.cxx.

27 {
28 // Retrieve a linear buffer pointer from the given pyobject.
29 
30 // special case: don't handle character strings here (yes, they're buffers, but not quite)
31  if ( PyBytes_Check( pyobject ) )
32  return 0;
33 
34 // attempt to retrieve pointer to buffer interface
35  PyBufferProcs* bufprocs = Py_TYPE(pyobject)->tp_as_buffer;
36 
37  PySequenceMethods* seqmeths = Py_TYPE(pyobject)->tp_as_sequence;
38  if ( seqmeths != 0 && bufprocs != 0
39  && bufprocs->bf_getbuffer != 0
40  ) {
41 
42  // get the buffer
43  Py_buffer bufinfo;
44  (*(bufprocs->bf_getbuffer))( pyobject, &bufinfo, PyBUF_WRITABLE );
45  buf = (char*)bufinfo.buf;
46  Py_ssize_t buflen = bufinfo.len;
47 
48  if ( buf && check == kTRUE ) {
49  // determine buffer compatibility (use "buf" as a status flag)
50  PyObject* pytc = PyObject_GetAttrString( pyobject, "typecode");
51  if ( pytc != 0 ) { // for array objects
52  const char* s = PyUnicode_AsUTF8AndSize( pytc, nullptr );
53  if ( s && s[0] != tc )
54  buf = 0; // no match
55  Py_DECREF( pytc );
56  } else if ( seqmeths->sq_length &&
57  (int)(buflen / (*(seqmeths->sq_length))( pyobject )) == size ) {
58  // this is a gamble ... may or may not be ok, but that's for the user
59  PyErr_Clear();
60  } else if ( buflen == size ) {
61  // also a gamble, but at least 1 item will fit into the buffer, so very likely ok ...
62  PyErr_Clear();
63  } else {
64  buf = 0; // not compatible
65 
66  // clarify error message
67  PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
68  PyErr_Fetch( &pytype, &pyvalue, &pytrace );
69  const char* s = PyUnicode_AsUTF8AndSize( pyvalue, nullptr );
70  if (!s) s = "(null)";
71  PyObject* pyvalue2 = PyUnicode_FromFormat(
72  (char*)"%s and given element size (%ld) do not match needed (%d)",
73  s,
74  seqmeths->sq_length ? (Long_t)(buflen / (*(seqmeths->sq_length))( pyobject )) : (Long_t)buflen,
75  size );
76  Py_DECREF( pyvalue );
77  PyErr_Restore( pytype, pyvalue2, pytrace );
78  }
79  }
80 
81  return buflen;
82  }
83 
84  return 0;
85 }

◆ getRootModule()

PyObject* RootUtils::getRootModule ( )

Definition at line 89 of file Utility.cxx.

90 {
91  return PyImport_ImportModule ("ROOT");
92 }

◆ getSetOwnershipFunc()

PyObject* RootUtils::getSetOwnershipFunc ( )

Definition at line 126 of file Utility.cxx.

127 {
128  PyObject* root = rootModule();
129  PyObject* ret = PyObject_GetAttrString (root, "SetOwnership");
130  Py_DECREF (root);
131  return ret;
132 }

◆ installMethod()

void RootUtils::installMethod ( PyObject pyclass,
PyMethodDef &  pdef,
const char *  name,
PyCFunction  cfunc 
)

Helper to install a method in a Python class.

Parameters
pyclassThe Python class.
pdefA PyMethodDef object.
nameThe method name.
cfuncThe C function to install.

Definition at line 320 of file PyROOTTTreePatch.cxx.

324 {
325  pdef.ml_name = const_cast<char*> (name);
326  pdef.ml_meth = cfunc;
327  pdef.ml_flags = METH_VARARGS;
328  pdef.ml_doc = 0;
329 
330  PyObject* func = PyCFunction_New (&pdef, 0);
331  PyObject* method = PyInstanceMethod_New (func);
332  Bool_t isOK = PyObject_SetAttrString (pyclass, pdef.ml_name, method) == 0;
333 
334  if (PyErr_Occurred())
335  fprintf (stderr, "Py error");
336  else if (!isOK) {
337  fprintf (stderr, "Could not add method %s\n", name);
338  }
339 }

◆ objectIsA()

TClass * RootUtils::objectIsA ( PyObject obj)

Definition at line 103 of file Utility.cxx.

104 {
105  TClass* cls = nullptr;
106  PyObject* attr = PyObject_GetAttrString ((PyObject*)Py_TYPE(obj), "__cpp_name__");
107  if (attr) {
108  PyObject* buf = PyUnicode_AsASCIIString (attr);
109  if (buf) {
110  char* s = PyBytes_AsString (buf);
111  if (*s == '<') ++s;
112  if (strncmp (s, "ROOT.", 5) == 0)
113  s += 5;
114  if (strncmp (s, "cppyy.gbl.", 10) == 0)
115  s += 10;
116  cls = TClass::GetClass (s);
117  Py_DECREF(buf);
118  }
119  Py_DECREF(attr);
120  }
121  PyErr_Clear();
122  return cls;
123 }

◆ PyGetString()

std::pair<std::string, bool> RootUtils::PyGetString ( PyObject s)
inline

Convert python string -> C++ string for py2 and py3.

Returns a pair (string, bool); the second element is true of the conversion succeeded.

This should be kept as an inline function to avoid having to have direct dependencies on python where it's not really needed.

Definition at line 40 of file PyGetString.h.

41 {
42  const char* cstr = PyUnicode_AsUTF8AndSize (s, nullptr);
43  if (!cstr && PyBytes_Check (s)) {
44  PyErr_Clear();
45  cstr = PyBytes_AsString (s);
46  }
47  if (cstr) {
48  return std::make_pair (std::string (cstr), true);
49  }
50  return std::make_pair (std::string(), false);
51 }

◆ rootModule()

PyObject* RootUtils::rootModule ( )

Definition at line 95 of file Utility.cxx.

96 {
97  static PyObject* const rootModule = getRootModule();
98  Py_INCREF (rootModule);
99  return rootModule;
100 }

◆ setOwnership()

bool RootUtils::setOwnership ( PyObject obj,
bool  flag 
)

Definition at line 141 of file Utility.cxx.

142 {
143  PyObject* func = setOwnershipFunc();
144  PyObject* ret = PyObject_CallFunction (func, const_cast<char*>("OI"),
145  obj,
146  static_cast<unsigned int>(flag));
147  Py_DECREF (func);
148  if (ret) {
149  Py_DECREF (ret);
150  return true;
151  }
152  return false;
153 }

◆ setOwnershipFunc()

PyObject* RootUtils::setOwnershipFunc ( )

Definition at line 134 of file Utility.cxx.

135 {
136  static PyObject* const func = getSetOwnershipFunc();
137  Py_INCREF (func);
138  return func;
139 }

◆ treeGetNotify()

PyObject* RootUtils::treeGetNotify ( PyObject ,
PyObject args 
)

Implementation for pythonization of TTree::SetNotify.

Parameters
argsThe Python arguments.

Definition at line 241 of file PyROOTTTreePatch.cxx.

242 {
243  // Decode the objects --- the tree.
244  PyObject* self = 0;
245  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O:SetNotify" ),
246  &self ) )
247  return 0;
248 
249  // Intern string if needed.
250  if (pynotify_str == 0)
251  pynotify_str = PyUnicode_InternFromString("__pynotify__");
252 
253  // Retrieve the notifier.
254  PyObject* ret = PyObject_GetAttr (self, pynotify_str);
255  if (!ret) {
256  PyErr_Clear();
257  Py_INCREF (Py_None);
258  ret = Py_None;
259  }
260  return ret;
261 }

◆ treeSetNotify()

PyObject* RootUtils::treeSetNotify ( PyObject ,
PyObject args 
)

Implementation for pythonization of TTree::SetNotify.

Parameters
argsThe Python arguments.

Definition at line 190 of file PyROOTTTreePatch.cxx.

191 {
192  // Decode the objects --- the tree and the notifier object.
193  PyObject* self = 0;
194  PyObject* obj = 0;
195  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "OO:SetNotify" ),
196  &self, &obj ) )
197  return 0;
198 
199  // Intern strings if needed.
200  if (pynotify_str == 0) {
201  pynotify_str = PyUnicode_InternFromString("__pynotify__");
202  }
203  if (notifier_str == 0) {
204  notifier_str = PyUnicode_InternFromString("__notifier__");
205  }
206 
207  // Set up notifier.
208  if (!PyObject_HasAttr (self, notifier_str)) {
209  // get hold of actual tree
210  void* vp = TPython::CPPInstance_AsVoidPtr (self);
211  TTree* tree =
212  (TTree*)objectIsA(self)->DynamicCast ( TTree::Class(), vp );
213 
214  PyObject* treeobj_ref = PyWeakref_NewRef (self, 0);
215  if (!treeobj_ref)
216  return 0;
217  TObject* notifier = new TreeNotifier (tree, treeobj_ref);
218  PyObject* notobj = TPython::CPPInstance_FromVoidPtr (notifier, "TObject");
219  setOwnership (notobj, true);
220  int stat = PyObject_SetAttr (self, notifier_str, notobj);
221  Py_XDECREF (notobj);
222  if (stat < 0)
223  return 0;
224  tree->SetNotify (notifier);
225  }
226 
227  // Install the object.
228  int stat = PyObject_SetAttr (self, pynotify_str, obj);
229  if (stat < 0)
230  return 0;
231 
232  Py_INCREF (Py_None);
233  return Py_None;
234 }
RunTileTBRec.method
method
Definition: RunTileTBRec.py:73
get_generator_info.result
result
Definition: get_generator_info.py:21
python.CaloAddPedShiftConfig.args
args
Definition: CaloAddPedShiftConfig.py:47
gridSubmitIDTPM.check
check
Definition: gridSubmitIDTPM.py:45
tree
TChain * tree
Definition: tile_monitor.h:30
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
get_generator_info.stderr
stderr
Definition: get_generator_info.py:40
RootUtils::getSetOwnershipFunc
PyObject * getSetOwnershipFunc()
Definition: Utility.cxx:126
sendEI_SPB.root
root
Definition: sendEI_SPB.py:34
klass
This class describe the base functionalities of a HypoTool used by the ComboAlg.
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
python.DecayParser.buf
buf
print ("=> [%s]"cmd)
Definition: DecayParser.py:27
RootUtils::objectIsA
TClass * objectIsA(PyObject *obj)
Definition: Utility.cxx:103
master.flag
bool flag
Definition: master.py:29
RootUtils::rootModule
PyObject * rootModule()
Definition: Utility.cxx:95
hist_file_dump.f
f
Definition: hist_file_dump.py:140
beamspotman.stat
stat
Definition: beamspotman.py:264
RootUtils::setOwnershipFunc
PyObject * setOwnershipFunc()
Definition: Utility.cxx:134
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
RootUtils::getRootModule
PyObject * getRootModule()
Definition: Utility.cxx:89
RTTAlgmain.address
address
Definition: RTTAlgmain.py:55
RootUtils::PyGetString
std::pair< std::string, bool > PyGetString(PyObject *s)
Convert python string -> C++ string for py2 and py3.
Definition: PyGetString.h:40
RTTAlgmain.branch
branch
Definition: RTTAlgmain.py:61
DeMoScan.first
bool first
Definition: DeMoScan.py:534
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
PyROOT::CPPInstance
Definition: PyROOTTTreePatch.cxx:33
RootUtils::setOwnership
bool setOwnership(PyObject *obj, bool flag)
Definition: Utility.cxx:141
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
RootUtils::GetBuffer
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check)
Definition: Utility.cxx:26
python.PyAthena.obj
obj
Definition: PyAthena.py:132
PyObject
_object PyObject
Definition: IPyComponent.h:26
RootUtils::_pythonize_tell_root_file
Long64_t _pythonize_tell_root_file(TFile *f)
tell the current position in file f
Definition: PyROOTTFilePythonize.cxx:49