ATLAS Offline Software
Loading...
Searching...
No Matches
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.
PyBytes _pythonize_read_root_file (TFile *f, Int_t len)
 read len bytes from file f
Long64_t _pythonize_tell_root_file (TFile *f)
 tell the current position in file f
PyObjectCPPInstanceReduce (PyObject *self, PyObject *)
 PyROOT object proxy pickle support.
PyObjectCPPInstanceExpand (PyObject *, PyObject *args)
 Helper for (un)pickling of CPPInstance's.
PyObjecttreeSetNotify (PyObject *, PyObject *args)
 Implementation for pythonization of TTree::SetNotify.
PyObjecttreeGetNotify (PyObject *, PyObject *args)
 Implementation for pythonization of TTree::SetNotify.
PyObjectbranchSetAddress (PyObject *, PyObject *args)
 Pythonization of TBranch::SetAddress.
void installMethod (PyObject *pyclass, PyMethodDef &pdef, const char *name, PyCFunction cfunc)
 Helper to install a method in a Python class.
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)

Variables

static PyObjectnotifier_str = 0
static PyObjectpynotify_str = 0

Typedef Documentation

◆ PyException

using RootUtils::PyException = 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}
Long64_t _pythonize_tell_root_file(TFile *f)
tell the current position in file f

◆ _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}
_object PyObject
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check)
Definition Utility.cxx:26
TClass * objectIsA(PyObject *obj)
Definition Utility.cxx:103

◆ 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}
std::pair< std::string, bool > PyGetString(PyObject *s)
Convert python string -> C++ string for py2 and py3.
Definition PyGetString.h:40

◆ 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}
static PyObject * gExpand

◆ 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}
static Double_t tc

◆ 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}
PyObject * rootModule()
Definition Utility.cxx:95

◆ 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}
PyObject * getRootModule()
Definition Utility.cxx:89

◆ 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}
PyObject * setOwnershipFunc()
Definition Utility.cxx:134

◆ 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}
PyObject * getSetOwnershipFunc()
Definition Utility.cxx:126

◆ 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}
static PyObject * pynotify_str

◆ 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}
Tree notification handler.
bool setOwnership(PyObject *obj, bool flag)
Definition Utility.cxx:141
static PyObject * notifier_str
TChain * tree

Variable Documentation

◆ notifier_str

PyObject* RootUtils::notifier_str = 0
static

Definition at line 55 of file PyROOTTTreePatch.cxx.

◆ pynotify_str

PyObject* RootUtils::pynotify_str = 0
static

Definition at line 56 of file PyROOTTTreePatch.cxx.