Logo ROOT   6.14/05
Reference Guide
Pythonize.cxx
Go to the documentation of this file.
1 // @(#)root/pyroot:$Id$
2 // Author: Wim Lavrijsen, Jul 2004
3 
4 // Bindings
5 #include "PyROOT.h"
6 #include "PyStrings.h"
7 #include "Pythonize.h"
8 #include "ObjectProxy.h"
9 #include "MethodProxy.h"
10 #include "RootWrapper.h"
11 #include "Utility.h"
12 #include "PyCallable.h"
13 #include "TPyBufferFactory.h"
14 #include "TFunctionHolder.h"
15 #include "Converters.h"
16 #include "TMemoryRegulator.h"
17 #include "Utility.h"
18 
19 // ROOT
20 #include "TClass.h"
21 #include "TFunction.h"
22 #include "TInterpreter.h"
23 #include "TMethod.h"
24 
25 #include "TClonesArray.h"
26 #include "TCollection.h"
27 #include "TDirectory.h"
28 #include "TError.h"
29 #include "TFile.h"
30 #include "TKey.h"
31 #include "TObject.h"
32 #include "TObjArray.h"
33 #include "TSeqCollection.h"
34 
35 #include "TTree.h"
36 #include "TBranch.h"
37 #include "TBranchElement.h"
38 #include "TBranchObject.h"
39 #include "TLeaf.h"
40 #include "TLeafElement.h"
41 #include "TLeafObject.h"
42 #include "TStreamerElement.h"
43 #include "TStreamerInfo.h"
44 
45 #include "ROOT/RVec.hxx"
46 
47 // Standard
48 #include <stdexcept>
49 #include <string>
50 #include <utility>
51 
52 #include <stdio.h>
53 #include <string.h> // only needed for Cling TMinuit workaround
54 
55 
56 // temp (?)
57 static inline TClass* OP2TCLASS( PyROOT::ObjectProxy* pyobj ) {
58  return TClass::GetClass( Cppyy::GetFinalName( pyobj->ObjectIsA() ).c_str());
59 }
60 //-- temp
61 
62 //- data and local helpers ---------------------------------------------------
63 namespace PyROOT {
65 }
66 
67 namespace {
68 
69 // for convenience
70  using namespace PyROOT;
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 /// prevents calls to Py_TYPE(pyclass)->tp_getattr, which is unnecessary for our
74 /// purposes here and could tickle problems w/ spurious lookups into ROOT meta
75 
76  Bool_t HasAttrDirect( PyObject* pyclass, PyObject* pyname, Bool_t mustBePyROOT = kFALSE ) {
77  PyObject* attr = PyType_Type.tp_getattro( pyclass, pyname );
78  if ( attr != 0 && ( ! mustBePyROOT || MethodProxy_Check( attr ) ) ) {
79  Py_DECREF( attr );
80  return kTRUE;
81  }
82 
83  PyErr_Clear();
84  return kFALSE;
85  }
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// prevents calls to descriptors
89 
90  PyObject* PyObject_GetAttrFromDict( PyObject* pyclass, PyObject* pyname ) {
91  PyObject* dict = PyObject_GetAttr( pyclass, PyStrings::gDict );
92  PyObject* attr = PyObject_GetItem( dict, pyname );
93  Py_DECREF( dict );
94  return attr;
95  }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 /// Scan the name of the class and determine whether it is a template instantiation.
99 
100  inline Bool_t IsTemplatedSTLClass( const std::string& name, const std::string& klass ) {
101  const int nsize = (int)name.size();
102  const int ksize = (int)klass.size();
103 
104  return ( ( ksize < nsize && name.substr(0,ksize) == klass ) ||
105  ( ksize+5 < nsize && name.substr(5,ksize) == klass ) ) &&
106  name.find( "::", name.find( ">" ) ) == std::string::npos;
107  }
108 
109 // to prevent compiler warnings about const char* -> char*
110  inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth )
111  {
112  // Helper; call method with signature: obj->meth().
113  Py_INCREF( obj );
114  PyObject* result = PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "" ) );
115  Py_DECREF( obj );
116  return result;
117  }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Helper; call method with signature: obj->meth( arg1 ).
121 
122  inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1 )
123  {
124  Py_INCREF( obj );
125  PyObject* result = PyObject_CallMethod(
126  obj, const_cast< char* >( meth ), const_cast< char* >( "O" ), arg1 );
127  Py_DECREF( obj );
128  return result;
129  }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Helper; call method with signature: obj->meth( arg1, arg2 ).
133 
134  inline PyObject* CallPyObjMethod(
135  PyObject* obj, const char* meth, PyObject* arg1, PyObject* arg2 )
136  {
137  Py_INCREF( obj );
138  PyObject* result = PyObject_CallMethod(
139  obj, const_cast< char* >( meth ), const_cast< char* >( "OO" ), arg1, arg2 );
140  Py_DECREF( obj );
141  return result;
142  }
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 /// Helper; call method with signature: obj->meth( arg1, int ).
146 
147  inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1, int arg2 )
148  {
149  Py_INCREF( obj );
150  PyObject* result = PyObject_CallMethod(
151  obj, const_cast< char* >( meth ), const_cast< char* >( "Oi" ), arg1, arg2 );
152  Py_DECREF( obj );
153  return result;
154  }
155 
156 
157 //- helpers --------------------------------------------------------------------
158  PyObject* PyStyleIndex( PyObject* self, PyObject* index )
159  {
160  // Helper; converts python index into straight C index.
161  Py_ssize_t idx = PyInt_AsSsize_t( index );
162  if ( idx == (Py_ssize_t)-1 && PyErr_Occurred() )
163  return 0;
164 
165  Py_ssize_t size = PySequence_Size( self );
166  if ( idx >= size || ( idx < 0 && idx < -size ) ) {
167  PyErr_SetString( PyExc_IndexError, "index out of range" );
168  return 0;
169  }
170 
171  PyObject* pyindex = 0;
172  if ( idx >= 0 ) {
173  Py_INCREF( index );
174  pyindex = index;
175  } else
176  pyindex = PyLong_FromLong( size + idx );
177 
178  return pyindex;
179  }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Helper; call method with signature: meth( pyindex ).
183 
184  inline PyObject* CallSelfIndex( ObjectProxy* self, PyObject* idx, const char* meth )
185  {
186  Py_INCREF( (PyObject*)self );
187  PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
188  if ( ! pyindex ) {
189  Py_DECREF( (PyObject*)self );
190  return 0;
191  }
192 
193  PyObject* result = CallPyObjMethod( (PyObject*)self, meth, pyindex );
194  Py_DECREF( pyindex );
195  Py_DECREF( (PyObject*)self );
196  return result;
197  }
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Helper; convert generic python object into a boolean value.
201 
202  inline PyObject* BoolNot( PyObject* value )
203  {
204  if ( PyObject_IsTrue( value ) == 1 ) {
205  Py_INCREF( Py_False );
206  Py_DECREF( value );
207  return Py_False;
208  } else {
209  Py_INCREF( Py_True );
210  Py_XDECREF( value );
211  return Py_True;
212  }
213  }
214 
215 //- "smart pointer" behavior ---------------------------------------------------
216  PyObject* DeRefGetAttr( PyObject* self, PyObject* name )
217  {
218  // Follow operator*() if present (available in python as __deref__), so that
219  // smart pointers behave as expected.
220  if ( ! PyROOT_PyUnicode_Check( name ) )
221  PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );
222 
223  PyObject* pyptr = CallPyObjMethod( self, "__deref__" );
224  if ( ! pyptr )
225  return 0;
226 
227  // prevent a potential infinite loop
228  if ( Py_TYPE(pyptr) == Py_TYPE(self) ) {
229  PyObject* val1 = PyObject_Str( self );
230  PyObject* val2 = PyObject_Str( name );
231  PyErr_Format( PyExc_AttributeError, "%s has no attribute \'%s\'",
233  Py_DECREF( val2 );
234  Py_DECREF( val1 );
235 
236  Py_DECREF( pyptr );
237  return 0;
238  }
239 
240  PyObject* result = PyObject_GetAttr( pyptr, name );
241  Py_DECREF( pyptr );
242  return result;
243  }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Follow operator->() if present (available in python as __follow__), so that
247 /// smart pointers behave as expected.
248 
249  PyObject* FollowGetAttr( PyObject* self, PyObject* name )
250  {
251  if ( ! PyROOT_PyUnicode_Check( name ) )
252  PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );
253 
254  PyObject* pyptr = CallPyObjMethod( self, "__follow__" );
255  if ( ! pyptr )
256  return 0;
257 
258  PyObject* result = PyObject_GetAttr( pyptr, name );
259  Py_DECREF( pyptr );
260  return result;
261  }
262 
263 //- TObject behavior -----------------------------------------------------------
264  PyObject* TObjectContains( PyObject* self, PyObject* obj )
265  {
266  // Implement python's __contains__ with TObject::FindObject.
267  if ( ! ( ObjectProxy_Check( obj ) || PyROOT_PyUnicode_Check( obj ) ) )
268  return PyInt_FromLong( 0l );
269 
270  PyObject* found = CallPyObjMethod( self, "FindObject", obj );
271  PyObject* result = PyInt_FromLong( PyObject_IsTrue( found ) );
272  Py_DECREF( found );
273  return result;
274  }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Implement python's __cmp__ with TObject::Compare.
278 
279  PyObject* TObjectCompare( PyObject* self, PyObject* obj )
280  {
281  if ( ! ObjectProxy_Check( obj ) )
282  return PyInt_FromLong( -1l );
283 
284  return CallPyObjMethod( self, "Compare", obj );
285  }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Implement python's __eq__ with TObject::IsEqual.
289 
290  PyObject* TObjectIsEqual( PyObject* self, PyObject* obj )
291  {
292  if ( ! ObjectProxy_Check( obj ) || ! ((ObjectProxy*)obj)->fObject )
293  return ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );
294 
295  return CallPyObjMethod( self, "IsEqual", obj );
296  }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Implement python's __ne__ in terms of not TObject::IsEqual.
300 
301  PyObject* TObjectIsNotEqual( PyObject* self, PyObject* obj )
302  {
303  if ( ! ObjectProxy_Check( obj ) || ! ((ObjectProxy*)obj)->fObject )
304  return ObjectProxy_Type.tp_richcompare( self, obj, Py_NE );
305 
306  return BoolNot( CallPyObjMethod( self, "IsEqual", obj ) );
307  }
308 
309 ////////////////////////////////////////////////////////////////////////////////
310 /// Contrary to TObjectIsEqual, it can now not be relied upon that the only
311 /// non-ObjectProxy obj is None, as any operator==(), taking any object (e.g.
312 /// an enum) can be implemented. However, those cases will yield an exception
313 /// if presented with None.
314 
315  PyObject* GenObjectIsEqual( PyObject* self, PyObject* obj )
316  {
317  PyObject* result = CallPyObjMethod( self, "__cpp_eq__", obj );
318  if ( ! result ) {
319  PyErr_Clear();
320  result = ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );
321  }
322 
323  return result;
324  }
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 /// Reverse of GenObjectIsEqual, if operator!= defined.
328 
329  PyObject* GenObjectIsNotEqual( PyObject* self, PyObject* obj )
330  {
331  PyObject* result = CallPyObjMethod( self, "__cpp_ne__", obj );
332  if ( ! result ) {
333  PyErr_Clear();
334  result = ObjectProxy_Type.tp_richcompare( self, obj, Py_NE );
335  }
336 
337  return result;
338  }
339 
340 //- TClass behavior ------------------------------------------------------------
341  PyObject* TClassStaticCast( ObjectProxy* self, PyObject* args )
342  {
343  // Implemented somewhat different than TClass::DynamicClass, in that "up" is
344  // chosen automatically based on the relationship between self and arg pyclass.
345  ObjectProxy* pyclass = 0; PyObject* pyobject = 0;
346  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O:StaticCast" ),
347  &ObjectProxy_Type, &pyclass, &pyobject ) )
348  return 0;
349 
350  // check the given arguments (dcasts are necessary b/c of could be a TQClass
351  TClass* from = (TClass*)OP2TCLASS(self)->DynamicCast( TClass::Class(), self->GetObject() );
352  TClass* to = (TClass*)OP2TCLASS(self)->DynamicCast( TClass::Class(), pyclass->GetObject() );
353 
354  if ( ! from ) {
355  PyErr_SetString( PyExc_TypeError, "unbound method TClass::StaticCast "
356  "must be called with a TClass instance as first argument" );
357  return 0;
358  }
359 
360  if ( ! to ) {
361  PyErr_SetString( PyExc_TypeError, "could not convert argument 1 (TClass* expected)" );
362  return 0;
363  }
364 
365  // retrieve object address
366  void* address = 0;
367  if ( ObjectProxy_Check( pyobject ) ) address = ((ObjectProxy*)pyobject)->GetObject();
368  else if ( PyInt_Check( pyobject ) || PyLong_Check( pyobject ) ) address = (void*)PyLong_AsLong( pyobject );
369  else Utility::GetBuffer( pyobject, '*', 1, address, kFALSE );
370 
371  if ( ! address ) {
372  PyErr_SetString( PyExc_TypeError, "could not convert argument 2 (void* expected)" );
373  return 0;
374  }
375 
376  // determine direction of cast
377  int up = -1;
378  if ( from->InheritsFrom( to ) ) up = 1;
379  else if ( to->InheritsFrom( from ) ) {
380  TClass* tmp = to; to = from; from = tmp;
381  up = 0;
382  }
383 
384  if ( up == -1 ) {
385  PyErr_Format( PyExc_TypeError, "unable to cast %s to %s", from->GetName(), to->GetName() );
386  return 0;
387  }
388 
389  // perform actual cast
390  void* result = from->DynamicCast( to, address, (Bool_t)up );
391 
392  // at this point, "result" can't be null (but is still safe if it is)
393  return BindCppObjectNoCast( result, Cppyy::GetScope( to->GetName() ) );
394  }
395 
396 ////////////////////////////////////////////////////////////////////////////////
397 /// TClass::DynamicCast returns a void* that the user still has to cast (it
398 /// will have the proper offset, though). Fix this by providing the requested
399 /// binding if the cast succeeded.
400 
401  PyObject* TClassDynamicCast( ObjectProxy* self, PyObject* args )
402  {
403  ObjectProxy* pyclass = 0; PyObject* pyobject = 0;
404  Long_t up = 1;
405  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O|l:DynamicCast" ),
406  &ObjectProxy_Type, &pyclass, &pyobject, &up ) )
407  return 0;
408 
409  // perform actual cast
410  PyObject* meth = PyObject_GetAttr( (PyObject*)self, PyStrings::gTClassDynCast );
411  PyObject* ptr = meth ? PyObject_Call( meth, args, 0 ) : 0;
412  Py_XDECREF( meth );
413 
414  // simply forward in case of call failure
415  if ( ! ptr )
416  return ptr;
417 
418  // retrieve object address
419  void* address = 0;
420  if ( ObjectProxy_Check( pyobject ) ) address = ((ObjectProxy*)pyobject)->GetObject();
421  else if ( PyInt_Check( pyobject ) || PyLong_Check( pyobject ) ) address = (void*)PyLong_AsLong( pyobject );
422  else Utility::GetBuffer( pyobject, '*', 1, address, kFALSE );
423 
424  if ( PyErr_Occurred() ) {
425  PyErr_Clear();
426  return ptr;
427  }
428 
429  // now use binding to return a usable class
430  TClass* klass = 0;
431  if ( up ) { // up-cast: result is a base
432  klass = (TClass*)OP2TCLASS(pyclass)->DynamicCast( TClass::Class(), pyclass->GetObject() );
433  } else { // down-cast: result is a derived
434  klass = (TClass*)OP2TCLASS(self)->DynamicCast( TClass::Class(), self->GetObject() );
435  }
436 
437  PyObject* result = BindCppObjectNoCast( (void*)address, Cppyy::GetScope( klass->GetName() ) );
438  Py_DECREF( ptr );
439 
440  return result;
441  }
442 
443 //- TCollection behavior -------------------------------------------------------
444  PyObject* TCollectionExtend( PyObject* self, PyObject* obj )
445  {
446  // Implement a python-style extend with TCollection::Add.
447  for ( Py_ssize_t i = 0; i < PySequence_Size( obj ); ++i ) {
448  PyObject* item = PySequence_GetItem( obj, i );
449  PyObject* result = CallPyObjMethod( self, "Add", item );
450  Py_XDECREF( result );
451  Py_DECREF( item );
452  }
453 
454  Py_INCREF( Py_None );
455  return Py_None;
456  }
457 
458 ////////////////////////////////////////////////////////////////////////////////
459 /// Implement a python-style remove with TCollection::Add.
460 
461  PyObject* TCollectionRemove( PyObject* self, PyObject* obj )
462  {
463  PyObject* result = CallPyObjMethod( self, "Remove", obj );
464  if ( ! result )
465  return 0;
466 
467  if ( ! PyObject_IsTrue( result ) ) {
468  Py_DECREF( result );
469  PyErr_SetString( PyExc_ValueError, "list.remove(x): x not in list" );
470  return 0;
471  }
472 
473  Py_DECREF( result );
474  Py_INCREF( Py_None );
475  return Py_None;
476  }
477 
478 ////////////////////////////////////////////////////////////////////////////////
479 /// Implement python's __add__ with the pythonized extend for TCollections.
480 
481  PyObject* TCollectionAdd( PyObject* self, PyObject* other )
482  {
483  PyObject* l = CallPyObjMethod( self, "Clone" );
484  if ( ! l )
485  return 0;
486 
487  PyObject* result = CallPyObjMethod( l, "extend", other );
488  if ( ! result ) {
489  Py_DECREF( l );
490  return 0;
491  }
492 
493  return l;
494  }
495 
496 ////////////////////////////////////////////////////////////////////////////////
497 /// Implement python's __mul__ with the pythonized extend for TCollections.
498 
499  PyObject* TCollectionMul( ObjectProxy* self, PyObject* pymul )
500  {
501  Long_t imul = PyLong_AsLong( pymul );
502  if ( imul == -1 && PyErr_Occurred() )
503  return 0;
504 
505  if ( ! self->GetObject() ) {
506  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
507  return 0;
508  }
509 
510  PyObject* nseq = BindCppObject(
511  Cppyy::Construct( self->ObjectIsA() ), self->ObjectIsA() );
512 
513  for ( Long_t i = 0; i < imul; ++i ) {
514  PyObject* result = CallPyObjMethod( nseq, "extend", (PyObject*)self );
515  Py_DECREF( result );
516  }
517 
518  return nseq;
519  }
520 
521 ////////////////////////////////////////////////////////////////////////////////
522 /// Implement python's __imul__ with the pythonized extend for TCollections.
523 
524  PyObject* TCollectionIMul( PyObject* self, PyObject* pymul )
525  {
526  Long_t imul = PyLong_AsLong( pymul );
527  if ( imul == -1 && PyErr_Occurred() )
528  return 0;
529 
530  PyObject* l = PySequence_List( self );
531 
532  for ( Long_t i = 0; i < imul - 1; ++i ) {
533  CallPyObjMethod( self, "extend", l );
534  }
535 
536  Py_INCREF( self );
537  return self;
538  }
539 
540 ////////////////////////////////////////////////////////////////////////////////
541 /// Implement a python-style count for TCollections.
542 
543  PyObject* TCollectionCount( PyObject* self, PyObject* obj )
544  {
545  Py_ssize_t count = 0;
546  for ( Py_ssize_t i = 0; i < PySequence_Size( self ); ++i ) {
547  PyObject* item = PySequence_GetItem( self, i );
548  PyObject* found = PyObject_RichCompare( item, obj, Py_EQ );
549 
550  Py_DECREF( item );
551 
552  if ( ! found )
553  return 0; // internal problem
554 
555  if ( PyObject_IsTrue( found ) )
556  count += 1;
557  Py_DECREF( found );
558  }
559 
560  return PyInt_FromSsize_t( count );
561  }
562 
563 ////////////////////////////////////////////////////////////////////////////////
564 /// Python __iter__ protocol for TCollections.
565 
566  PyObject* TCollectionIter( ObjectProxy* self ) {
567  if ( ! self->GetObject() ) {
568  PyErr_SetString( PyExc_TypeError, "iteration over non-sequence" );
569  return 0;
570  }
571 
572  TCollection* col =
573  (TCollection*)OP2TCLASS(self)->DynamicCast( TCollection::Class(), self->GetObject() );
574 
575  PyObject* pyobject = BindCppObject( (void*) new TIter( col ), "TIter" );
576  ((ObjectProxy*)pyobject)->HoldOn();
577  return pyobject;
578  }
579 
580 
581 //- TSeqCollection behavior ----------------------------------------------------
582  PyObject* TSeqCollectionGetItem( ObjectProxy* self, PySliceObject* index )
583  {
584  // Python-style indexing and size checking for getting objects from a TCollection.
585  if ( PySlice_Check( index ) ) {
586  if ( ! self->GetObject() ) {
587  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
588  return 0;
589  }
590 
591  TClass* clSeq = OP2TCLASS(self);
592  TSeqCollection* oseq =
593  (TSeqCollection*)clSeq->DynamicCast( TSeqCollection::Class(), self->GetObject() );
594  TSeqCollection* nseq = (TSeqCollection*)clSeq->New();
595 
596  Py_ssize_t start, stop, step;
597  PySlice_GetIndices( (PyROOT_PySliceCast)index, oseq->GetSize(), &start, &stop, &step );
598 
599  for ( Py_ssize_t i = start; i < stop; i += step ) {
600  nseq->Add( oseq->At( (Int_t)i ) );
601  }
602 
603  return BindCppObject( (void*) nseq, clSeq->GetName() );
604  }
605 
606  return CallSelfIndex( self, (PyObject*)index, "At" );
607  }
608 
609 ////////////////////////////////////////////////////////////////////////////////
610 /// Python-style indexing and size checking for setting objects in a TCollection.
611 
612  PyObject* TSeqCollectionSetItem( ObjectProxy* self, PyObject* args )
613  {
614  PyObject* index = 0, *obj = 0;
615  if ( ! PyArg_ParseTuple( args,
616  const_cast< char* >( "OO:__setitem__" ), &index, &obj ) )
617  return 0;
618 
619  if ( PySlice_Check( index ) ) {
620  if ( ! self->GetObject() ) {
621  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
622  return 0;
623  }
624 
626  TSeqCollection::Class(), self->GetObject() );
627 
628  Py_ssize_t start, stop, step;
629  PySlice_GetIndices( (PyROOT_PySliceCast)index, oseq->GetSize(), &start, &stop, &step );
630  for ( Py_ssize_t i = stop - step; i >= start; i -= step ) {
631  oseq->RemoveAt( (Int_t)i );
632  }
633 
634  for ( Py_ssize_t i = 0; i < PySequence_Size( obj ); ++i ) {
635  ObjectProxy* item = (ObjectProxy*)PySequence_GetItem( obj, i );
636  item->Release();
637  oseq->AddAt( (TObject*) item->GetObject(), (Int_t)(i + start) );
638  Py_DECREF( item );
639  }
640 
641  Py_INCREF( Py_None );
642  return Py_None;
643  }
644 
645  PyObject* pyindex = PyStyleIndex( (PyObject*)self, index );
646  if ( ! pyindex )
647  return 0;
648 
649  PyObject* result = CallPyObjMethod( (PyObject*)self, "RemoveAt", pyindex );
650  if ( ! result ) {
651  Py_DECREF( pyindex );
652  return 0;
653  }
654 
655  Py_DECREF( result );
656  result = CallPyObjMethod( (PyObject*)self, "AddAt", obj, pyindex );
657  Py_DECREF( pyindex );
658  return result;
659  }
660 
661 ////////////////////////////////////////////////////////////////////////////////
662 /// Implement python's __del__ with TCollection::RemoveAt.
663 
664  PyObject* TSeqCollectionDelItem( ObjectProxy* self, PySliceObject* index )
665  {
666  if ( PySlice_Check( index ) ) {
667  if ( ! self->GetObject() ) {
668  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
669  return 0;
670  }
671 
673  TSeqCollection::Class(), self->GetObject() );
674 
675  Py_ssize_t start, stop, step;
676  PySlice_GetIndices( (PyROOT_PySliceCast)index, oseq->GetSize(), &start, &stop, &step );
677  for ( Py_ssize_t i = stop - step; i >= start; i -= step ) {
678  oseq->RemoveAt( (Int_t)i );
679  }
680 
681  Py_INCREF( Py_None );
682  return Py_None;
683  }
684 
685  PyObject* result = CallSelfIndex( self, (PyObject*)index, "RemoveAt" );
686  if ( ! result )
687  return 0;
688 
689  Py_DECREF( result );
690  Py_INCREF( Py_None );
691  return Py_None;
692  }
693 
694 ////////////////////////////////////////////////////////////////////////////////
695 /// Python-style insertion implemented with TCollection::AddAt.
696 
697  PyObject* TSeqCollectionInsert( PyObject* self, PyObject* args )
698  {
699  PyObject* obj = 0; Long_t idx = 0;
700  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "lO:insert" ), &idx, &obj ) )
701  return 0;
702 
703  Py_ssize_t size = PySequence_Size( self );
704  if ( idx < 0 )
705  idx = 0;
706  else if ( size < idx )
707  idx = size;
708 
709  return CallPyObjMethod( self, "AddAt", obj, idx );
710  }
711 
712 ////////////////////////////////////////////////////////////////////////////////
713 /// Implement a python-style pop for TCollections.
714 
715  PyObject* TSeqCollectionPop( ObjectProxy* self, PyObject* args )
716  {
717  int nArgs = PyTuple_GET_SIZE( args );
718  if ( nArgs == 0 ) {
719  // create the default argument 'end of sequence'
720  PyObject* index = PyInt_FromSsize_t( PySequence_Size( (PyObject*)self ) - 1 );
721  PyObject* result = CallSelfIndex( self, index, "RemoveAt" );
722  Py_DECREF( index );
723  return result;
724  } else if ( nArgs != 1 ) {
725  PyErr_Format( PyExc_TypeError,
726  "pop() takes at most 1 argument (%d given)", nArgs );
727  return 0;
728  }
729 
730  return CallSelfIndex( self, PyTuple_GET_ITEM( args, 0 ), "RemoveAt" );
731  }
732 
733 ////////////////////////////////////////////////////////////////////////////////
734 /// Implement a python-style reverse for TCollections.
735 
736  PyObject* TSeqCollectionReverse( PyObject* self )
737  {
738  PyObject* tup = PySequence_Tuple( self );
739  if ( ! tup )
740  return 0;
741 
742  PyObject* result = CallPyObjMethod( self, "Clear" );
743  Py_XDECREF( result );
744 
745  for ( Py_ssize_t i = 0; i < PySequence_Size( tup ); ++i ) {
746  PyObject* retval = CallPyObjMethod( self, "AddAt", PyTuple_GET_ITEM( tup, i ), 0 );
747  Py_XDECREF( retval );
748  }
749 
750  Py_INCREF( Py_None );
751  return Py_None;
752  }
753 
754 ////////////////////////////////////////////////////////////////////////////////
755 /// Implement a python-style sort for TCollections.
756 
757  PyObject* TSeqCollectionSort( PyObject* self, PyObject* args, PyObject* kw )
758  {
759  if ( PyTuple_GET_SIZE( args ) == 0 && ! kw ) {
760  // no specialized sort, use ROOT one
761  return CallPyObjMethod( self, "Sort" );
762  } else {
763  // sort in a python list copy
764  PyObject* l = PySequence_List( self );
765  PyObject* result = 0;
766  if ( PyTuple_GET_SIZE( args ) == 1 )
767  result = CallPyObjMethod( l, "sort", PyTuple_GET_ITEM( args, 0 ) );
768  else {
769  PyObject* pymeth = PyObject_GetAttrString( l, const_cast< char* >( "sort" ) );
770  result = PyObject_Call( pymeth, args, kw );
771  Py_DECREF( pymeth );
772  }
773 
774  Py_XDECREF( result );
775  if ( PyErr_Occurred() ) {
776  Py_DECREF( l );
777  return 0;
778  }
779 
780  result = CallPyObjMethod( self, "Clear" );
781  Py_XDECREF( result );
782  result = CallPyObjMethod( self, "extend", l );
783  Py_XDECREF( result );
784  Py_DECREF( l );
785 
786  Py_INCREF( Py_None );
787  return Py_None;
788  }
789  }
790 
791 ////////////////////////////////////////////////////////////////////////////////
792 /// Implement a python-style index with TCollection::IndexOf.
793 
794  PyObject* TSeqCollectionIndex( PyObject* self, PyObject* obj )
795  {
796  PyObject* index = CallPyObjMethod( self, "IndexOf", obj );
797  if ( ! index )
798  return 0;
799 
800  if ( PyLong_AsLong( index ) < 0 ) {
801  Py_DECREF( index );
802  PyErr_SetString( PyExc_ValueError, "list.index(x): x not in list" );
803  return 0;
804  }
805 
806  return index;
807  }
808 
809 //- TObjArray behavior ---------------------------------------------------------
810  PyObject* TObjArrayLen( PyObject* self )
811  {
812  // GetSize on a TObjArray returns its capacity, not size in use
813  PyObject* size = CallPyObjMethod( self, "GetLast" );
814  if ( ! size )
815  return 0;
816 
817  long lsize = PyLong_AsLong( size );
818  if ( lsize == -1 && PyErr_Occurred() )
819  return 0;
820 
821  Py_DECREF( size );
822  return PyInt_FromLong( lsize + 1 );
823  }
824 
825 
826 //- TClonesArray behavior ------------------------------------------------------
827  PyObject* TClonesArraySetItem( ObjectProxy* self, PyObject* args )
828  {
829  // TClonesArray sets objects by constructing them in-place; which is impossible
830  // to support as the python object given as value must exist a priori. It can,
831  // however, be memcpy'd and stolen, caveat emptor.
832  ObjectProxy* pyobj = 0; PyObject* idx = 0;
833  if ( ! PyArg_ParseTuple( args,
834  const_cast< char* >( "OO!:__setitem__" ), &idx, &ObjectProxy_Type, &pyobj ) )
835  return 0;
836 
837  if ( ! self->GetObject() ) {
838  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
839  return 0;
840  }
841 
842  PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
843  if ( ! pyindex )
844  return 0;
845  int index = (int)PyLong_AsLong( pyindex );
846  Py_DECREF( pyindex );
847 
848  // get hold of the actual TClonesArray
849  TClonesArray* cla =
850  (TClonesArray*)OP2TCLASS(self)->DynamicCast( TClonesArray::Class(), self->GetObject() );
851 
852  if ( ! cla ) {
853  PyErr_SetString( PyExc_TypeError, "attempt to call with null object" );
854  return 0;
855  }
856 
857  if ( Cppyy::GetScope( cla->GetClass()->GetName() ) != pyobj->ObjectIsA() ) {
858  PyErr_Format( PyExc_TypeError, "require object of type %s, but %s given",
859  cla->GetClass()->GetName(), Cppyy::GetFinalName( pyobj->ObjectIsA() ).c_str() );
860  }
861 
862  // destroy old stuff, if applicable
863  if ( ((const TClonesArray&)*cla)[index] ) {
864  cla->RemoveAt( index );
865  }
866 
867  if ( pyobj->GetObject() ) {
868  // accessing an entry will result in new, unitialized memory (if properly used)
869  TObject* object = (*cla)[index];
870  pyobj->Release();
871  TMemoryRegulator::RegisterObject( pyobj, object );
872  memcpy( (void*)object, pyobj->GetObject(), cla->GetClass()->Size() );
873  }
874 
875  Py_INCREF( Py_None );
876  return Py_None;
877  }
878 
879 //- vector behavior as primitives ----------------------------------------------
880  typedef struct {
881  PyObject_HEAD
882  PyObject* vi_vector;
883  void* vi_data;
884  PyROOT::TConverter* vi_converter;
885  Py_ssize_t vi_pos;
886  Py_ssize_t vi_len;
887  Py_ssize_t vi_stride;
888  } vectoriterobject;
889 
890  static void vectoriter_dealloc( vectoriterobject* vi ) {
891  Py_XDECREF( vi->vi_vector );
892  delete vi->vi_converter;
893  PyObject_GC_Del( vi );
894  }
895 
896  static int vectoriter_traverse( vectoriterobject* vi, visitproc visit, void* arg ) {
897  Py_VISIT( vi->vi_vector );
898  return 0;
899  }
900 
901  static PyObject* vectoriter_iternext( vectoriterobject* vi ) {
902  if ( vi->vi_pos >= vi->vi_len )
903  return nullptr;
904 
905  PyObject* result = nullptr;
906 
907  if ( vi->vi_data && vi->vi_converter ) {
908  void* location = (void*)((ptrdiff_t)vi->vi_data + vi->vi_stride * vi->vi_pos );
909  result = vi->vi_converter->FromMemory( location );
910  } else {
911  PyObject* pyindex = PyLong_FromLong( vi->vi_pos );
912  result = CallPyObjMethod( (PyObject*)vi->vi_vector, "_vector__at", pyindex );
913  Py_DECREF( pyindex );
914  }
915 
916  vi->vi_pos += 1;
917  return result;
918  }
919 
920  PyTypeObject VectorIter_Type = {
921  PyVarObject_HEAD_INIT( &PyType_Type, 0 )
922  (char*)"ROOT.vectoriter", // tp_name
923  sizeof(vectoriterobject), // tp_basicsize
924  0,
925  (destructor)vectoriter_dealloc, // tp_dealloc
926  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
927  Py_TPFLAGS_DEFAULT |
928  Py_TPFLAGS_HAVE_GC, // tp_flags
929  0,
930  (traverseproc)vectoriter_traverse, // tp_traverse
931  0, 0, 0,
932  PyObject_SelfIter, // tp_iter
933  (iternextfunc)vectoriter_iternext, // tp_iternext
934  0, // tp_methods
935  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
936 #if PY_VERSION_HEX >= 0x02030000
937  , 0 // tp_del
938 #endif
939 #if PY_VERSION_HEX >= 0x02060000
940  , 0 // tp_version_tag
941 #endif
942 #if PY_VERSION_HEX >= 0x03040000
943  , 0 // tp_finalize
944 #endif
945  };
946 
947  static PyObject* vector_iter( PyObject* v ) {
948  vectoriterobject* vi = PyObject_GC_New( vectoriterobject, &VectorIter_Type );
949  if ( ! vi ) return NULL;
950 
951  Py_INCREF( v );
952  vi->vi_vector = v;
953 
954  PyObject* pyvalue_type = PyObject_GetAttrString( (PyObject*)Py_TYPE(v), "value_type" );
955  PyObject* pyvalue_size = PyObject_GetAttrString( (PyObject*)Py_TYPE(v), "value_size" );
956 
957  if ( pyvalue_type && pyvalue_size ) {
958  PyObject* pydata = CallPyObjMethod( v, "data" );
959  if ( !pydata || Utility::GetBuffer( pydata, '*', 1, vi->vi_data, kFALSE ) == 0 )
960  vi->vi_data = nullptr;
961  Py_XDECREF( pydata );
962 
963  vi->vi_converter = PyROOT::CreateConverter( PyROOT_PyUnicode_AsString( pyvalue_type ) );
964  vi->vi_stride = PyLong_AsLong( pyvalue_size );
965  } else {
966  PyErr_Clear();
967  vi->vi_data = nullptr;
968  vi->vi_converter = nullptr;
969  vi->vi_stride = 0;
970  }
971 
972  Py_XDECREF( pyvalue_size );
973  Py_XDECREF( pyvalue_type );
974 
975  vi->vi_len = vi->vi_pos = 0;
976  vi->vi_len = PySequence_Size( v );
977 
978  PyObject_GC_Track( vi );
979  return (PyObject*)vi;
980  }
981 
982 
983  PyObject* VectorGetItem( ObjectProxy* self, PySliceObject* index )
984  {
985  // Implement python's __getitem__ for std::vector<>s.
986  if ( PySlice_Check( index ) ) {
987  if ( ! self->GetObject() ) {
988  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
989  return 0;
990  }
991 
992  PyObject* pyclass = PyObject_GetAttr( (PyObject*)self, PyStrings::gClass );
993  PyObject* nseq = PyObject_CallObject( pyclass, NULL );
994  Py_DECREF( pyclass );
995 
996  Py_ssize_t start, stop, step;
997  PySlice_GetIndices( (PyROOT_PySliceCast)index, PyObject_Length( (PyObject*)self ), &start, &stop, &step );
998  for ( Py_ssize_t i = start; i < stop; i += step ) {
999  PyObject* pyidx = PyInt_FromSsize_t( i );
1000  CallPyObjMethod( nseq, "push_back", CallPyObjMethod( (PyObject*)self, "_vector__at", pyidx ) );
1001  Py_DECREF( pyidx );
1002  }
1003 
1004  return nseq;
1005  }
1006 
1007  return CallSelfIndex( self, (PyObject*)index, "_vector__at" );
1008  }
1009 
1010  PyObject* VectorBoolSetItem( ObjectProxy* self, PyObject* args )
1011  {
1012  // std::vector<bool> is a special-case in C++, and its return type depends on
1013  // the compiler: treat it special here as well
1014  int bval = 0; PyObject* idx = 0;
1015  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "Oi:__setitem__" ), &idx, &bval ) )
1016  return 0;
1017 
1018  if ( ! self->GetObject() ) {
1019  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
1020  return 0;
1021  }
1022 
1023  PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
1024  if ( ! pyindex )
1025  return 0;
1026  int index = (int)PyLong_AsLong( pyindex );
1027  Py_DECREF( pyindex );
1028 
1029  std::string clName = Cppyy::GetFinalName( self->ObjectIsA() );
1030  std::string::size_type pos = clName.find( "vector<bool" );
1031  if ( pos != 0 && pos != 5 /* following std:: */ ) {
1032  PyErr_Format( PyExc_TypeError,
1033  "require object of type std::vector<bool>, but %s given",
1034  Cppyy::GetFinalName( self->ObjectIsA() ).c_str() );
1035  return 0;
1036  }
1037 
1038  // get hold of the actual std::vector<bool> (no cast, as vector is never a base)
1039  std::vector<bool>* vb = (std::vector<bool>*)self->GetObject();
1040 
1041  // finally, set the value
1042  (*vb)[ index ] = (bool)bval;
1043 
1044  Py_INCREF( Py_None );
1045  return Py_None;
1046  }
1047 
1048 //- map behavior as primitives ------------------------------------------------
1049  PyObject* MapContains( PyObject* self, PyObject* obj )
1050  {
1051  // Implement python's __contains__ for std::map<>s.
1052  PyObject* result = 0;
1053 
1054  PyObject* iter = CallPyObjMethod( self, "find", obj );
1055  if ( ObjectProxy_Check( iter ) ) {
1056  PyObject* end = CallPyObjMethod( self, "end" );
1057  if ( ObjectProxy_Check( end ) ) {
1058  if ( ! PyObject_RichCompareBool( iter, end, Py_EQ ) ) {
1059  Py_INCREF( Py_True );
1060  result = Py_True;
1061  }
1062  }
1063  Py_XDECREF( end );
1064  }
1065  Py_XDECREF( iter );
1066 
1067  if ( ! result ) {
1068  PyErr_Clear(); // e.g. wrong argument type, which should always lead to False
1069  Py_INCREF( Py_False );
1070  result = Py_False;
1071  }
1072 
1073  return result;
1074  }
1075 
1076 //- STL container iterator support --------------------------------------------
1077  PyObject* StlSequenceIter( PyObject* self )
1078  {
1079  // Implement python's __iter__ for std::iterator<>s.
1080  PyObject* iter = CallPyObjMethod( self, "begin" );
1081  if ( iter ) {
1082  PyObject* end = CallPyObjMethod( self, "end" );
1083  if ( end )
1084  PyObject_SetAttr( iter, PyStrings::gEnd, end );
1085  Py_XDECREF( end );
1086 
1087  // add iterated collection as attribute so its refcount stays >= 1 while it's being iterated over
1088  PyObject_SetAttr( iter, PyUnicode_FromString("_collection"), self );
1089  }
1090  return iter;
1091  }
1092 
1093 //- safe indexing for STL-like vector w/o iterator dictionaries ---------------
1094  PyObject* CheckedGetItem( PyObject* self, PyObject* obj )
1095  {
1096  // Implement a generic python __getitem__ for std::vector<>s that are missing
1097  // their std::vector<>::iterator dictionary. This is then used for iteration
1098  // by means of consecutive index.
1099  Bool_t inbounds = kFALSE;
1100  Py_ssize_t size = PySequence_Size( self );
1101  Py_ssize_t idx = PyInt_AsSsize_t( obj );
1102  if ( 0 <= idx && 0 <= size && idx < size )
1103  inbounds = kTRUE;
1104 
1105  if ( inbounds ) {
1106  return CallPyObjMethod( self, "_getitem__unchecked", obj );
1107  } else if ( PyErr_Occurred() ) {
1108  // argument conversion problem: let method itself resolve anew and report
1109  PyErr_Clear();
1110  return CallPyObjMethod( self, "_getitem__unchecked", obj );
1111  } else {
1112  PyErr_SetString( PyExc_IndexError, "index out of range" );
1113  }
1114 
1115  return 0;
1116  }
1117 
1118 //- pair as sequence to allow tuple unpacking ---------------------------------
1119  PyObject* PairUnpack( PyObject* self, PyObject* pyindex )
1120  {
1121  // For std::map<> iteration, unpack std::pair<>s into tuples for the loop.
1122  Long_t idx = PyLong_AsLong( pyindex );
1123  if ( idx == -1 && PyErr_Occurred() )
1124  return 0;
1125 
1126  if ( ! ObjectProxy_Check( self ) || ! ((ObjectProxy*)self)->GetObject() ) {
1127  PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
1128  return 0;
1129  }
1130 
1131  if ( (int)idx == 0 )
1132  return PyObject_GetAttr( self, PyStrings::gFirst );
1133  else if ( (int)idx == 1 )
1134  return PyObject_GetAttr( self, PyStrings::gSecond );
1135 
1136  // still here? Trigger stop iteration
1137  PyErr_SetString( PyExc_IndexError, "out of bounds" );
1138  return 0;
1139  }
1140 
1141 //- string behavior as primitives ----------------------------------------------
1142 #if PY_VERSION_HEX >= 0x03000000
1143 // TODO: this is wrong, b/c it doesn't order
1144 static int PyObject_Compare( PyObject* one, PyObject* other ) {
1145  return ! PyObject_RichCompareBool( one, other, Py_EQ );
1146 }
1147 #endif
1148  static inline PyObject* PyROOT_PyString_FromCppString( std::string* s ) {
1149  return PyROOT_PyUnicode_FromStringAndSize( s->c_str(), s->size() );
1150  }
1151 
1152  static inline PyObject* PyROOT_PyString_FromCppString( TString* s ) {
1153  return PyROOT_PyUnicode_FromStringAndSize( s->Data(), s->Length() );
1154  }
1155 
1156  static inline PyObject* PyROOT_PyString_FromCppString( TObjString* s ) {
1157  return PyROOT_PyUnicode_FromStringAndSize( s->GetString().Data(), s->GetString().Length() );
1158  }
1159 
1160 #define PYROOT_IMPLEMENT_STRING_PYTHONIZATION( type, name ) \
1161  inline PyObject* name##GetData( PyObject* self ) { \
1162  if ( PyROOT::ObjectProxy_Check( self ) ) { \
1163  type* obj = ((type*)((ObjectProxy*)self)->GetObject()); \
1164  if ( obj ) { \
1165  return PyROOT_PyString_FromCppString( obj ); \
1166  } else { \
1167  return ObjectProxy_Type.tp_str( self ); \
1168  } \
1169  } \
1170  PyErr_Format( PyExc_TypeError, "object mismatch (%s expected)", #type );\
1171  return 0; \
1172  } \
1173  \
1174  PyObject* name##StringRepr( PyObject* self ) \
1175  { \
1176  PyObject* data = name##GetData( self ); \
1177  if ( data ) { \
1178  PyObject* repr = PyROOT_PyUnicode_FromFormat( "\'%s\'", PyROOT_PyUnicode_AsString( data ) ); \
1179  Py_DECREF( data ); \
1180  return repr; \
1181  } \
1182  return 0; \
1183  } \
1184  \
1185  PyObject* name##StringIsEqual( PyObject* self, PyObject* obj ) \
1186  { \
1187  PyObject* data = name##GetData( self ); \
1188  if ( data ) { \
1189  PyObject* result = PyObject_RichCompare( data, obj, Py_EQ ); \
1190  Py_DECREF( data ); \
1191  return result; \
1192  } \
1193  return 0; \
1194  } \
1195  \
1196  PyObject* name##StringIsNotEqual( PyObject* self, PyObject* obj ) \
1197  { \
1198  PyObject* data = name##GetData( self ); \
1199  if ( data ) { \
1200  PyObject* result = PyObject_RichCompare( data, obj, Py_NE ); \
1201  Py_DECREF( data ); \
1202  return result; \
1203  } \
1204  return 0; \
1205  }
1206 
1207  // Only define StlStringCompare:
1208  // TStringCompare is unused and generates a warning;
1209 #define PYROOT_IMPLEMENT_STRING_PYTHONIZATION_CMP( type, name ) \
1210  PYROOT_IMPLEMENT_STRING_PYTHONIZATION( type, name ) \
1211  PyObject* name##StringCompare( PyObject* self, PyObject* obj ) \
1212  { \
1213  PyObject* data = name##GetData( self ); \
1214  int result = 0; \
1215  if ( data ) { \
1216  result = PyObject_Compare( data, obj ); \
1217  Py_DECREF( data ); \
1218  } \
1219  if ( PyErr_Occurred() ) \
1220  return 0; \
1221  return PyInt_FromLong( result ); \
1222  }
1223 
1224  PYROOT_IMPLEMENT_STRING_PYTHONIZATION_CMP( std::string, Stl )
1226 
1227 
1228 //- TObjString behavior --------------------------------------------------------
1230 
1231 ////////////////////////////////////////////////////////////////////////////////
1232 /// Implementation of python __len__ for TObjString.
1233 
1234  PyObject* TObjStringLength( PyObject* self )
1235  {
1236  PyObject* data = CallPyObjMethod( self, "GetName" );
1237  Py_ssize_t size = PySequence_Size( data );
1238  Py_DECREF( data );
1239  return PyInt_FromSsize_t( size );
1240  }
1241 
1242 
1243 //- TIter behavior -------------------------------------------------------------
1244  PyObject* TIterNext( PyObject* self )
1245  {
1246  // Implementation of python __next__ (iterator protocol) for TIter.
1247  PyObject* next = CallPyObjMethod( self, "Next" );
1248 
1249  if ( ! next )
1250  return 0;
1251 
1252  if ( ! PyObject_IsTrue( next ) ) {
1253  Py_DECREF( next );
1254  PyErr_SetString( PyExc_StopIteration, "" );
1255  return 0;
1256  }
1257 
1258  return next;
1259  }
1260 
1261 
1262 //- STL iterator behavior ------------------------------------------------------
1263  PyObject* StlIterNext( PyObject* self )
1264  {
1265  // Python iterator protocol __next__ for STL forward iterators.
1266  PyObject* next = 0;
1267  PyObject* last = PyObject_GetAttr( self, PyStrings::gEnd );
1268 
1269  if ( last != 0 ) {
1270  // handle special case of empty container (i.e. self is end)
1271  if ( PyObject_RichCompareBool( last, self, Py_EQ ) ) {
1272  PyErr_SetString( PyExc_StopIteration, "" );
1273  } else {
1274  PyObject* dummy = PyInt_FromLong( 1l );
1275  PyObject* iter = CallPyObjMethod( self, "__postinc__", dummy );
1276  Py_DECREF( dummy );
1277  if ( iter != 0 ) {
1278  if ( PyObject_RichCompareBool( last, iter, Py_EQ ) )
1279  PyErr_SetString( PyExc_StopIteration, "" );
1280  else
1281  next = CallPyObjMethod( iter, "__deref__" );
1282  } else {
1283  PyErr_SetString( PyExc_StopIteration, "" );
1284  }
1285  Py_XDECREF( iter );
1286  }
1287  } else {
1288  PyErr_SetString( PyExc_StopIteration, "" );
1289  }
1290 
1291  Py_XDECREF( last );
1292  return next;
1293  }
1294 
1295 ////////////////////////////////////////////////////////////////////////////////
1296 /// Called if operator== not available (e.g. if a global overload as under gcc).
1297 /// An exception is raised as the user should fix the dictionary.
1298 
1299  PyObject* StlIterIsEqual( PyObject* self, PyObject* other )
1300  {
1301  return PyErr_Format( PyExc_LookupError,
1302  "No operator==(const %s&, const %s&) available in the dictionary!",
1303  Utility::ClassName( self ).c_str(), Utility::ClassName( other ).c_str() );
1304  }
1305 
1306 ////////////////////////////////////////////////////////////////////////////////
1307 /// Called if operator!= not available (e.g. if a global overload as under gcc).
1308 /// An exception is raised as the user should fix the dictionary.
1309 
1310  PyObject* StlIterIsNotEqual( PyObject* self, PyObject* other )
1311  {
1312  return PyErr_Format( PyExc_LookupError,
1313  "No operator!=(const %s&, const %s&) available in the dictionary!",
1314  Utility::ClassName( self ).c_str(), Utility::ClassName( other ).c_str() );
1315  }
1316 
1317 
1318 //- TDirectory member templates ----------------------------------------------
1319  PyObject* TDirectoryGetObject( ObjectProxy* self, PyObject* args )
1320  {
1321  // Pythonization of TDirector::GetObject().
1322  PyObject* name = 0; ObjectProxy* ptr = 0;
1323  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!:TDirectory::GetObject" ),
1324  &PyROOT_PyUnicode_Type, &name, &ObjectProxy_Type, &ptr ) )
1325  return 0;
1326 
1327  TDirectory* dir =
1328  (TDirectory*)OP2TCLASS(self)->DynamicCast( TDirectory::Class(), self->GetObject() );
1329 
1330  if ( ! dir ) {
1331  PyErr_SetString( PyExc_TypeError,
1332  "TDirectory::GetObject must be called with a TDirectory instance as first argument" );
1333  return 0;
1334  }
1335 
1336  void* address = dir->GetObjectChecked( PyROOT_PyUnicode_AsString( name ), OP2TCLASS(ptr) );
1337  if ( address ) {
1338  ptr->Set( address );
1339 
1340  Py_INCREF( Py_None );
1341  return Py_None;
1342  }
1343 
1344  PyErr_Format( PyExc_LookupError, "no such object, \"%s\"", PyROOT_PyUnicode_AsString( name ) );
1345  return 0;
1346  }
1347 
1348 ////////////////////////////////////////////////////////////////////////////////
1349 /// Type-safe version of TDirectory::WriteObjectAny, which is a template for
1350 /// the same reason on the C++ side.
1351 
1352  PyObject* TDirectoryWriteObject( ObjectProxy* self, PyObject* args )
1353  {
1354  ObjectProxy *wrt = 0; PyObject *name = 0, *option = 0;
1355  Int_t bufsize = 0;
1356  if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!|O!i:TDirectory::WriteObject" ),
1357  &ObjectProxy_Type, &wrt, &PyROOT_PyUnicode_Type, &name,
1358  &PyROOT_PyUnicode_Type, &option, &bufsize ) )
1359  return 0;
1360 
1361  TDirectory* dir =
1362  (TDirectory*)OP2TCLASS(self)->DynamicCast( TDirectory::Class(), self->GetObject() );
1363 
1364  if ( ! dir ) {
1365  PyErr_SetString( PyExc_TypeError,
1366  "TDirectory::WriteObject must be called with a TDirectory instance as first argument" );
1367  return 0;
1368  }
1369 
1370  Int_t result = 0;
1371  if ( option != 0 ) {
1372  result = dir->WriteObjectAny( wrt->GetObject(), OP2TCLASS(wrt),
1373  PyROOT_PyUnicode_AsString( name ), PyROOT_PyUnicode_AsString( option ), bufsize );
1374  } else {
1375  result = dir->WriteObjectAny(
1376  wrt->GetObject(), OP2TCLASS(wrt), PyROOT_PyUnicode_AsString( name ) );
1377  }
1378 
1379  return PyInt_FromLong( (Long_t)result );
1380  }
1381 
1382 }
1383 
1384 
1385 namespace PyROOT { // workaround for Intel icc on Linux
1386 
1387 //- TTree behavior ------------------------------------------------------------
1389  {
1390  // allow access to branches/leaves as if they are data members
1391  const char* name1 = PyROOT_PyUnicode_AsString( pyname );
1392  if ( ! name1 )
1393  return 0;
1394 
1395  // get hold of actual tree
1396  TTree* tree =
1397  (TTree*)OP2TCLASS(self)->DynamicCast( TTree::Class(), self->GetObject() );
1398 
1399  if ( ! tree ) {
1400  PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-pointer" );
1401  return 0;
1402  }
1403 
1404  // deal with possible aliasing
1405  const char* name = tree->GetAlias( name1 );
1406  if ( ! name ) name = name1;
1407 
1408  // search for branch first (typical for objects)
1409  TBranch* branch = tree->GetBranch( name );
1410  if ( ! branch ) {
1411  // for benefit of naming of sub-branches, the actual name may have a trailing '.'
1412  branch = tree->GetBranch( (std::string( name ) + '.' ).c_str() );
1413  }
1414 
1415  if ( branch ) {
1416  // found a branched object, wrap its address for the object it represents
1417 
1418  // for partial return of a split object
1419  if ( branch->InheritsFrom(TBranchElement::Class()) ) {
1420  TBranchElement* be = (TBranchElement*)branch;
1421  if ( be->GetCurrentClass() && (be->GetCurrentClass() != be->GetTargetClass()) && (0 <= be->GetID()) ) {
1422  Long_t offset = ((TStreamerElement*)be->GetInfo()->GetElements()->At(be->GetID()))->GetOffset();
1423  return BindCppObjectNoCast( be->GetObject() + offset, Cppyy::GetScope( be->GetCurrentClass()->GetName() ) );
1424  }
1425  }
1426 
1427  // for return of a full object
1428  if ( branch->IsA() == TBranchElement::Class() || branch->IsA() == TBranchObject::Class() ) {
1429  TClass* klass = TClass::GetClass( branch->GetClassName() );
1430  if ( klass && branch->GetAddress() )
1431  return BindCppObjectNoCast( *(void**)branch->GetAddress(), Cppyy::GetScope( branch->GetClassName() ) );
1432 
1433  // try leaf, otherwise indicate failure by returning a typed null-object
1434  TObjArray* leaves = branch->GetListOfLeaves();
1435  if ( klass && ! tree->GetLeaf( name ) &&
1436  ! (leaves->GetSize() && ( leaves->First() == leaves->Last() ) ) )
1437  return BindCppObjectNoCast( NULL, Cppyy::GetScope( branch->GetClassName() ) );
1438  }
1439  }
1440 
1441  // if not, try leaf
1442  TLeaf* leaf = tree->GetLeaf( name );
1443  if ( branch && ! leaf ) {
1444  leaf = branch->GetLeaf( name );
1445  if ( ! leaf ) {
1446  TObjArray* leaves = branch->GetListOfLeaves();
1447  if ( leaves->GetSize() && ( leaves->First() == leaves->Last() ) ) {
1448  // i.e., if unambiguously only this one
1449  leaf = (TLeaf*)leaves->At( 0 );
1450  }
1451  }
1452  }
1453 
1454  if ( leaf ) {
1455  // found a leaf, extract value and wrap
1456  if ( 1 < leaf->GetLenStatic() || leaf->GetLeafCount() ) {
1457  // array types
1458  std::string typeName = leaf->GetTypeName();
1459  TConverter* pcnv = CreateConverter( typeName + '*', leaf->GetNdata() );
1460 
1461  void* address = 0;
1462  if ( leaf->GetBranch() ) address = (void*)leaf->GetBranch()->GetAddress();
1463  if ( ! address ) address = (void*)leaf->GetValuePointer();
1464 
1465  PyObject* value = pcnv->FromMemory( &address );
1466  delete pcnv;
1467 
1468  return value;
1469  } else if ( leaf->GetValuePointer() ) {
1470  // value types
1471  TConverter* pcnv = CreateConverter( leaf->GetTypeName() );
1472  PyObject* value = 0;
1473  if ( leaf->IsA() == TLeafElement::Class() || leaf->IsA() == TLeafObject::Class() )
1474  value = pcnv->FromMemory( (void*)*(void**)leaf->GetValuePointer() );
1475  else
1476  value = pcnv->FromMemory( (void*)leaf->GetValuePointer() );
1477  delete pcnv;
1478 
1479  return value;
1480  }
1481  }
1482 
1483  // confused
1484  PyErr_Format( PyExc_AttributeError,
1485  "\'%s\' object has no attribute \'%s\'", tree->IsA()->GetName(), name );
1486  return 0;
1487  }
1488 
1489 ////////////////////////////////////////////////////////////////////////////////
1490 
1491  class TTreeMemberFunction : public PyCallable {
1492  protected:
1493  TTreeMemberFunction( MethodProxy* org ) { Py_INCREF( org ); fOrg = org; }
1494  TTreeMemberFunction( const TTreeMemberFunction& t ) : PyCallable( t )
1495  {
1496  // Copy constructor; conform to python reference counting.
1497  Py_INCREF( t.fOrg );
1498  fOrg = t.fOrg;
1499  }
1500  TTreeMemberFunction& operator=( const TTreeMemberFunction& t )
1501  {
1502  // Assignment operator; conform to python reference counting.
1503  if ( &t != this ) {
1504  Py_INCREF( t.fOrg );
1505  Py_XDECREF( fOrg );
1506  fOrg = t.fOrg;
1507  }
1508  return *this;
1509  }
1510  ~TTreeMemberFunction() { Py_DECREF( fOrg ); fOrg = 0; }
1511 
1512  public:
1513  virtual PyObject* GetSignature() { return PyROOT_PyUnicode_FromString( "(...)" ); }
1514  virtual PyObject* GetPrototype() { return PyObject_GetAttrString( (PyObject*)fOrg, (char*)"__doc__" ); }
1515  virtual Int_t GetPriority() { return 100; }
1516  virtual PyObject* GetCoVarNames() {
1517  PyObject* co_varnames = PyTuple_New( 1 /* self */ + 1 /* fake */ );
1518  PyTuple_SET_ITEM( co_varnames, 0, PyROOT_PyUnicode_FromString( "self" ) );
1519  PyTuple_SET_ITEM( co_varnames, 1, PyROOT_PyUnicode_FromString( "*args" ) );
1520  return co_varnames;
1521  }
1522  virtual PyObject* GetArgDefault( Int_t ) { return NULL; }
1523  virtual PyObject* GetScopeProxy() { return CreateScopeProxy( "TTree" ); }
1524 
1525  protected:
1526  MethodProxy* fOrg;
1527  };
1528 
1529 ////////////////////////////////////////////////////////////////////////////////
1530 
1531  class TTreeBranch : public TTreeMemberFunction {
1532  public:
1533  TTreeBranch( MethodProxy* org ) : TTreeMemberFunction( org ) {}
1534 
1535  public:
1536  virtual Int_t GetMaxArgs() { return 5; }
1537  virtual PyCallable* Clone() { return new TTreeBranch( *this ); }
1538 
1539  virtual PyObject* Call(
1540  ObjectProxy*& self, PyObject* args, PyObject* kwds, TCallContext* /* ctxt */ )
1541  {
1542  // acceptable signatures:
1543  // ( const char*, void*, const char*, Int_t = 32000 )
1544  // ( const char*, const char*, T**, Int_t = 32000, Int_t = 99 )
1545  // ( const char*, T**, Int_t = 32000, Int_t = 99 )
1546  int argc = PyTuple_GET_SIZE( args );
1547 
1548  if ( 2 <= argc ) {
1549  TTree* tree =
1550  (TTree*)OP2TCLASS(self)->DynamicCast( TTree::Class(), self->GetObject() );
1551 
1552  if ( ! tree ) {
1553  PyErr_SetString( PyExc_TypeError,
1554  "TTree::Branch must be called with a TTree instance as first argument" );
1555  return 0;
1556  }
1557 
1558  PyObject *name = 0, *clName = 0, *leaflist = 0;
1559  PyObject *address = 0;
1560  PyObject *bufsize = 0, *splitlevel = 0;
1561 
1562  // try: ( const char*, void*, const char*, Int_t = 32000 )
1563  if ( PyArg_ParseTuple( args, const_cast< char* >( "O!OO!|O!:Branch" ),
1564  &PyROOT_PyUnicode_Type, &name, &address, &PyROOT_PyUnicode_Type,
1565  &leaflist, &PyInt_Type, &bufsize ) ) {
1566 
1567  void* buf = 0;
1568  if ( ObjectProxy_Check( address ) )
1569  buf = (void*)((ObjectProxy*)address)->GetObject();
1570  else
1571  Utility::GetBuffer( address, '*', 1, buf, kFALSE );
1572 
1573  if ( buf != 0 ) {
1574  TBranch* branch = 0;
1575  if ( argc == 4 ) {
1576  branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), buf,
1577  PyROOT_PyUnicode_AsString( leaflist ), PyInt_AS_LONG( bufsize ) );
1578  } else {
1579  branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), buf,
1580  PyROOT_PyUnicode_AsString( leaflist ) );
1581  }
1582 
1583  return BindCppObject( branch, "TBranch" );
1584  }
1585 
1586  }
1587  PyErr_Clear();
1588 
1589  // try: ( const char*, const char*, T**, Int_t = 32000, Int_t = 99 )
1590  // or: ( const char*, T**, Int_t = 32000, Int_t = 99 )
1591  Bool_t bIsMatch = kFALSE;
1592  if ( PyArg_ParseTuple( args, const_cast< char* >( "O!O!O|O!O!:Branch" ),
1593  &PyROOT_PyUnicode_Type, &name, &PyROOT_PyUnicode_Type, &clName, &address,
1594  &PyInt_Type, &bufsize, &PyInt_Type, &splitlevel ) ) {
1595  bIsMatch = kTRUE;
1596  } else {
1597  PyErr_Clear(); clName = 0; // clName no longer used
1598  if ( PyArg_ParseTuple( args, const_cast< char* >( "O!O|O!O!" ),
1599  &PyROOT_PyUnicode_Type, &name, &address,
1600  &PyInt_Type, &bufsize, &PyInt_Type, &splitlevel ) ) {
1601  bIsMatch = kTRUE;
1602  } else
1603  PyErr_Clear();
1604  }
1605 
1606  if ( bIsMatch == kTRUE ) {
1607  std::string klName = clName ? PyROOT_PyUnicode_AsString( clName ) : "";
1608  void* buf = 0;
1609 
1610  if ( ObjectProxy_Check( address ) ) {
1611  if ( ((ObjectProxy*)address)->fFlags & ObjectProxy::kIsReference )
1612  buf = (void*)((ObjectProxy*)address)->fObject;
1613  else
1614  buf = (void*)&((ObjectProxy*)address)->fObject;
1615 
1616  if ( ! clName ) {
1617  klName = OP2TCLASS((ObjectProxy*)address)->GetName();
1618  argc += 1;
1619  }
1620  } else
1621  Utility::GetBuffer( address, '*', 1, buf, kFALSE );
1622 
1623  if ( buf != 0 && klName != "" ) {
1624  TBranch* branch = 0;
1625  if ( argc == 3 ) {
1626  branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), klName.c_str(), buf );
1627  } else if ( argc == 4 ) {
1628  branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), klName.c_str(), buf,
1629  PyInt_AS_LONG( bufsize ) );
1630  } else if ( argc == 5 ) {
1631  branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), klName.c_str(), buf,
1632  PyInt_AS_LONG( bufsize ), PyInt_AS_LONG( splitlevel ) );
1633  }
1634 
1635  return BindCppObject( branch, "TBranch" );
1636  }
1637  }
1638  }
1639 
1640  // still here? Then call original Branch() to reach the other overloads:
1641  Py_INCREF( (PyObject*)self );
1642  fOrg->fSelf = self;
1643  PyObject* result = PyObject_Call( (PyObject*)fOrg, args, kwds );
1644  fOrg->fSelf = 0;
1645  Py_DECREF( (PyObject*)self );
1646 
1647  return result;
1648  }
1649  };
1650 
1651 ////////////////////////////////////////////////////////////////////////////////
1652 
1653  class TTreeSetBranchAddress : public TTreeMemberFunction {
1654  public:
1655  TTreeSetBranchAddress( MethodProxy* org ) : TTreeMemberFunction( org ) {}
1656 
1657  public:
1658  virtual PyObject* GetPrototype()
1659  {
1660  return PyROOT_PyUnicode_FromString( "TBranch* TTree::SetBranchAddress( ... )" );
1661  }
1662 
1663  virtual Int_t GetMaxArgs() { return 2; }
1664  virtual PyCallable* Clone() { return new TTreeSetBranchAddress( *this ); }
1665 
1666  virtual PyObject* Call(
1667  ObjectProxy*& self, PyObject* args, PyObject* kwds, TCallContext* /* ctxt */ )
1668  {
1669  // acceptable signature:
1670  // ( const char*, void* )
1671  int argc = PyTuple_GET_SIZE( args );
1672 
1673  if ( 2 == argc ) {
1674  TTree* tree =
1675  (TTree*)OP2TCLASS(self)->DynamicCast( TTree::Class(), self->GetObject() );
1676 
1677  if ( ! tree ) {
1678  PyErr_SetString( PyExc_TypeError,
1679  "TTree::SetBranchAddress must be called with a TTree instance as first argument" );
1680  return 0;
1681  }
1682 
1683  PyObject *name = 0, *address = 0;
1684 
1685  // try: ( const char*, void* )
1686  if ( PyArg_ParseTuple( args, const_cast< char* >( "SO:SetBranchAddress" ),
1687  &name, &address ) ) {
1688 
1689  void* buf = 0;
1690  if ( ObjectProxy_Check( address ) ) {
1691  if ( ((ObjectProxy*)address)->fFlags & ObjectProxy::kIsReference )
1692  buf = (void*)((ObjectProxy*)address)->fObject;
1693  else
1694  buf = (void*)&((ObjectProxy*)address)->fObject;
1695  } else
1696  Utility::GetBuffer( address, '*', 1, buf, kFALSE );
1697 
1698  if ( buf != 0 ) {
1699  tree->SetBranchAddress( PyROOT_PyUnicode_AsString( name ), buf );
1700 
1701  Py_INCREF( Py_None );
1702  return Py_None;
1703  }
1704  }
1705  }
1706 
1707  // still here? Then call original Branch() to reach the other overloads:
1708  Py_INCREF( (PyObject*)self );
1709  fOrg->fSelf = self;
1710  PyObject* result = PyObject_Call( (PyObject*)fOrg, args, kwds );
1711  fOrg->fSelf = 0;
1712  Py_DECREF( (PyObject*)self );
1713 
1714  return result;
1715  }
1716 
1717  protected:
1718  virtual PyObject* ReportTypeError()
1719  {
1720  PyErr_SetString( PyExc_TypeError,
1721  "TTree::SetBranchAddress must be called with a TTree instance as first argument" );
1722  return 0;
1723  }
1724  };
1725 
1726 
1727 // TChain overrides TTree's SetBranchAddress, so set it again (the python method only forwards
1728 // onto a TTree*, so the C++ virtual function call will make sure the right method is used)
1729  class TChainSetBranchAddress : public TTreeSetBranchAddress {
1730  public:
1731  TChainSetBranchAddress( MethodProxy* org ) : TTreeSetBranchAddress( org ) {}
1732 
1733  public:
1734  virtual PyObject* GetPrototype()
1735  {
1736  return PyROOT_PyUnicode_FromString( "TBranch* TChain::SetBranchAddress( ... )" );
1737  }
1738 
1739  virtual Int_t GetMaxArgs() { return 2; }
1740  virtual PyCallable* Clone() { return new TChainSetBranchAddress( *this ); }
1741 
1742  protected:
1743  virtual PyObject* ReportTypeError()
1744  {
1745  PyErr_SetString( PyExc_TypeError,
1746  "TChain::SetBranchAddress must be called with a TChain instance as first argument" );
1747  return 0;
1748  }
1749  };
1750 
1751 //- TMinuit behavior ----------------------------------------------------------
1752  void TMinuitPyCallback( void* vpyfunc, Long_t /* npar */,
1753  Int_t& a0, Double_t* a1, Double_t& a2, Double_t* a3, Int_t a4 ) {
1754  // a void* was passed to keep the interface on builtin types only
1755  PyObject* pyfunc = (PyObject*)vpyfunc;
1756 
1757  // prepare arguments
1758  PyObject* pya0 = BufFac_t::Instance()->PyBuffer_FromMemory( &a0, sizeof(Int_t) );
1759  PyObject* pya1 = BufFac_t::Instance()->PyBuffer_FromMemory( a1, a0 * sizeof(Double_t) );
1760  PyObject* pya2 = BufFac_t::Instance()->PyBuffer_FromMemory( &a2, sizeof(Double_t) );
1761  PyObject* pya3 = BufFac_t::Instance()->PyBuffer_FromMemory( a3, -1 ); // size unknown
1762 
1763  if ( ! (pya0 && pya1 && pya2 && pya3) ) {
1764  Py_XDECREF( pya3 ); Py_XDECREF( pya2 ); Py_XDECREF( pya1 ); Py_XDECREF( pya0 );
1765  return;
1766  }
1767 
1768  // perform actual call
1769  PyObject* result = PyObject_CallFunction(
1770  pyfunc, (char*)"OOOOi", pya0, pya1, pya2, pya3, a4 );
1771  Py_DECREF( pya3 ); Py_DECREF( pya2 ); Py_DECREF( pya1 ); Py_DECREF( pya0 );
1772 
1773  if ( ! result ) {
1774  PyErr_Print();
1775  throw std::runtime_error( "TMinuit python fit function call failed" );
1776  }
1777 
1778  Py_XDECREF( result );
1779  }
1780 
1781 //- TFN behavior --------------------------------------------------------------
1782  double TFNPyCallback( void* vpyfunc, Long_t npar, double* a0, double* a1 ) {
1783  // a void* was passed to keep the interface on builtin types only
1784  PyObject* pyfunc = (PyObject*)vpyfunc;
1785 
1786  // prepare arguments and call
1787  PyObject* pya0 = BufFac_t::Instance()->PyBuffer_FromMemory( a0, 4 * sizeof(double) );
1788  if ( ! pya0 )
1789  return 0.;
1790 
1791  PyObject* result = 0;
1792  if ( npar != 0 ) {
1793  PyObject* pya1 = BufFac_t::Instance()->PyBuffer_FromMemory( a1, npar * sizeof(double) );
1794  result = PyObject_CallFunction( pyfunc, (char*)"OO", pya0, pya1 );
1795  Py_DECREF( pya1 );
1796  } else
1797  result = PyObject_CallFunction( pyfunc, (char*)"O", pya0 );
1798 
1799  Py_DECREF( pya0 );
1800 
1801  // translate result, throw if an error has occurred
1802  double d = 0.;
1803  if ( ! result ) {
1804  PyErr_Print();
1805  throw std::runtime_error( "TFN python function call failed" );
1806  } else {
1807  d = PyFloat_AsDouble( result );
1808  Py_DECREF( result );
1809  }
1810 
1811  return d;
1812  }
1813 
1814 } // namespace PyROOT
1815 
1816 
1817 namespace {
1818 
1819 // for convenience
1820  using namespace PyROOT;
1821 
1822 //- THN behavior --------------------------------------------------------------
1823  PyObject* THNIMul( PyObject* self, PyObject* scale )
1824  {
1825  // Use THN::Scale to perform *= ... need this stub to return self.
1826  PyObject* result = CallPyObjMethod( self, "Scale", scale );
1827  if ( ! result )
1828  return result;
1829 
1830  Py_DECREF( result );
1831  Py_INCREF( self );
1832  return self;
1833  }
1834 
1835 
1836 ////////////////////////////////////////////////////////////////////////////////
1837 
1838  class TPretendInterpreted: public PyCallable {
1839  public:
1840  TPretendInterpreted( int nArgs ) : fNArgs( nArgs ) {}
1841 
1842  public:
1843  Int_t GetNArgs() { return fNArgs; }
1844  virtual Int_t GetPriority() { return 100; }
1845  virtual Int_t GetMaxArgs() { return GetNArgs()+1; }
1846  virtual PyObject* GetCoVarNames() {
1847  PyObject* co_varnames = PyTuple_New( 1 /* self */ + 1 /* fake */ );
1848  PyTuple_SET_ITEM( co_varnames, 0, PyROOT_PyUnicode_FromString( "self" ) );
1849  PyTuple_SET_ITEM( co_varnames, 1, PyROOT_PyUnicode_FromString( "*args" ) );
1850  return co_varnames;
1851  }
1852  virtual PyObject* GetArgDefault( Int_t ) { return NULL; }
1853 
1854  Bool_t IsCallable( PyObject* pyobject )
1855  {
1856  // Determine whether the given pyobject is indeed callable.
1857  if ( ! pyobject || ! PyCallable_Check( pyobject ) ) {
1858  PyObject* str = pyobject ? PyObject_Str( pyobject ) : PyROOT_PyUnicode_FromString( "null pointer" );
1859  PyErr_Format( PyExc_ValueError,
1860  "\"%s\" is not a valid python callable", PyROOT_PyUnicode_AsString( str ) );
1861  Py_DECREF( str );
1862  return kFALSE;
1863  }
1864 
1865  return kTRUE;
1866  }
1867 
1868  private:
1869  Int_t fNArgs;
1870  };
1871 
1872 ////////////////////////////////////////////////////////////////////////////////
1873 
1874  class TF1InitWithPyFunc : public TPretendInterpreted {
1875  public:
1876  TF1InitWithPyFunc( int ntf = 1 ) : TPretendInterpreted( 2 + 2*ntf ) {}
1877 
1878  public:
1879  virtual PyObject* GetSignature() { return PyROOT_PyUnicode_FromString( "(...)" ); }
1880  virtual PyObject* GetPrototype()
1881  {
1883  "TF1::TF1(const char* name, PyObject* callable, "
1884  "Double_t xmin, Double_t xmax, Int_t npar = 0)" );
1885  }
1886  virtual PyObject* GetScopeProxy() { return CreateScopeProxy( "TF1" ); }
1887  virtual PyCallable* Clone() { return new TF1InitWithPyFunc( *this ); }
1888 
1889  virtual PyObject* Call(
1890  ObjectProxy*& self, PyObject* args, PyObject* /* kwds */, TCallContext* /* ctxt */ )
1891  {
1892  // expected signature: ( char* name, pyfunc, double xmin, double xmax, int npar = 0 )
1893  int argc = PyTuple_GET_SIZE( args );
1894  const int reqNArgs = GetNArgs();
1895  if ( ! ( argc == reqNArgs || argc == reqNArgs+1 ) ) {
1896  PyErr_Format( PyExc_TypeError,
1897  "TFN::TFN(const char*, PyObject* callable, ...) =>\n"
1898  " takes at least %d and at most %d arguments (%d given)",
1899  reqNArgs, reqNArgs+1, argc );
1900  return 0; // reported as an overload failure
1901  }
1902 
1903  PyObject* pyfunc = PyTuple_GET_ITEM( args, 1 );
1904 
1905  // verify/setup the callback parameters
1906  Long_t npar = 0; // default value if not given
1907  if ( argc == reqNArgs+1 )
1908  npar = PyInt_AsLong( PyTuple_GET_ITEM( args, reqNArgs ) );
1909 
1910  // create signature
1911  std::vector<std::string> signature; signature.reserve( 2 );
1912  signature.push_back( "double*" );
1913  signature.push_back( "double*" );
1914 
1915  // registration with Cling
1916  void* fptr = Utility::CreateWrapperMethod(
1917  pyfunc, npar, "double", signature, "TFNPyCallback" );
1918  if ( ! fptr /* PyErr was set */ )
1919  return 0;
1920 
1921  // get constructor
1922  MethodProxy* method =
1923  (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gInit );
1924 
1925  // build new argument array
1926  PyObject* newArgs = PyTuple_New( reqNArgs + 1 );
1927 
1928  for ( int iarg = 0; iarg < argc; ++iarg ) {
1929  PyObject* item = PyTuple_GET_ITEM( args, iarg );
1930  if ( iarg != 1 ) {
1931  Py_INCREF( item );
1932  PyTuple_SET_ITEM( newArgs, iarg, item );
1933  } else {
1934  PyTuple_SET_ITEM( newArgs, iarg, PyROOT_PyCapsule_New( fptr, NULL, NULL ) );
1935  }
1936  }
1937 
1938  if ( argc == reqNArgs ) // meaning: use default for last value
1939  PyTuple_SET_ITEM( newArgs, reqNArgs, PyInt_FromLong( 0l ) );
1940 
1941  // re-run constructor, will select the proper one with void* for callback
1942  PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
1943 
1944  // done, may have worked, if not: 0 is returned
1945  Py_DECREF( newArgs );
1946  Py_DECREF( method );
1947  return result;
1948  }
1949  };
1950 
1951 ////////////////////////////////////////////////////////////////////////////////
1952 
1953  class TF2InitWithPyFunc : public TF1InitWithPyFunc {
1954  public:
1955  TF2InitWithPyFunc() : TF1InitWithPyFunc( 2 ) {}
1956 
1957  public:
1958  virtual PyObject* GetPrototype()
1959  {
1961  "TF2::TF2(const char* name, PyObject* callable, "
1962  "Double_t xmin, Double_t xmax, "
1963  "Double_t ymin, Double_t ymax, Int_t npar = 0)" );
1964  }
1965  virtual PyObject* GetScopeProxy() { return CreateScopeProxy( "TF2" ); }
1966  virtual PyCallable* Clone() { return new TF2InitWithPyFunc( *this ); }
1967  };
1968 
1969 ////////////////////////////////////////////////////////////////////////////////
1970 
1971  class TF3InitWithPyFunc : public TF1InitWithPyFunc {
1972  public:
1973  TF3InitWithPyFunc() : TF1InitWithPyFunc( 3 ) {}
1974 
1975  public:
1976  virtual PyObject* GetPrototype()
1977  {
1979  "TF3::TF3(const char* name, PyObject* callable, "
1980  "Double_t xmin, Double_t xmax, "
1981  "Double_t ymin, Double_t ymax, "
1982  "Double_t zmin, Double_t zmax, Int_t npar = 0)" );
1983  }
1984  virtual PyObject* GetScopeProxy() { return CreateScopeProxy( "TF3" ); }
1985  virtual PyCallable* Clone() { return new TF3InitWithPyFunc( *this ); }
1986  };
1987 
1988 //- TFunction behavior ---------------------------------------------------------
1989  PyObject* TFunctionCall( ObjectProxy*& self, PyObject* args ) {
1990  return TFunctionHolder( Cppyy::gGlobalScope, (Cppyy::TCppMethod_t)self->GetObject() ).Call( self, args, 0 );
1991  }
1992 
1993 
1994 //- TMinuit behavior -----------------------------------------------------------
1995  class TMinuitSetFCN : public TPretendInterpreted {
1996  public:
1997  TMinuitSetFCN( int nArgs = 1 ) : TPretendInterpreted( nArgs ) {}
1998 
1999  public:
2000  virtual PyObject* GetSignature() { return PyROOT_PyUnicode_FromString( "(PyObject* callable)" ); }
2001  virtual PyObject* GetPrototype()
2002  {
2004  "TMinuit::SetFCN(PyObject* callable)" );
2005  }
2006  virtual PyObject* GetScopeProxy() { return CreateScopeProxy( "TMinuit" ); }
2007  virtual PyCallable* Clone() { return new TMinuitSetFCN( *this ); }
2008 
2009  virtual PyObject* Call(
2010  ObjectProxy*& self, PyObject* args, PyObject* kwds, TCallContext* ctxt )
2011  {
2012  // expected signature: ( pyfunc )
2013  int argc = PyTuple_GET_SIZE( args );
2014  if ( argc != 1 ) {
2015  PyErr_Format( PyExc_TypeError,
2016  "TMinuit::SetFCN(PyObject* callable, ...) =>\n"
2017  " takes exactly 1 argument (%d given)", argc );
2018  return 0; // reported as an overload failure
2019  }
2020 
2021  PyObject* pyfunc = PyTuple_GET_ITEM( args, 0 );
2022  if ( ! IsCallable( pyfunc ) )
2023  return 0;
2024 
2025  // create signature
2026  std::vector<std::string> signature; signature.reserve( 5 );
2027  signature.push_back( "Int_t&" );
2028  signature.push_back( "Double_t*" );
2029  signature.push_back( "Double_t&" );
2030  signature.push_back( "Double_t*" );
2031  signature.push_back( "Int_t" );
2032 
2033  // registration with Cling
2034  void* fptr = Utility::CreateWrapperMethod(
2035  pyfunc, 5, "void", signature, "TMinuitPyCallback" );
2036  if ( ! fptr /* PyErr was set */ )
2037  return 0;
2038 
2039  // get setter function
2040  MethodProxy* method =
2041  (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gSetFCN );
2042 
2043  // CLING WORKAROUND: SetFCN(void* fun) is deprecated but for whatever reason
2044  // still available yet not functional; select the correct one based on its
2045  // signature of the full function pointer
2046  PyCallable* setFCN = 0;
2047  const MethodProxy::Methods_t& methods = method->fMethodInfo->fMethods;
2048  for ( MethodProxy::Methods_t::const_iterator im = methods.begin(); im != methods.end(); ++im ) {
2049  PyObject* sig = (*im)->GetSignature();
2050  if ( sig && strstr( PyROOT_PyUnicode_AsString( sig ), "Double_t&" ) ) {
2051  // the comparison was not exact, but this is just a workaround
2052  setFCN = *im;
2053  Py_DECREF( sig );
2054  break;
2055  }
2056  Py_DECREF( sig );
2057  }
2058  if ( ! setFCN ) // this never happens but Coverity insists; it can be
2059  return 0; // removed with the workaround in due time
2060  // END CLING WORKAROUND
2061 
2062  // build new argument array
2063  PyObject* newArgs = PyTuple_New( 1 );
2064  PyTuple_SET_ITEM( newArgs, 0, PyROOT_PyCapsule_New( fptr, NULL, NULL ) );
2065 
2066  // re-run
2067  // CLING WORKAROUND: this is to be the call once TMinuit is fixed:
2068  // PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
2069  PyObject* result = setFCN->Call( self, newArgs, kwds, ctxt );
2070  // END CLING WORKAROUND
2071 
2072  // done, may have worked, if not: 0 is returned
2073  Py_DECREF( newArgs );
2074  Py_DECREF( method );
2075  return result;
2076  }
2077  };
2078 
2079  class TMinuitFitterSetFCN : public TMinuitSetFCN {
2080  public:
2081  TMinuitFitterSetFCN() : TMinuitSetFCN( 1 ) {}
2082 
2083  public:
2084  virtual PyObject* GetPrototype()
2085  {
2087  "TMinuitFitter::SetFCN(PyObject* callable)" );
2088  }
2089 
2090  virtual PyCallable* Clone() { return new TMinuitFitterSetFCN( *this ); }
2091 
2092  virtual PyObject* Call(
2093  ObjectProxy*& self, PyObject* args, PyObject* kwds, TCallContext* ctxt )
2094  {
2095  // expected signature: ( pyfunc )
2096  int argc = PyTuple_GET_SIZE( args );
2097  if ( argc != 1 ) {
2098  PyErr_Format( PyExc_TypeError,
2099  "TMinuitFitter::SetFCN(PyObject* callable, ...) =>\n"
2100  " takes exactly 1 argument (%d given)", argc );
2101  return 0; // reported as an overload failure
2102  }
2103 
2104  return TMinuitSetFCN::Call( self, args, kwds, ctxt );
2105  }
2106  };
2107 
2108 //- Fit::TFitter behavior ------------------------------------------------------
2109  PyObject* gFitterPyCallback = 0;
2110 
2111  void FitterPyCallback( int& npar, double* gin, double& f, double* u, int flag )
2112  {
2113  // Cling-callable callback for Fit::Fitter derived objects.
2114  PyObject* result = 0;
2115 
2116  // prepare arguments
2117  PyObject* arg1 = BufFac_t::Instance()->PyBuffer_FromMemory( &npar );
2118 
2120 
2121  PyObject* arg3 = PyList_New( 1 );
2122  PyList_SetItem( arg3, 0, PyFloat_FromDouble( f ) );
2123 
2124  PyObject* arg4 = BufFac_t::Instance()->PyBuffer_FromMemory( u, npar * sizeof(double) );
2125 
2126  // perform actual call
2127  result = PyObject_CallFunction(
2128  gFitterPyCallback, (char*)"OOOOi", arg1, arg2, arg3, arg4, flag );
2129  f = PyFloat_AsDouble( PyList_GetItem( arg3, 0 ) );
2130 
2131  Py_DECREF( arg4 ); Py_DECREF( arg3 ); Py_DECREF( arg2 ); Py_DECREF( arg1 );
2132 
2133  if ( ! result ) {
2134  PyErr_Print();
2135  throw std::runtime_error( "TMinuit python fit function call failed" );
2136  }
2137 
2138  Py_XDECREF( result );
2139  }
2140 
2141  class TFitterFitFCN : public TPretendInterpreted {
2142  public:
2143  TFitterFitFCN() : TPretendInterpreted( 2 ) {}
2144 
2145  public:
2146  virtual PyObject* GetSignature()
2147  {
2149  "(PyObject* callable, int npar = 0, const double* params = 0, unsigned int dataSize = 0, bool chi2fit = false)" );
2150  }
2151  virtual PyObject* GetPrototype()
2152  {
2154  "TFitter::FitFCN(PyObject* callable, int npar = 0, const double* params = 0, unsigned int dataSize = 0, bool chi2fit = false)" );
2155  }
2156  virtual PyObject* GetScopeProxy() { return CreateScopeProxy( "TFitter" ); }
2157  virtual PyCallable* Clone() { return new TFitterFitFCN( *this ); }
2158 
2159  virtual PyObject* Call(
2160  ObjectProxy*& self, PyObject* args, PyObject* /* kwds */, TCallContext* /* ctxt */ )
2161  {
2162  // expected signature: ( self, pyfunc, int npar = 0, const double* params = 0, unsigned int dataSize = 0, bool chi2fit = false )
2163  int argc = PyTuple_GET_SIZE( args );
2164  if ( argc < 1 ) {
2165  PyErr_Format( PyExc_TypeError,
2166  "TFitter::FitFCN(PyObject* callable, ...) =>\n"
2167  " takes at least 1 argument (%d given)", argc );
2168  return 0; // reported as an overload failure
2169  }
2170 
2171  PyObject* pyfunc = PyTuple_GET_ITEM( args, 0 );
2172  if ( ! IsCallable( pyfunc ) )
2173  return 0;
2174 
2175  // global registration
2176  Py_XDECREF( gFitterPyCallback );
2177  Py_INCREF( pyfunc );
2178  gFitterPyCallback = pyfunc;
2179 
2180  // get function
2181  MethodProxy* method =
2182  (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gFitFCN );
2183 
2184  // build new argument array
2185  PyObject* newArgs = PyTuple_New( argc );
2186  PyTuple_SET_ITEM( newArgs, 0, PyROOT_PyCapsule_New( (void*)FitterPyCallback, NULL, NULL ) );
2187  for ( int iarg = 1; iarg < argc; ++iarg ) {
2188  PyObject* pyarg = PyTuple_GET_ITEM( args, iarg );
2189  Py_INCREF( pyarg );
2190  PyTuple_SET_ITEM( newArgs, iarg, pyarg );
2191  }
2192 
2193  // re-run
2194  PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
2195 
2196  // done, may have worked, if not: 0 is returned
2197  Py_DECREF( newArgs );
2198  Py_DECREF( method );
2199  return result;
2200  }
2201  };
2202 
2203 
2204 //- TFile::Get -----------------------------------------------------------------
2205  PyObject* TFileGetAttr( PyObject* self, PyObject* attr )
2206  {
2207  // Pythonization of TFile::Get that raises AttributeError on failure.
2208  PyObject* result = CallPyObjMethod( self, "Get", attr );
2209  if ( !result )
2210  return result;
2211 
2212  if ( !PyObject_IsTrue( result ) ) {
2213  PyObject* astr = PyObject_Str( attr );
2214  PyErr_Format( PyExc_AttributeError, "TFile object has no attribute \'%s\'",
2215  PyROOT_PyUnicode_AsString( astr ) );
2216  Py_DECREF( astr );
2217  Py_DECREF( result );
2218  return nullptr;
2219  }
2220 
2221  // caching behavior seems to be more clear to the user; can always override said
2222  // behavior (i.e. re-read from file) with an explicit Get() call
2223  PyObject_SetAttr( self, attr, result );
2224  return result;
2225  }
2226 
2227 // This is done for TFile, but Get() is really defined in TDirectoryFile and its base
2228 // TDirectory suffers from a similar problem. Nevertheless, the TFile case is by far
2229 // the most common, so we'll leave it at this until someone asks for one of the bases
2230 // to be pythonized.
2231  PyObject* TDirectoryFileGet( ObjectProxy* self, PyObject* pynamecycle )
2232  {
2233  // Pythonization of TDirectoryFile::Get that handles non-TObject deriveds
2234  if ( ! ObjectProxy_Check( self ) ) {
2235  PyErr_SetString( PyExc_TypeError,
2236  "TDirectoryFile::Get must be called with a TDirectoryFile instance as first argument" );
2237  return nullptr;
2238  }
2239 
2240  TDirectoryFile* dirf =
2241  (TDirectoryFile*)OP2TCLASS(self)->DynamicCast( TDirectoryFile::Class(), self->GetObject() );
2242  if ( !dirf ) {
2243  PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-pointer" );
2244  return nullptr;
2245  }
2246 
2247  const char* namecycle = PyROOT_PyUnicode_AsString( pynamecycle );
2248  if ( !namecycle )
2249  return nullptr; // TypeError already set
2250 
2251  TKey* key = dirf->GetKey( namecycle );
2252  if ( key ) {
2253  void* addr = dirf->GetObjectChecked( namecycle, key->GetClassName() );
2254  return BindCppObjectNoCast( addr,
2256  }
2257 
2258  // no key? for better or worse, call normal Get()
2259  void* addr = dirf->Get( namecycle );
2260  return BindCppObject( addr, (Cppyy::TCppType_t)Cppyy::GetScope( "TObject" ), kFALSE );
2261  }
2262 
2263  //- Adding array interface to classes ---------------
2264  void AddArrayInterface(PyObject *pyclass, PyCFunction func)
2265  {
2266  Utility::AddToClass(pyclass, "_get__array_interface__", func, METH_NOARGS);
2267  }
2268 
2269  template <typename dtype>
2270  PyObject *FillArrayInterfaceDict(char type)
2271  {
2272  PyObject *dict = PyDict_New();
2273  PyDict_SetItemString(dict, "version", PyLong_FromLong(3));
2274 #ifdef R__BYTESWAP
2275  const char endianess = '<';
2276 #else
2277  const char endianess = '>';
2278 #endif
2279  const UInt_t bytes = sizeof(dtype);
2280  PyDict_SetItemString(dict, "typestr",
2281  PyROOT_PyUnicode_FromString(TString::Format("%c%c%i", endianess, type, bytes).Data()));
2282  return dict;
2283  }
2284 
2285  template <typename dtype, char typestr>
2286  PyObject *STLVectorArrayInterface(ObjectProxy *self)
2287  {
2288  std::vector<dtype> *cobj = (std::vector<dtype> *)(self->GetObject());
2289 
2290  PyObject *dict = FillArrayInterfaceDict<dtype>(typestr);
2291  PyDict_SetItemString(dict, "shape", PyTuple_Pack(1, PyLong_FromLong(cobj->size())));
2292  PyDict_SetItemString(dict, "data",
2293  PyTuple_Pack(2, PyLong_FromLong(reinterpret_cast<long>(cobj->data())), Py_False));
2294 
2295  return dict;
2296  }
2297 
2298  template <typename dtype, char typestr>
2299  PyObject *RVecArrayInterface(ObjectProxy *self)
2300  {
2301  using ROOT::VecOps::RVec;
2302  RVec<dtype> *cobj = (RVec<dtype> *)(self->GetObject());
2303 
2304  PyObject *dict = FillArrayInterfaceDict<dtype>(typestr);
2305  PyDict_SetItemString(dict, "shape", PyTuple_Pack(1, PyLong_FromLong(cobj->size())));
2306  PyDict_SetItemString(dict, "data",
2307  PyTuple_Pack(2, PyLong_FromLong(reinterpret_cast<long>(cobj->data())), Py_False));
2308 
2309  return dict;
2310  }
2311 
2312  //- simplistic len() functions -------------------------------------------------
2313  PyObject* ReturnThree( ObjectProxy*, PyObject* ) {
2314  return PyInt_FromLong( 3 );
2315  }
2316 
2317  PyObject* ReturnTwo( ObjectProxy*, PyObject* ) {
2318  return PyInt_FromLong( 2 );
2319  }
2320 
2321 } // unnamed namespace
2322 
2323 
2324 //- public functions -----------------------------------------------------------
2325 Bool_t PyROOT::Pythonize( PyObject* pyclass, const std::string& name )
2326 {
2327 // Add pre-defined pythonizations (for STL and ROOT) to classes based on their
2328 // signature and/or class name.
2329  if ( pyclass == 0 )
2330  return kFALSE;
2331 
2332 //- method name based pythonization --------------------------------------------
2333 
2334 // for smart pointer style classes (note fall-through)
2335  if ( HasAttrDirect( pyclass, PyStrings::gDeref ) ) {
2336  Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) DeRefGetAttr, METH_O );
2337  } else if ( HasAttrDirect( pyclass, PyStrings::gFollow ) ) {
2338  Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) FollowGetAttr, METH_O );
2339  }
2340 
2341 // for STL containers, and user classes modeled after them
2342  if ( HasAttrDirect( pyclass, PyStrings::gSize ) )
2343  Utility::AddToClass( pyclass, "__len__", "size" );
2344 
2345 // like-wise, some typical container sizings
2346  if ( HasAttrDirect( pyclass, PyStrings::gGetSize ) )
2347  Utility::AddToClass( pyclass, "__len__", "GetSize" );
2348 
2349  if ( HasAttrDirect( pyclass, PyStrings::ggetSize ) )
2350  Utility::AddToClass( pyclass, "__len__", "getSize" );
2351 
2352  if ( HasAttrDirect( pyclass, PyStrings::gBegin ) && HasAttrDirect( pyclass, PyStrings::gEnd ) ) {
2353  // some classes may not have dicts for their iterators, making begin/end useless
2354  PyObject* pyfullname = PyObject_GetAttr( pyclass, PyStrings::gCppName );
2355  if ( ! pyfullname ) pyfullname = PyObject_GetAttr( pyclass, PyStrings::gName );
2356  TClass* klass = TClass::GetClass( PyROOT_PyUnicode_AsString( pyfullname ) );
2357  Py_DECREF( pyfullname );
2358 
2359  if (!klass->InheritsFrom(TCollection::Class())) {
2360  // TCollection has a begin and end method so that they can be used in
2361  // the C++ range expression. However, unlike any other use of TIter,
2362  // TCollection::begin must include the first iteration. PyROOT is
2363  // handling TIter as a special case (as it should) and also does this
2364  // first iteration (via the first call to Next to get the first element)
2365  // and thus using begin in this case lead to the first element being
2366  // forgotten by PyROOT.
2367  // i.e. Don't search for begin in TCollection since we can not use.'
2368 
2369  TMethod* meth = klass->GetMethodAllAny( "begin" );
2370 
2371  TClass* iklass = 0;
2372  if ( meth ) {
2373  Int_t oldl = gErrorIgnoreLevel; gErrorIgnoreLevel = 3000;
2374  iklass = TClass::GetClass( meth->GetReturnTypeNormalizedName().c_str() );
2375  gErrorIgnoreLevel = oldl;
2376  }
2377 
2378  if ( iklass && iklass->GetClassInfo() ) {
2379  ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)StlSequenceIter;
2380  Utility::AddToClass( pyclass, "__iter__", (PyCFunction) StlSequenceIter, METH_NOARGS );
2381  } else if ( HasAttrDirect( pyclass, PyStrings::gGetItem ) && HasAttrDirect( pyclass, PyStrings::gLen ) ) {
2382  Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
2383  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
2384  }
2385  }
2386  }
2387 
2388 // search for global comparator overloads (may fail; not sure whether it isn't better to
2389 // do this lazily just as is done for math operators, but this interplays nicely with the
2390 // generic versions)
2391  Utility::AddBinaryOperator( pyclass, "==", "__eq__" );
2392  Utility::AddBinaryOperator( pyclass, "!=", "__ne__" );
2393 
2394 // map operator==() through GenObjectIsEqual to allow comparison to None (kTRUE is to
2395 // require that the located method is a MethodProxy; this prevents circular calls as
2396 // GenObjectIsEqual is no MethodProxy)
2397  if ( HasAttrDirect( pyclass, PyStrings::gEq, kTRUE ) ) {
2398  Utility::AddToClass( pyclass, "__cpp_eq__", "__eq__" );
2399  Utility::AddToClass( pyclass, "__eq__", (PyCFunction) GenObjectIsEqual, METH_O );
2400  }
2401 
2402 // map operator!=() through GenObjectIsNotEqual to allow comparison to None (see note
2403 // on kTRUE above for __eq__)
2404  if ( HasAttrDirect( pyclass, PyStrings::gNe, kTRUE ) ) {
2405  Utility::AddToClass( pyclass, "__cpp_ne__", "__ne__" );
2406  Utility::AddToClass( pyclass, "__ne__", (PyCFunction) GenObjectIsNotEqual, METH_O );
2407  }
2408 
2409 
2410 //- class name based pythonization ---------------------------------------------
2411 
2412  if ( name == "TObject" ) {
2413  // support for the 'in' operator
2414  Utility::AddToClass( pyclass, "__contains__", (PyCFunction) TObjectContains, METH_O );
2415 
2416  // comparing for lists
2417  Utility::AddToClass( pyclass, "__cmp__", (PyCFunction) TObjectCompare, METH_O );
2418  Utility::AddToClass( pyclass, "__eq__", (PyCFunction) TObjectIsEqual, METH_O );
2419  Utility::AddToClass( pyclass, "__ne__", (PyCFunction) TObjectIsNotEqual, METH_O );
2420 
2421  }
2422 
2423  else if ( name == "TClass" ) {
2424  // make DynamicCast return a usable python object, rather than void*
2425  Utility::AddToClass( pyclass, "_TClass__DynamicCast", "DynamicCast" );
2426  Utility::AddToClass( pyclass, "DynamicCast", (PyCFunction) TClassDynamicCast );
2427 
2428  // the following cast is easier to use (reads both ways)
2429  Utility::AddToClass( pyclass, "StaticCast", (PyCFunction) TClassStaticCast );
2430 
2431  }
2432 
2433  else if ( name == "TCollection" ) {
2434  Utility::AddToClass( pyclass, "append", "Add" );
2435  Utility::AddToClass( pyclass, "extend", (PyCFunction) TCollectionExtend, METH_O );
2436  Utility::AddToClass( pyclass, "remove", (PyCFunction) TCollectionRemove, METH_O );
2437  Utility::AddToClass( pyclass, "__add__", (PyCFunction) TCollectionAdd, METH_O );
2438  Utility::AddToClass( pyclass, "__imul__", (PyCFunction) TCollectionIMul, METH_O );
2439  Utility::AddToClass( pyclass, "__mul__", (PyCFunction) TCollectionMul, METH_O );
2440  Utility::AddToClass( pyclass, "__rmul__", (PyCFunction) TCollectionMul, METH_O );
2441 
2442  Utility::AddToClass( pyclass, "count", (PyCFunction) TCollectionCount, METH_O );
2443 
2444  ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)TCollectionIter;
2445  Utility::AddToClass( pyclass, "__iter__", (PyCFunction)TCollectionIter, METH_NOARGS );
2446 
2447  }
2448 
2449  else if ( name == "TSeqCollection" ) {
2450  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) TSeqCollectionGetItem, METH_O );
2451  Utility::AddToClass( pyclass, "__setitem__", (PyCFunction) TSeqCollectionSetItem );
2452  Utility::AddToClass( pyclass, "__delitem__", (PyCFunction) TSeqCollectionDelItem, METH_O );
2453 
2454  Utility::AddToClass( pyclass, "insert", (PyCFunction) TSeqCollectionInsert );
2455  Utility::AddToClass( pyclass, "pop", (PyCFunction) TSeqCollectionPop );
2456  Utility::AddToClass( pyclass, "reverse", (PyCFunction) TSeqCollectionReverse, METH_NOARGS );
2457  Utility::AddToClass( pyclass, "sort", (PyCFunction) TSeqCollectionSort,
2458  METH_VARARGS | METH_KEYWORDS );
2459 
2460  Utility::AddToClass( pyclass, "index", (PyCFunction) TSeqCollectionIndex, METH_O );
2461 
2462  }
2463 
2464  else if ( name == "TObjArray" ) {
2465  Utility::AddToClass( pyclass, "__len__", (PyCFunction) TObjArrayLen, METH_NOARGS );
2466  }
2467 
2468  else if ( name == "TClonesArray" ) {
2469  // restore base TSeqCollection operator[] to prevent random object creation (it's
2470  // functionality is equivalent to the operator[](int) const of TClonesArray, but
2471  // there's no guarantee it'll be selected over the non-const version)
2472  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) TSeqCollectionGetItem, METH_O );
2473 
2474  // this setitem should be used with as much care as the C++ one
2475  Utility::AddToClass( pyclass, "__setitem__", (PyCFunction) TClonesArraySetItem );
2476 
2477  }
2478 
2479  else if ( IsTemplatedSTLClass( name, "vector" ) ) {
2480 
2481  if ( HasAttrDirect( pyclass, PyStrings::gLen ) && HasAttrDirect( pyclass, PyStrings::gAt ) ) {
2482  Utility::AddToClass( pyclass, "_vector__at", "at" );
2483  // remove iterator that was set earlier (checked __getitem__ will do the trick)
2484  if ( HasAttrDirect( pyclass, PyStrings::gIter ) )
2485  PyObject_DelAttr( pyclass, PyStrings::gIter );
2486  } else if ( HasAttrDirect( pyclass, PyStrings::gGetItem ) ) {
2487  Utility::AddToClass( pyclass, "_vector__at", "__getitem__" ); // unchecked!
2488  }
2489 
2490  // vector-optimized iterator protocol
2491  ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)vector_iter;
2492 
2493  // helpers for iteration
2494  TypedefInfo_t* ti = gInterpreter->TypedefInfo_Factory( (name+"::value_type").c_str() );
2495  if ( gInterpreter->TypedefInfo_IsValid( ti ) ) {
2496  PyObject* pyvalue_size = PyLong_FromLong( gInterpreter->TypedefInfo_Size( ti ) );
2497  PyObject_SetAttrString( pyclass, "value_size", pyvalue_size );
2498  Py_DECREF( pyvalue_size );
2499 
2500  PyObject* pyvalue_type = PyROOT_PyUnicode_FromString( gInterpreter->TypedefInfo_TrueName( ti ) );
2501  PyObject_SetAttrString( pyclass, "value_type", pyvalue_type );
2502  Py_DECREF( pyvalue_type );
2503  }
2504  gInterpreter->TypedefInfo_Delete( ti );
2505 
2506  // provide a slice-able __getitem__, if possible
2507  if ( HasAttrDirect( pyclass, PyStrings::gVectorAt ) )
2508  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) VectorGetItem, METH_O );
2509 
2510  // std::vector<bool> is a special case in C++
2511  std::string::size_type pos = name.find( "vector<bool" ); // to cover all variations
2512  if ( pos == 0 /* at beginning */ || pos == 5 /* after std:: */ ) {
2513  Utility::AddToClass( pyclass, "__setitem__", (PyCFunction) VectorBoolSetItem );
2514  }
2515 
2516  // add array interface
2517  if (name.find("<float>") != std::string::npos) {
2518  AddArrayInterface(pyclass, (PyCFunction)STLVectorArrayInterface<float, 'f'>);
2519  } else if (name.find("<double>") != std::string::npos) {
2520  AddArrayInterface(pyclass, (PyCFunction)STLVectorArrayInterface<double, 'f'>);
2521  } else if (name.find("<int>") != std::string::npos) {
2522  AddArrayInterface(pyclass, (PyCFunction)STLVectorArrayInterface<int, 'i'>);
2523  } else if (name.find("<unsigned int>") != std::string::npos) {
2524  AddArrayInterface(pyclass, (PyCFunction)STLVectorArrayInterface<unsigned int, 'u'>);
2525  } else if (name.find("<long>") != std::string::npos) {
2526  AddArrayInterface(pyclass, (PyCFunction)STLVectorArrayInterface<long, 'i'>);
2527  } else if (name.find("<unsigned long>") != std::string::npos) {
2528  AddArrayInterface(pyclass, (PyCFunction)STLVectorArrayInterface<unsigned long, 'u'>);
2529  }
2530 
2531  }
2532 
2533  else if ( IsTemplatedSTLClass( name, "map" ) ) {
2534  Utility::AddToClass( pyclass, "__contains__", (PyCFunction) MapContains, METH_O );
2535 
2536  }
2537 
2538  else if ( IsTemplatedSTLClass( name, "pair" ) ) {
2539  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) PairUnpack, METH_O );
2540  Utility::AddToClass( pyclass, "__len__", (PyCFunction) ReturnTwo, METH_NOARGS );
2541 
2542  }
2543 
2544  else if ( name.find( "iterator" ) != std::string::npos ) {
2545  ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)StlIterNext;
2546  Utility::AddToClass( pyclass, PYROOT__next__, (PyCFunction) StlIterNext, METH_NOARGS );
2547 
2548  // special case, if operator== is a global overload and included in the dictionary
2549  if ( ! HasAttrDirect( pyclass, PyStrings::gCppEq, kTRUE ) )
2550  Utility::AddToClass( pyclass, "__eq__", (PyCFunction) StlIterIsEqual, METH_O );
2551  if ( ! HasAttrDirect( pyclass, PyStrings::gCppNe, kTRUE ) )
2552  Utility::AddToClass( pyclass, "__ne__", (PyCFunction) StlIterIsNotEqual, METH_O );
2553 
2554  }
2555 
2556  else if ( name == "string" || name == "std::string" ) {
2557  Utility::AddToClass( pyclass, "__repr__", (PyCFunction) StlStringRepr, METH_NOARGS );
2558  Utility::AddToClass( pyclass, "__str__", "c_str" );
2559  Utility::AddToClass( pyclass, "__cmp__", (PyCFunction) StlStringCompare, METH_O );
2560  Utility::AddToClass( pyclass, "__eq__", (PyCFunction) StlStringIsEqual, METH_O );
2561  Utility::AddToClass( pyclass, "__ne__", (PyCFunction) StlStringIsNotEqual, METH_O );
2562 
2563  }
2564 
2565  else if ( name == "TString" ) {
2566  Utility::AddToClass( pyclass, "__repr__", (PyCFunction) TStringRepr, METH_NOARGS );
2567  Utility::AddToClass( pyclass, "__str__", "Data" );
2568  Utility::AddToClass( pyclass, "__len__", "Length" );
2569 
2570  Utility::AddToClass( pyclass, "__cmp__", "CompareTo" );
2571  Utility::AddToClass( pyclass, "__eq__", (PyCFunction) TStringIsEqual, METH_O );
2572  Utility::AddToClass( pyclass, "__ne__", (PyCFunction) TStringIsNotEqual, METH_O );
2573 
2574  }
2575 
2576  else if ( name == "TObjString" ) {
2577  Utility::AddToClass( pyclass, "__repr__", (PyCFunction) TObjStringRepr, METH_NOARGS );
2578  Utility::AddToClass( pyclass, "__str__", "GetName" );
2579  Utility::AddToClass( pyclass, "__len__", (PyCFunction) TObjStringLength, METH_NOARGS );
2580 
2581  Utility::AddToClass( pyclass, "__cmp__", (PyCFunction) TObjStringCompare, METH_O );
2582  Utility::AddToClass( pyclass, "__eq__", (PyCFunction) TObjStringIsEqual, METH_O );
2583  Utility::AddToClass( pyclass, "__ne__", (PyCFunction) TObjStringIsNotEqual, METH_O );
2584 
2585  }
2586 
2587  else if ( name == "TIter" ) {
2588  ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)PyObject_SelfIter;
2589  Utility::AddToClass( pyclass, "__iter__", (PyCFunction) PyObject_SelfIter, METH_NOARGS );
2590 
2591  ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)TIterNext;
2592  Utility::AddToClass( pyclass, PYROOT__next__, (PyCFunction) TIterNext, METH_NOARGS );
2593 
2594  }
2595 
2596  else if ( name == "TDirectory" ) {
2597  // note: this replaces the already existing TDirectory::GetObject()
2598  Utility::AddToClass( pyclass, "GetObject", (PyCFunction) TDirectoryGetObject );
2599 
2600  // note: this replaces the already existing TDirectory::WriteObject()
2601  Utility::AddToClass( pyclass, "WriteObject", (PyCFunction) TDirectoryWriteObject );
2602 
2603  }
2604 
2605  else if ( name == "TDirectoryFile" ) {
2606  // add safety for non-TObject derived Get() results
2607  Utility::AddToClass( pyclass, "Get", (PyCFunction) TDirectoryFileGet, METH_O );
2608 
2609  return kTRUE;
2610  }
2611 
2612  else if ( name == "TTree" ) {
2613  // allow direct browsing of the tree
2614  Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) TTreeGetAttr, METH_O );
2615 
2616  // workaround for templated member Branch()
2617  MethodProxy* original =
2618  (MethodProxy*)PyObject_GetAttrFromDict( pyclass, PyStrings::gBranch );
2619  MethodProxy* method = MethodProxy_New( "Branch", new TTreeBranch( original ) );
2620  Py_DECREF( original ); original = 0;
2621 
2622  PyObject_SetAttrString(
2623  pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
2624  Py_DECREF( method ); method = 0;
2625 
2626  // workaround for templated member SetBranchAddress()
2627  original = (MethodProxy*)PyObject_GetAttrFromDict( pyclass, PyStrings::gSetBranchAddress );
2628  method = MethodProxy_New( "SetBranchAddress", new TTreeSetBranchAddress( original ) );
2629  Py_DECREF( original ); original = 0;
2630 
2631  PyObject_SetAttrString(
2632  pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
2633  Py_DECREF( method ); method = 0;
2634 
2635  }
2636 
2637  else if ( name == "TChain" ) {
2638  // allow SetBranchAddress to take object directly, w/o needing AddressOf()
2639  MethodProxy* original =
2640  (MethodProxy*)PyObject_GetAttrFromDict( pyclass, PyStrings::gSetBranchAddress );
2641  MethodProxy* method = MethodProxy_New( "SetBranchAddress", new TChainSetBranchAddress( original ) );
2642  Py_DECREF( original ); original = 0;
2643 
2644  PyObject_SetAttrString(
2645  pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
2646  Py_DECREF( method ); method = 0;
2647 
2648  }
2649 
2650  else if ( name == "TStyle" ) {
2651  MethodProxy* ctor = (MethodProxy*)PyObject_GetAttr( pyclass, PyStrings::gInit );
2652  ctor->fMethodInfo->fFlags &= ~TCallContext::kIsCreator;
2653  Py_DECREF( ctor );
2654  }
2655 
2656  else if ( name == "TH1" ) // allow hist *= scalar
2657  Utility::AddToClass( pyclass, "__imul__", (PyCFunction) THNIMul, METH_O );
2658 
2659  else if ( name == "TF1" ) // allow instantiation with python callable
2660  Utility::AddToClass( pyclass, "__init__", new TF1InitWithPyFunc );
2661 
2662  else if ( name == "TF2" ) // allow instantiation with python callable
2663  Utility::AddToClass( pyclass, "__init__", new TF2InitWithPyFunc );
2664 
2665  else if ( name == "TF3" ) // allow instantiation with python callable
2666  Utility::AddToClass( pyclass, "__init__", new TF3InitWithPyFunc );
2667 
2668  else if ( name == "TFunction" ) // allow direct call
2669  Utility::AddToClass( pyclass, "__call__", (PyCFunction) TFunctionCall );
2670 
2671  else if ( name == "TMinuit" ) // allow call with python callable
2672  Utility::AddToClass( pyclass, "SetFCN", new TMinuitSetFCN );
2673 
2674  else if ( name == "TFitter" ) // allow call with python callable (this is not correct)
2675  Utility::AddToClass( pyclass, "SetFCN", new TMinuitFitterSetFCN );
2676 
2677  else if ( name == "Fitter" ) // really Fit::Fitter, allow call with python callable
2678  Utility::AddToClass( pyclass, "FitFCN", new TFitterFitFCN );
2679 
2680  else if ( name == "TFile" ) {
2681  // TFile::Open really is a constructor, really
2682  PyObject* attr = PyObject_GetAttrString( pyclass, (char*)"Open" );
2683  if ( MethodProxy_Check( attr ) )
2684  ((MethodProxy*)attr)->fMethodInfo->fFlags |= TCallContext::kIsCreator;
2685  Py_XDECREF( attr );
2686 
2687  // allow member-style access to entries in file
2688  Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) TFileGetAttr, METH_O );
2689 
2690  }
2691 
2692  else if ( name.substr(0,8) == "TVector3" ) {
2693  Utility::AddToClass( pyclass, "__len__", (PyCFunction) ReturnThree, METH_NOARGS );
2694  Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
2695  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
2696 
2697  }
2698 
2699  else if ( name.substr(0,8) == "TVectorT" ) {
2700  // allow proper iteration
2701  Utility::AddToClass( pyclass, "__len__", "GetNoElements" );
2702  Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
2703  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
2704  }
2705 
2706  else if ( name.substr(0,6) == "TArray" && name != "TArray" ) { // allow proper iteration
2707  // __len__ is already set from GetSize()
2708  Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
2709  Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
2710  }
2711 
2712 // Make RooFit 'using' member functions available (not supported by dictionary)
2713  else if ( name == "RooDataHist" )
2714  Utility::AddUsingToClass( pyclass, "plotOn" );
2715 
2716  else if ( name == "RooSimultaneous" )
2717  Utility::AddUsingToClass( pyclass, "plotOn" );
2718 
2719  else if (name.find("RVec<") != std::string::npos) {
2720  // add array interface
2721  if (name.find("<float>") != std::string::npos) {
2722  AddArrayInterface(pyclass, (PyCFunction)RVecArrayInterface<float, 'f'>);
2723  } else if (name.find("<double>") != std::string::npos) {
2724  AddArrayInterface(pyclass, (PyCFunction)RVecArrayInterface<double, 'f'>);
2725  } else if (name.find("<int>") != std::string::npos) {
2726  AddArrayInterface(pyclass, (PyCFunction)RVecArrayInterface<int, 'i'>);
2727  } else if (name.find("<unsigned int>") != std::string::npos) {
2728  AddArrayInterface(pyclass, (PyCFunction)RVecArrayInterface<unsigned int, 'u'>);
2729  } else if (name.find("<long>") != std::string::npos) {
2730  AddArrayInterface(pyclass, (PyCFunction)RVecArrayInterface<long, 'i'>);
2731  } else if (name.find("<unsigned long>") != std::string::npos) {
2732  AddArrayInterface(pyclass, (PyCFunction)RVecArrayInterface<unsigned long, 'u'>);
2733  }
2734  }
2735 
2736  // TODO: store these on the pythonizations module, not on gRootModule
2737  // TODO: externalize this code and use update handlers on the python side
2738  PyObject* userPythonizations = PyObject_GetAttrString( gRootModule, "UserPythonizations" );
2739  PyObject* pythonizationScope = PyObject_GetAttrString( gRootModule, "PythonizationScope" );
2740 
2741  std::vector< std::string > pythonization_scopes;
2742  pythonization_scopes.push_back( "__global__" );
2743 
2744  std::string user_scope = PyROOT_PyUnicode_AsString( pythonizationScope );
2745  if ( user_scope != "__global__" ) {
2746  if ( PyDict_Contains( userPythonizations, pythonizationScope ) ) {
2747  pythonization_scopes.push_back( user_scope );
2748  }
2749  }
2750 
2751  Bool_t pstatus = kTRUE;
2752 
2753  for ( auto key = pythonization_scopes.cbegin(); key != pythonization_scopes.cend(); ++key ) {
2754  PyObject* tmp = PyDict_GetItemString( userPythonizations, key->c_str() );
2755  Py_ssize_t num_pythonizations = PyList_Size( tmp );
2756  PyObject* arglist = nullptr;
2757  if ( num_pythonizations )
2758  arglist = Py_BuildValue( "O,s", pyclass, name.c_str() );
2759  for ( Py_ssize_t i = 0; i < num_pythonizations; ++i ) {
2760  PyObject* pythonizor = PyList_GetItem( tmp, i );
2761  // TODO: detail error handling for the pythonizors
2762  PyObject* result = PyObject_CallObject( pythonizor, arglist );
2763  if ( !result ) {
2764  pstatus = kFALSE;
2765  break;
2766  } else
2767  Py_DECREF( result );
2768  }
2769  Py_XDECREF( arglist );
2770  }
2771 
2772  Py_DECREF( userPythonizations );
2773  Py_DECREF( pythonizationScope );
2774 
2775 
2776 // phew! all done ...
2777  return pstatus;
2778 }
R__EXTERN PyObject * gFirst
Definition: PyStrings.h:46
R__EXTERN PyObject * gCppEq
Definition: PyStrings.h:19
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
Definition: TBranch.cxx:1275
virtual void Add(TObject *obj)
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
TCppScope_t TCppType_t
Definition: Cppyy.h:13
Bool_t AddBinaryOperator(PyObject *left, PyObject *right, const char *op, const char *label, const char *alt_label=NULL)
Install the named operator (op) into the left object&#39;s class if such a function exists as a global ov...
Definition: Utility.cxx:315
R__EXTERN PyObject * gInit
Definition: PyStrings.h:27
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
R__EXTERN PyObject * gIter
Definition: PyStrings.h:28
#define pyname
Definition: TMCParticle.cxx:19
An array of TObjects.
Definition: TObjArray.h:37
R__EXTERN PyObject * gDict
Definition: PyStrings.h:22
R__EXTERN PyObject * gEq
Definition: PyStrings.h:24
R__EXTERN PyObject * gGetSize
Definition: PyStrings.h:49
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
virtual TClass * GetTargetClass()
Collectable string class.
Definition: TObjString.h:28
static Bool_t RegisterObject(ObjectProxy *pyobj, TObject *object)
start tracking <object> proxied by <pyobj>
double T(double x)
Definition: ChebyshevPol.h:34
R__EXTERN PyObject * gTClassDynCast
Definition: PyStrings.h:59
R__EXTERN PyObject * gSize
Definition: PyStrings.h:48
virtual const char * GetClassName() const
Definition: TKey.h:71
virtual TKey * GetKey(const char *name, Short_t cycle=9999) const
Return pointer to key with name,cycle.
virtual const char * GetTypeName() const
Definition: TLeaf.h:89
R__EXTERN PyObject * gFollow
Definition: PyStrings.h:25
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
Definition: MethodProxy.h:75
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
R__EXTERN PyObject * gSetFCN
Definition: PyStrings.h:58
std::string GetFinalName(TCppType_t type)
Definition: Cppyy.cxx:561
Int_t GetOffset() const
Definition: TBranch.h:190
R__EXTERN PyObject * gBranch
Definition: PyStrings.h:54
std::vector< PyCallable *> Methods_t
Definition: MethodProxy.h:24
R__EXTERN PyObject * gFitFCN
Definition: PyStrings.h:55
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN PyObject * gEnd
Definition: PyStrings.h:45
#define gInterpreter
Definition: TInterpreter.h:527
#define PYROOT_IMPLEMENT_STRING_PYTHONIZATION(type, name)
Definition: Pythonize.cxx:1160
R__EXTERN PyObject * gCppNe
Definition: PyStrings.h:20
PyObject * TTreeGetAttr(ObjectProxy *self, PyObject *pyname)
Definition: Pythonize.cxx:1388
R__EXTERN PyObject * gVectorAt
Definition: PyStrings.h:52
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
#define PyInt_FromSsize_t
Definition: PyROOT.h:158
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4205
R__EXTERN PyObject * gDeref
Definition: PyStrings.h:21
virtual TObject * RemoveAt(Int_t idx)
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl) ...
Definition: TDirectory.cxx:868
#define PyVarObject_HEAD_INIT(type, size)
Definition: PyROOT.h:149
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
Sequenceable collection abstract base class.
MethodProxy::Methods_t fMethods
Definition: MethodProxy.h:32
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2286
void Class()
Definition: Class.C:29
R__EXTERN PyObject * gRootModule
Definition: ObjectProxy.cxx:39
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1645
std::string GetReturnTypeNormalizedName() const
Get the normalized name of the return type.
Definition: TFunction.cxx:154
virtual PyObject * FromMemory(void *address)
Definition: Converters.cxx:135
Int_t GetID() const
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:400
virtual Int_t WriteObjectAny(const void *, const char *, const char *, Option_t *="", Int_t=0)
Definition: TDirectory.h:200
R__EXTERN PyObject * gAt
Definition: PyStrings.h:43
const std::string ClassName(PyObject *pyobj)
Retrieve the class name from the given python object (which may be just an instance of the class)...
Definition: Utility.cxx:702
#define PyROOT_PyUnicode_Type
Definition: PyROOT.h:77
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:66
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
#define PyROOT_PySliceCast
Definition: PyROOT.h:144
A "std::vector"-like collection of values implementing handy operation to analyse them...
Definition: RVec.hxx:146
TObject * First() const
Return the object in the first slot.
Definition: TObjArray.cxx:495
TConverter * CreateConverter(const std::string &fullType, Long_t size=-1)
PyTypeObject ObjectProxy_Type
const TString & GetString() const
Definition: TObjString.h:47
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
R__EXTERN PyObject * gClass
Definition: PyStrings.h:18
R__EXTERN PyObject * gBegin
Definition: PyStrings.h:44
TCppScope_t gGlobalScope
Definition: Cppyy.cxx:63
#define PyInt_AsSsize_t
Definition: PyROOT.h:157
SVector< double, 2 > v
Definition: Dict.h:5
A ROOT file is structured in Directories (like a file system).
char * GetObject() const
Return a pointer to our object.
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Collection abstract base class.
Definition: TCollection.h:63
#define PyROOT_PyUnicode_FromStringAndSize
Definition: PyROOT.h:75
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5434
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:74
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
virtual void * GetValuePointer() const
Definition: TLeaf.h:88
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE, Bool_t isValue=kFALSE)
only known or knowable objects will be bound (null object is ok)
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4688
virtual Int_t GetLenStatic() const
Return the fixed length of this leaf.
Definition: TLeaf.h:82
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
A Branch for the case of an object.
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
MethodInfo_t * fMethodInfo
Definition: MethodProxy.h:52
#define d(i)
Definition: RSha256.hxx:102
virtual PyObject * Call(ObjectProxy *&self, PyObject *args, PyObject *kwds, TCallContext *ctxt=0)=0
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
R__EXTERN PyObject * gGetItem
Definition: PyStrings.h:26
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:176
double Double_t
Definition: RtypesCore.h:55
const std::string & GetName() const
Definition: MethodProxy.h:45
R__EXTERN PyObject * gName
Definition: PyStrings.h:33
Describe directory structure in memory.
Definition: TDirectory.h:34
int type
Definition: TGX11.cxx:120
#define PYROOT__next__
Definition: PyROOT.h:92
static TClass * OP2TCLASS(PyROOT::ObjectProxy *pyobj)
Definition: Pythonize.cxx:57
static RooMathCoreReg dummy
R__EXTERN PyObject * gLen
Definition: PyStrings.h:29
Bool_t AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Add the given function to the class under name &#39;label&#39;.
Definition: Utility.cxx:186
static constexpr double s
#define PyROOT_PyUnicode_Check
Definition: PyROOT.h:64
TObjArray * GetListOfLeaves()
Definition: TBranch.h:202
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl) ...
virtual void AddAt(TObject *obj, Int_t idx)=0
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
#define PYROOT_IMPLEMENT_STRING_PYTHONIZATION_CMP(type, name)
Definition: Pythonize.cxx:1209
R__EXTERN PyObject * gNe
Definition: PyStrings.h:35
Bool_t AddUsingToClass(PyObject *pyclass, const char *method)
Helper to add base class methods to the derived class one (this covers the &#39;using&#39; cases...
Definition: Utility.cxx:261
R__EXTERN PyObject * gCppName
Definition: PyStrings.h:34
TClass * GetClass() const
Definition: TClonesArray.h:56
Binding & operator=(OUT(*fun)(void))
virtual TObject * At(Int_t idx) const =0
#define org(otri, vertexptr)
Definition: triangle.c:1037
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
#define R__EXTERN
Definition: DllImport.h:27
An array of clone (identical) objects.
Definition: TClonesArray.h:32
#define Py_TYPE(ob)
Definition: PyROOT.h:151
int Py_ssize_t
Definition: PyROOT.h:156
auto * l
Definition: textangle.C:4
void * GetObject() const
Definition: ObjectProxy.h:47
static TPyBufferFactory * Instance()
R__EXTERN PyObject * gSecond
Definition: PyStrings.h:47
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check=kTRUE)
Retrieve a linear buffer pointer from the given pyobject.
Definition: Utility.cxx:539
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
Retrieve scope proxy from the known ones.
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
void * CreateWrapperMethod(PyObject *pyfunc, Long_t user, const char *retType, const std::vector< std::string > &signature, const char *callback)
Compile a function on the fly and return a function pointer for use on C-APIs.
Definition: Utility.cxx:846
Bool_t MethodProxy_Check(T *object)
Definition: MethodProxy.h:63
Definition: tree.py:1
virtual char * GetAddress() const
Definition: TBranch.h:169
double TFNPyCallback(void *vpyfunc, Long_t npar, double *a0, double *a1)
Definition: Pythonize.cxx:1782
R__EXTERN PyObject * ggetSize
Definition: PyStrings.h:50
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition: TClass.cxx:4729
TCppObject_t Construct(TCppType_t type)
Definition: Cppyy.cxx:265
static PyObject * PyROOT_PyCapsule_New(void *cobj, const char *, void(*destr)(void *))
Definition: PyROOT.h:79
R__EXTERN PyObject * gSetBranchAddress
Definition: PyStrings.h:57
TBranch * GetBranch() const
Definition: TLeaf.h:71
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
A TTree is a list of TBranches.
Definition: TBranch.h:62
const Bool_t kTRUE
Definition: RtypesCore.h:87
void TMinuitPyCallback(void *vpyfunc, Long_t, Int_t &a0, Double_t *a1, Double_t &a2, Double_t *a3, Int_t a4)
Definition: Pythonize.cxx:1752
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE)
if the object is a null pointer, return a typed one (as needed for overloading)
void Set(void *address, EFlags flags=kNone)
Definition: ObjectProxy.h:33
char name[80]
Definition: TGX11.cxx:109
_object PyObject
Definition: TPyArg.h:20
Cppyy::TCppType_t ObjectIsA() const
Definition: ObjectProxy.h:66
Bool_t Pythonize(PyObject *pyclass, const std::string &name)
Definition: Pythonize.cxx:2325
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4792
virtual Int_t GetNdata() const
Definition: TLeaf.h:86