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