Pythonize.cxx

Go to the documentation of this file.
00001 // @(#)root/pyroot:$Id: Pythonize.cxx 36998 2010-11-26 23:40:58Z wlav $
00002 // Author: Wim Lavrijsen, Jul 2004
00003 
00004 // Bindings
00005 #include "PyROOT.h"
00006 #include "PyStrings.h"
00007 #include "Pythonize.h"
00008 #include "ObjectProxy.h"
00009 #include "MethodProxy.h"
00010 #include "RootWrapper.h"
00011 #include "Utility.h"
00012 #include "PyCallable.h"
00013 #include "PyBufferFactory.h"
00014 #include "FunctionHolder.h"
00015 #include "Converters.h"
00016 #include "MemoryRegulator.h"
00017 #include "Adapters.h"
00018 #include "Utility.h"
00019 
00020 // ROOT
00021 #include "TClass.h"
00022 #include "TMethod.h"
00023 #include "TCollection.h"
00024 #include "TDirectory.h"
00025 #include "TSeqCollection.h"
00026 #include "TClonesArray.h"
00027 #include "TObject.h"
00028 #include "TFunction.h"
00029 #include "TError.h"
00030 
00031 #include "TTree.h"
00032 #include "TBranch.h"
00033 #include "TLeaf.h"
00034 
00035 // CINT
00036 #include "Api.h"
00037 
00038 // Standard
00039 #include <stdexcept>
00040 #include <string>
00041 #include <stdio.h>
00042 #include <utility>
00043 
00044 
00045 namespace {
00046 
00047 // for convenience
00048    using namespace PyROOT;
00049 
00050 //____________________________________________________________________________
00051    Bool_t HasAttrDirect( PyObject* pyclass, PyObject* pyname, Bool_t mustBePyROOT = kFALSE ) {
00052    // prevents calls to Py_TYPE(pyclass)->tp_getattr, which is unnecessary for our
00053    // purposes here and could tickle problems w/ spurious lookups into ROOT meta
00054       PyObject* attr = PyType_Type.tp_getattro( pyclass, pyname );
00055       if ( attr != 0 && ( ! mustBePyROOT || MethodProxy_Check( attr ) ) ) {
00056          Py_DECREF( attr );
00057          return kTRUE;
00058       }
00059 
00060       PyErr_Clear();
00061       return kFALSE;
00062    }
00063 
00064 //____________________________________________________________________________
00065    inline Bool_t IsTemplatedSTLClass( const std::string& name, const std::string& klass ) {
00066       const int nsize = (int)name.size();
00067       const int ksize = (int)klass.size();
00068 
00069       return ( ( ksize   < nsize && name.substr(0,ksize) == klass ) ||
00070                ( ksize+5 < nsize && name.substr(5,ksize) == klass ) ) &&
00071              name.find( "::", name.find( ">" ) ) == std::string::npos;
00072    }
00073 
00074 // to prevent compiler warnings about const char* -> char*
00075    inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth )
00076    {
00077       Py_INCREF( obj );
00078       PyObject* result = PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "" ) );
00079       Py_DECREF( obj );
00080       return result;
00081    }
00082 
00083 //____________________________________________________________________________
00084    inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1 )
00085    {
00086       Py_INCREF( obj );
00087       PyObject* result = PyObject_CallMethod(
00088          obj, const_cast< char* >( meth ), const_cast< char* >( "O" ), arg1 );
00089       Py_DECREF( obj );
00090       return result;
00091    }
00092 
00093 //____________________________________________________________________________
00094    inline PyObject* CallPyObjMethod(
00095       PyObject* obj, const char* meth, PyObject* arg1, PyObject* arg2 )
00096    {
00097       Py_INCREF( obj );
00098       PyObject* result = PyObject_CallMethod(
00099          obj, const_cast< char* >( meth ), const_cast< char* >( "OO" ), arg1, arg2 );
00100       Py_DECREF( obj );
00101       return result;
00102    }
00103 
00104 //____________________________________________________________________________
00105    inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1, int arg2 )
00106    {
00107       Py_INCREF( obj );
00108       PyObject* result = PyObject_CallMethod(
00109          obj, const_cast< char* >( meth ), const_cast< char* >( "Oi" ), arg1, arg2 );
00110       Py_DECREF( obj );
00111       return result;
00112    }
00113 
00114 
00115 //- helpers --------------------------------------------------------------------
00116    PyObject* PyStyleIndex( PyObject* self, PyObject* index )
00117    {
00118       Py_ssize_t idx = PyInt_AsSsize_t( index );
00119       if ( idx == (Py_ssize_t)-1 && PyErr_Occurred() )
00120          return 0;
00121 
00122       Py_ssize_t size = PySequence_Size( self );
00123       if ( idx >= size || ( idx < 0 && idx < -size ) ) {
00124          PyErr_SetString( PyExc_IndexError, "index out of range" );
00125          return 0;
00126       }
00127 
00128       PyObject* pyindex = 0;
00129       if ( idx >= 0 ) {
00130          Py_INCREF( index );
00131          pyindex = index;
00132       } else
00133          pyindex = PyLong_FromLong( size + idx );
00134 
00135       return pyindex;
00136    }
00137 
00138 //____________________________________________________________________________
00139    inline PyObject* CallSelfIndex( ObjectProxy* self, PyObject* idx, const char* meth )
00140    {
00141       Py_INCREF( (PyObject*)self );
00142       PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
00143       if ( ! pyindex ) {
00144          Py_DECREF( (PyObject*)self );
00145          return 0;
00146       }
00147 
00148       PyObject* result = CallPyObjMethod( (PyObject*)self, meth, pyindex );
00149       Py_DECREF( pyindex );
00150       Py_DECREF( (PyObject*)self );
00151       return result;
00152    }
00153 
00154 //____________________________________________________________________________
00155    inline PyObject* BoolNot( PyObject* value )
00156    {
00157       if ( PyObject_IsTrue( value ) == 1 ) {
00158          Py_INCREF( Py_False );
00159          Py_DECREF( value );
00160          return Py_False;
00161       } else {
00162          Py_INCREF( Py_True );
00163          Py_XDECREF( value );
00164          return Py_True;
00165       }
00166    }
00167 
00168 //- "smart pointer" behavior ---------------------------------------------------
00169    PyObject* DeRefGetAttr( PyObject* self, PyObject* name )
00170    {
00171       if ( ! PyROOT_PyUnicode_Check( name ) )
00172          PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );
00173 
00174       PyObject* pyptr = CallPyObjMethod( self, "__deref__" );
00175       if ( ! pyptr )
00176          return 0;
00177 
00178    // prevent a potential infinite loop
00179       if ( Py_TYPE(pyptr) == Py_TYPE(self) ) {
00180          PyObject* val1 = PyObject_Str( self );
00181          PyObject* val2 = PyObject_Str( name );
00182          PyErr_Format( PyExc_AttributeError, "%s has no attribute \'%s\'",
00183             PyROOT_PyUnicode_AsString( val1 ), PyROOT_PyUnicode_AsString( val2 ) );
00184          Py_DECREF( val2 );
00185          Py_DECREF( val1 );
00186 
00187          Py_DECREF( pyptr );
00188          return 0;
00189       }
00190 
00191       PyObject* result = PyObject_GetAttr( pyptr, name );
00192       Py_DECREF( pyptr );
00193       return result;
00194    }
00195 
00196 //____________________________________________________________________________
00197    PyObject* FollowGetAttr( PyObject* self, PyObject* name )
00198    {
00199       if ( ! PyROOT_PyUnicode_Check( name ) )
00200          PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );
00201 
00202       PyObject* pyptr = CallPyObjMethod( self, "__follow__" );
00203       if ( ! pyptr )
00204          return 0;
00205 
00206       PyObject* result = PyObject_GetAttr( pyptr, name );
00207       Py_DECREF( pyptr );
00208       return result;
00209    }
00210 
00211 //- TObject behavior -----------------------------------------------------------
00212    PyObject* TObjectContains( PyObject* self, PyObject* obj )
00213    {
00214       if ( ! ( ObjectProxy_Check( obj ) || PyROOT_PyUnicode_Check( obj ) ) )
00215          return PyInt_FromLong( 0l );
00216 
00217       PyObject* found = CallPyObjMethod( self, "FindObject", obj );
00218       PyObject* result = PyInt_FromLong( PyObject_IsTrue( found ) );
00219       Py_DECREF( found );
00220       return result;
00221    }
00222 
00223 //____________________________________________________________________________
00224    PyObject* TObjectCompare( PyObject* self, PyObject* obj )
00225    {
00226       if ( ! ObjectProxy_Check( obj ) )
00227          return PyInt_FromLong( -1l );
00228 
00229       return CallPyObjMethod( self, "Compare", obj );
00230    }
00231 
00232 //____________________________________________________________________________
00233    PyObject* TObjectIsEqual( PyObject* self, PyObject* obj )
00234    {
00235       if ( ! ObjectProxy_Check( obj ) || ! ((ObjectProxy*)obj)->fObject )
00236          return ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );
00237 
00238       return CallPyObjMethod( self, "IsEqual", obj );
00239    }
00240 
00241 //____________________________________________________________________________
00242    PyObject* TObjectIsNotEqual( PyObject* self, PyObject* obj )
00243    {
00244       if ( ! ObjectProxy_Check( obj ) || ! ((ObjectProxy*)obj)->fObject )
00245          return ObjectProxy_Type.tp_richcompare( self, obj, Py_NE );
00246 
00247       return BoolNot( CallPyObjMethod( self, "IsEqual", obj ) );
00248    }
00249 
00250 //____________________________________________________________________________
00251    PyObject* GenObjectIsEqual( PyObject* self, PyObject* obj )
00252    {
00253    // Contrary to TObjectIsEqual, it can now not be relied upon that the only
00254    // non-ObjectProxy obj is None, as any operator==(), taking any object (e.g.
00255    // an enum) can be implemented. However, those cases will yield an exception
00256    // if presented with None.
00257       PyObject* result = CallPyObjMethod( self, "__cpp_eq__", obj );
00258       if ( ! result ) {
00259          PyErr_Clear();
00260          result = ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );
00261       }
00262 
00263       return result;
00264    }
00265 
00266 //____________________________________________________________________________
00267    PyObject* GenObjectIsNotEqual( PyObject* self, PyObject* obj )
00268    {
00269    // Reverse of GenObjectIsEqual, if operator!= defined
00270       PyObject* result = CallPyObjMethod( self, "__cpp_ne__", obj );
00271       if ( ! result ) {
00272          PyErr_Clear();
00273          result = ObjectProxy_Type.tp_richcompare( self, obj, Py_NE );
00274       }
00275 
00276       return result;
00277    }
00278 
00279 //- TClass behavior ------------------------------------------------------------
00280    PyObject* TClassStaticCast( ObjectProxy* self, PyObject* args )
00281    {
00282    // Implemented somewhat different than TClass::DynamicClass, in that "up" is
00283    // chosen automatically based on the relationship between self and arg pyclass.
00284       ObjectProxy* pyclass = 0; PyObject* pyobject = 0;
00285       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O:StaticCast" ),
00286               &ObjectProxy_Type, &pyclass, &pyobject ) )
00287          return 0;
00288 
00289    // check the given arguments (dcasts are necessary b/c of could be a TQClass
00290       TClass* from =
00291          (TClass*)self->ObjectIsA()->DynamicCast( TClass::Class(), self->GetObject() );
00292       TClass* to   =
00293          (TClass*)pyclass->ObjectIsA()->DynamicCast( TClass::Class(), pyclass->GetObject() );
00294 
00295       if ( ! from ) {
00296          PyErr_SetString( PyExc_TypeError, "unbound method TClass::StaticCast "
00297             "must be called with a TClass instance as first argument" );
00298          return 0;
00299       }
00300 
00301       if ( ! to ) {
00302          PyErr_SetString( PyExc_TypeError, "could not convert argument 1 (TClass* expected)" );
00303          return 0;
00304       }
00305 
00306    // retrieve object address
00307       void* address = 0;
00308       if ( ObjectProxy_Check( pyobject ) ) address = ((ObjectProxy*)pyobject)->GetObject();
00309       else if ( PyInt_Check( pyobject ) ) address = (void*)PyInt_AS_LONG( pyobject );
00310       else Utility::GetBuffer( pyobject, '*', 1, address, kFALSE );
00311 
00312       if ( ! address ) {
00313          PyErr_SetString( PyExc_TypeError, "could not convert argument 2 (void* expected)" );
00314          return 0;
00315       }
00316 
00317    // determine direction of cast
00318       int up = -1;
00319       if ( from->InheritsFrom( to ) ) up = 1;
00320       else if ( to->InheritsFrom( from ) ) {
00321          TClass* tmp = to; to = from; from = tmp;
00322          up = 0;
00323       }
00324 
00325       if ( up == -1 ) {
00326          PyErr_Format( PyExc_TypeError, "unable to cast %s to %s", from->GetName(), to->GetName() );
00327          return 0;
00328       }
00329 
00330    // perform actual cast
00331       void* result = from->DynamicCast( to, address, (Bool_t)up );
00332 
00333    // at this point, "result" can't be null (but is still safe if it is)
00334       return BindRootObjectNoCast( result, to );
00335    }
00336 
00337 //____________________________________________________________________________
00338    PyObject* TClassDynamicCast( ObjectProxy* self, PyObject* args )
00339    {
00340       ObjectProxy* pyclass = 0; PyObject* pyobject = 0;
00341       long up = 1;
00342       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O|l:DynamicCast" ),
00343               &ObjectProxy_Type, &pyclass, &pyobject, &up ) )
00344          return 0;
00345 
00346    // perform actual cast
00347       PyObject* meth = PyObject_GetAttr( (PyObject*)self, PyStrings::gTClassDynCast );
00348       PyObject* ptr = meth ? PyObject_Call(
00349          meth, PyTuple_GetSlice( args, 1, PyTuple_GET_SIZE( args ) ), 0 ) : 0;
00350       Py_XDECREF( meth );
00351 
00352    // simply forward in case of call failure
00353       if ( ! ptr )
00354          return ptr;
00355 
00356    // supposed to be an int or long ...
00357       long address = PyLong_AsLong( ptr );
00358       if ( address == -1 && PyErr_Occurred() ) {
00359          PyErr_Clear();
00360          return ptr;
00361       }
00362 
00363    // now use binding to return a usable class
00364       TClass* klass = 0;
00365       if ( up ) {                  // up-cast: result is a base
00366          klass = (TClass*)pyclass->ObjectIsA()->DynamicCast( TClass::Class(), pyclass->GetObject() );
00367       } else {                     // down-cast: result is a derived
00368          klass = (TClass*)self->ObjectIsA()->DynamicCast( TClass::Class(), self->GetObject() );
00369       }
00370 
00371       PyObject* result = BindRootObjectNoCast( (void*)address, klass );
00372       Py_DECREF( ptr );
00373       return result;
00374    }
00375 
00376 //- TCollection behavior -------------------------------------------------------
00377    PyObject* TCollectionExtend( PyObject* self, PyObject* obj )
00378    {
00379       for ( Py_ssize_t i = 0; i < PySequence_Size( obj ); ++i ) {
00380          PyObject* item = PySequence_GetItem( obj, i );
00381          PyObject* result = CallPyObjMethod( self, "Add", item );
00382          Py_XDECREF( result );
00383          Py_DECREF( item );
00384       }
00385 
00386       Py_INCREF( Py_None );
00387       return Py_None;
00388    }
00389 
00390 //____________________________________________________________________________
00391    PyObject* TCollectionRemove( PyObject* self, PyObject* obj )
00392    {
00393       PyObject* result = CallPyObjMethod( self, "Remove", obj );
00394       if ( ! result )
00395          return 0;
00396 
00397       if ( ! PyObject_IsTrue( result ) ) {
00398          Py_DECREF( result );
00399          PyErr_SetString( PyExc_ValueError, "list.remove(x): x not in list" );
00400          return 0;
00401       }
00402 
00403       Py_DECREF( result );
00404       Py_INCREF( Py_None );
00405       return Py_None;
00406    }
00407 
00408 //____________________________________________________________________________
00409    PyObject* TCollectionAdd( PyObject* self, PyObject* other )
00410    {
00411       PyObject* l = CallPyObjMethod( self, "Clone" );
00412       if ( ! l )
00413          return 0;
00414 
00415       PyObject* result = CallPyObjMethod( l, "extend", other );
00416       if ( ! result ) {
00417          Py_DECREF( l );
00418          return 0;
00419       }
00420 
00421       return l;
00422    }
00423 
00424 //____________________________________________________________________________
00425    PyObject* TCollectionMul( ObjectProxy* self, PyObject* pymul )
00426    {
00427       Long_t imul = PyLong_AsLong( pymul );
00428       if ( imul == -1 && PyErr_Occurred() )
00429          return 0;
00430 
00431       if ( ! self->GetObject() ) {
00432          PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00433          return 0;
00434       }
00435 
00436       PyObject* nseq = BindRootObject( self->ObjectIsA()->New(), self->ObjectIsA() );
00437 
00438       for ( Long_t i = 0; i < imul; ++i ) {
00439          PyObject* result = CallPyObjMethod( nseq, "extend", (PyObject*)self );
00440          Py_DECREF( result );
00441       }
00442 
00443       return nseq;
00444    }
00445 
00446 //____________________________________________________________________________
00447    PyObject* TCollectionIMul( PyObject* self, PyObject* pymul )
00448    {
00449       Long_t imul = PyLong_AsLong( pymul );
00450       if ( imul == -1 && PyErr_Occurred() )
00451          return 0;
00452 
00453       PyObject* l = PySequence_List( self );
00454 
00455       for ( Long_t i = 0; i < imul - 1; ++i ) {
00456          CallPyObjMethod( self, "extend", l );
00457       }
00458 
00459       Py_INCREF( self );
00460       return self;
00461    }
00462 
00463 //____________________________________________________________________________
00464    PyObject* TCollectionCount( PyObject* self, PyObject* obj )
00465    {
00466       Py_ssize_t count = 0;
00467       for ( Py_ssize_t i = 0; i < PySequence_Size( self ); ++i ) {
00468          PyObject* item = PySequence_GetItem( self, i );
00469          PyObject* found = PyObject_RichCompare( item, obj, Py_EQ );
00470 
00471          Py_DECREF( item );
00472 
00473          if ( ! found )
00474             return 0;                        // internal problem
00475 
00476          if ( PyObject_IsTrue( found ) )
00477             count += 1;
00478          Py_DECREF( found );
00479       }
00480 
00481       return PyInt_FromSsize_t( count );
00482    }
00483 
00484 //____________________________________________________________________________
00485    PyObject* TCollectionIter( ObjectProxy* self ) {
00486       if ( ! self->GetObject() ) {
00487          PyErr_SetString( PyExc_TypeError, "iteration over non-sequence" );
00488          return 0;
00489       }
00490 
00491       TCollection* col =
00492          (TCollection*)self->ObjectIsA()->DynamicCast( TCollection::Class(), self->GetObject() );
00493 
00494       PyObject* pyobject = BindRootObject( (void*) new TIter( col ), TIter::Class() );
00495       ((ObjectProxy*)pyobject)->HoldOn();
00496       return pyobject;
00497    }
00498 
00499 
00500 //- TSeqCollection behavior ----------------------------------------------------
00501    PyObject* TSeqCollectionGetItem( ObjectProxy* self, PySliceObject* index )
00502    {
00503       if ( PySlice_Check( index ) ) {
00504          if ( ! self->GetObject() ) {
00505             PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00506             return 0;
00507          }
00508 
00509          TClass* clSeq = self->ObjectIsA();
00510          TSeqCollection* oseq =
00511             (TSeqCollection*)clSeq->DynamicCast( TSeqCollection::Class(), self->GetObject() );
00512          TSeqCollection* nseq = (TSeqCollection*)clSeq->New();
00513 
00514          Py_ssize_t start, stop, step;
00515          PySlice_GetIndices( index, oseq->GetSize(), &start, &stop, &step );
00516          for ( Py_ssize_t i = start; i < stop; i += step ) {
00517             nseq->Add( oseq->At( (Int_t)i ) );
00518          }
00519 
00520          return BindRootObject( (void*) nseq, clSeq );
00521       }
00522 
00523       return CallSelfIndex( self, (PyObject*)index, "At" );
00524    }
00525 
00526 //____________________________________________________________________________
00527    PyObject* TSeqCollectionSetItem( ObjectProxy* self, PyObject* args )
00528    {
00529       PyObject* index = 0, *obj = 0;
00530       if ( ! PyArg_ParseTuple( args,
00531                 const_cast< char* >( "OO:__setitem__" ), &index, &obj ) )
00532          return 0;
00533 
00534       if ( PySlice_Check( index ) ) {
00535          if ( ! self->GetObject() ) {
00536             PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00537             return 0;
00538          }
00539 
00540          TSeqCollection* oseq = (TSeqCollection*)self->ObjectIsA()->DynamicCast(
00541             TSeqCollection::Class(), self->GetObject() );
00542 
00543          Py_ssize_t start, stop, step;
00544          PySlice_GetIndices( (PySliceObject*) index, oseq->GetSize(), &start, &stop, &step );
00545          for ( Py_ssize_t i = stop - step; i >= start; i -= step ) {
00546             oseq->RemoveAt( (Int_t)i );
00547          }
00548 
00549          for ( Py_ssize_t i = 0; i < PySequence_Size( obj ); ++i ) {
00550             ObjectProxy* item = (ObjectProxy*)PySequence_GetItem( obj, i );
00551             item->Release();
00552             oseq->AddAt( (TObject*) item->GetObject(), (Int_t)(i + start) );
00553             Py_DECREF( item );
00554          }
00555 
00556          Py_INCREF( Py_None );
00557          return Py_None;
00558       }
00559 
00560       PyObject* pyindex = PyStyleIndex( (PyObject*)self, index );
00561       if ( ! pyindex )
00562          return 0;
00563 
00564       PyObject* result  = CallPyObjMethod( (PyObject*)self, "RemoveAt", pyindex );
00565       if ( ! result ) {
00566          Py_DECREF( pyindex );
00567          return 0;
00568       }
00569 
00570       Py_DECREF( result );
00571       result = CallPyObjMethod( (PyObject*)self, "AddAt", obj, pyindex );
00572       Py_DECREF( pyindex );
00573       return result;
00574    }
00575 
00576 //____________________________________________________________________________
00577    PyObject* TSeqCollectionDelItem( ObjectProxy* self, PySliceObject* index )
00578    {
00579       if ( PySlice_Check( index ) ) {
00580          if ( ! self->GetObject() ) {
00581             PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00582             return 0;
00583          }
00584 
00585          TSeqCollection* oseq = (TSeqCollection*)self->ObjectIsA()->DynamicCast(
00586             TSeqCollection::Class(), self->GetObject() );
00587 
00588          Py_ssize_t start, stop, step;
00589          PySlice_GetIndices( index, oseq->GetSize(), &start, &stop, &step );
00590          for ( Py_ssize_t i = stop - step; i >= start; i -= step ) {
00591             oseq->RemoveAt( (Int_t)i );
00592          }
00593 
00594          Py_INCREF( Py_None );
00595          return Py_None;
00596       }
00597 
00598       PyObject* result = CallSelfIndex( self, (PyObject*)index, "RemoveAt" );
00599       if ( ! result )
00600          return 0;
00601 
00602       Py_DECREF( result );
00603       Py_INCREF( Py_None );
00604       return Py_None;
00605    }
00606 
00607 //____________________________________________________________________________
00608    PyObject* TSeqCollectionInsert( PyObject* self, PyObject* args )
00609    {
00610       PyObject* obj = 0; Long_t idx = 0;
00611       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "lO:insert" ), &idx, &obj ) )
00612          return 0;
00613 
00614       Py_ssize_t size = PySequence_Size( self );
00615       if ( idx < 0 )
00616          idx = 0;
00617       else if ( size < idx )
00618          idx = size;
00619 
00620       return CallPyObjMethod( self, "AddAt", obj, idx );
00621    }
00622 
00623 //____________________________________________________________________________
00624    PyObject* TSeqCollectionPop( ObjectProxy* self, PyObject* args )
00625    {
00626       int nArgs = PyTuple_GET_SIZE( args );
00627       if ( nArgs == 0 ) {
00628       // create the default argument 'end of sequence'
00629          PyObject* index = PyInt_FromSsize_t( PySequence_Size( (PyObject*)self ) - 1 );
00630          PyObject* result = CallSelfIndex( self, index, "RemoveAt" );
00631          Py_DECREF( index );
00632          return result;
00633       } else if ( nArgs != 1 ) {
00634          PyErr_Format( PyExc_TypeError,
00635             "pop() takes at most 1 argument (%d given)", nArgs );
00636          return 0;
00637       }
00638 
00639       return CallSelfIndex( self, PyTuple_GET_ITEM( args, 0 ), "RemoveAt" );
00640    }
00641 
00642 //____________________________________________________________________________
00643    PyObject* TSeqCollectionReverse( PyObject* self )
00644    {
00645       PyObject* tup = PySequence_Tuple( self );
00646       if ( ! tup )
00647          return 0;
00648 
00649       PyObject* result = CallPyObjMethod( self, "Clear" );
00650       Py_XDECREF( result );
00651 
00652       for ( Py_ssize_t i = 0; i < PySequence_Size( tup ); ++i ) {
00653          PyObject* retval = CallPyObjMethod( self, "AddAt", PyTuple_GET_ITEM( tup, i ), 0 );
00654          Py_XDECREF( retval );
00655       }
00656 
00657       Py_INCREF( Py_None );
00658       return Py_None;
00659    }
00660 
00661 //____________________________________________________________________________
00662    PyObject* TSeqCollectionSort( PyObject* self, PyObject* args, PyObject* kw )
00663    {
00664       if ( PyTuple_GET_SIZE( args ) == 0 && ! kw ) {
00665       // no specialized sort, use ROOT one
00666          return CallPyObjMethod( self, "Sort" );
00667       } else {
00668       // sort in a python list copy
00669          PyObject* l = PySequence_List( self );
00670          PyObject* result = 0;
00671          if ( PyTuple_GET_SIZE( args ) == 1 )
00672             result = CallPyObjMethod( l, "sort", PyTuple_GET_ITEM( args, 0 ) );
00673          else {
00674             PyObject* pymeth = PyObject_GetAttrString( l, const_cast< char* >( "sort" ) );
00675             result = PyObject_Call( pymeth, args, kw );
00676             Py_DECREF( pymeth );
00677          }
00678 
00679          Py_XDECREF( result );
00680          if ( PyErr_Occurred() ) {
00681             Py_DECREF( l );
00682             return 0;
00683          }
00684 
00685          result = CallPyObjMethod( self, "Clear" );
00686          Py_XDECREF( result );
00687          result = CallPyObjMethod( self, "extend", l );
00688          Py_XDECREF( result );
00689          Py_DECREF( l );
00690 
00691          Py_INCREF( Py_None );
00692          return Py_None;
00693       }
00694    }
00695 
00696 //____________________________________________________________________________
00697    PyObject* TSeqCollectionIndex( PyObject* self, PyObject* obj )
00698    {
00699       PyObject* index = CallPyObjMethod( self, "IndexOf", obj );
00700       if ( ! index )
00701          return 0;
00702 
00703       if ( PyLong_AsLong( index ) < 0 ) {
00704          Py_DECREF( index );
00705          PyErr_SetString( PyExc_ValueError, "list.index(x): x not in list" );
00706          return 0;
00707       }
00708 
00709       return index;
00710    }
00711 
00712 //- TClonesArray behavior ------------------------------------------------------
00713    PyObject* TClonesArraySetItem( ObjectProxy* self, PyObject* args )
00714    {
00715    // TClonesArray sets objects by constructing them in-place; which is impossible
00716    // to support as the python object given as value must exist a priori. It can,
00717    // however, be memcpy'd and stolen, caveat emptor.
00718       ObjectProxy* pyobj = 0; PyObject* idx = 0;
00719       if ( ! PyArg_ParseTuple( args,
00720                const_cast< char* >( "OO!:__setitem__" ), &idx, &ObjectProxy_Type, &pyobj ) )
00721          return 0;
00722 
00723       if ( ! self->GetObject() ) {
00724          PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00725          return 0;
00726       }
00727 
00728       PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
00729       if ( ! pyindex )
00730          return 0;
00731       int index = (int)PyLong_AsLong( pyindex );
00732       Py_DECREF( pyindex );
00733 
00734    // get hold of the actual TClonesArray
00735       TClonesArray* cla =
00736          (TClonesArray*)self->ObjectIsA()->DynamicCast( TClonesArray::Class(), self->GetObject() );
00737 
00738       if ( ! cla ) {
00739          PyErr_SetString( PyExc_TypeError, "attempt to call with null object" );
00740          return 0;
00741       }
00742 
00743       if ( cla->GetClass() != pyobj->ObjectIsA() ) {
00744          PyErr_Format( PyExc_TypeError, "require object of type %s, but %s given",
00745             cla->GetClass()->GetName(), pyobj->ObjectIsA()->GetName() );
00746       }
00747 
00748    // destroy old stuff, if applicable
00749       if ( ((const TClonesArray&)*cla)[index] ) {
00750          cla->RemoveAt( index );
00751       }
00752 
00753       if ( pyobj->GetObject() ) {
00754       // accessing an entry will result in new, unitialized memory (if properly used)
00755          TObject* object = (*cla)[index];
00756          pyobj->Release();
00757          TMemoryRegulator::RegisterObject( pyobj, object );
00758          memcpy( (void*)object, pyobj->GetObject(), cla->GetClass()->Size() );
00759       }
00760 
00761       Py_INCREF( Py_None );
00762       return Py_None;
00763    }
00764 
00765 //- vector behavior as primitives ----------------------------------------------
00766    PyObject* VectorGetItem( ObjectProxy* self, PySliceObject* index )
00767    {
00768       if ( PySlice_Check( index ) ) {
00769          if ( ! self->GetObject() ) {
00770             PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00771             return 0;
00772          }
00773 
00774          PyObject* pyclass = PyObject_GetAttr( (PyObject*)self, PyStrings::gClass );
00775          PyObject* nseq = PyObject_CallObject( pyclass, NULL );
00776          Py_DECREF( pyclass );
00777  
00778          Py_ssize_t start, stop, step;
00779          PySlice_GetIndices( index, PyObject_Length( (PyObject*)self ), &start, &stop, &step );
00780          for ( Py_ssize_t i = start; i < stop; i += step ) {
00781             PyObject* pyidx = PyInt_FromSsize_t( i );
00782             CallPyObjMethod( nseq, "push_back", CallPyObjMethod( (PyObject*)self, "_vector__at", pyidx ) );
00783             Py_DECREF( pyidx );
00784          }
00785 
00786          return nseq;
00787       }
00788 
00789       return CallSelfIndex( self, (PyObject*)index, "_vector__at" );
00790    }
00791 
00792 //- map behavior as primitives ------------------------------------------------
00793    PyObject* MapContains( PyObject* self, PyObject* obj )
00794    {
00795       PyObject* result = 0;
00796 
00797       PyObject* iter = CallPyObjMethod( self, "find", obj );
00798       if ( ObjectProxy_Check( iter ) ) {
00799          PyObject* end = CallPyObjMethod( self, "end" );
00800          if ( ObjectProxy_Check( end ) ) {
00801             if ( ! PyObject_RichCompareBool( iter, end, Py_EQ ) ) {
00802                Py_INCREF( Py_True );
00803                result = Py_True;
00804             }
00805          }
00806          Py_XDECREF( end );
00807       }
00808       Py_XDECREF( iter );
00809 
00810       if ( ! result ) {
00811          PyErr_Clear();            // e.g. wrong argument type, which should always lead to False
00812          Py_INCREF( Py_False );
00813          result = Py_False;
00814       }
00815 
00816       return result;
00817    }
00818 
00819 //- STL container iterator support --------------------------------------------
00820    PyObject* StlSequenceIter( PyObject* self )
00821    {
00822       PyObject* iter = CallPyObjMethod( self, "begin" );
00823       if ( iter ) {
00824          PyObject* end = CallPyObjMethod( self, "end" );
00825          if ( end )
00826             PyObject_SetAttr( iter, PyStrings::gEnd, end );
00827          Py_XDECREF( end );
00828       }
00829       return iter;
00830    }
00831 
00832 //- safe indexing for STL-like vector w/o iterator dictionaries ---------------
00833    PyObject* CheckedGetItem( PyObject* self, PyObject* obj )
00834    {
00835       Bool_t inbounds = kFALSE;
00836       Py_ssize_t size = PySequence_Size( self );
00837       Py_ssize_t idx  = PyInt_AsSsize_t( obj );
00838       if ( 0 <= idx && 0 <= size && idx < size )
00839          inbounds = kTRUE;
00840 
00841       if ( inbounds ) {
00842          return CallPyObjMethod( self, "_getitem__unchecked", obj );
00843       } else if ( PyErr_Occurred() ) {
00844       // argument conversion problem: let method itself resolve anew and report
00845          PyErr_Clear();
00846          return CallPyObjMethod( self, "_getitem__unchecked", obj );
00847       } else {
00848          PyErr_SetString( PyExc_IndexError, "index out of range" );
00849       }
00850 
00851       return 0;
00852    }
00853 
00854 //- pair as sequence to allow tuple unpacking ---------------------------------
00855    PyObject* PairUnpack( PyObject* self, PyObject* pyindex )
00856    {
00857       Long_t idx = PyLong_AsLong( pyindex );
00858       if ( idx == -1 && PyErr_Occurred() )
00859          return 0;
00860 
00861       if ( ! ObjectProxy_Check( self ) || ! ((ObjectProxy*)self)->GetObject() ) {
00862          PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
00863          return 0;
00864       }
00865 
00866       if ( (int)idx == 0 )
00867          return PyObject_GetAttr( self, PyStrings::gFirst );
00868       else if ( (int)idx == 1 )
00869          return PyObject_GetAttr( self, PyStrings::gSecond );
00870 
00871    // still here? Trigger stop iteration
00872       PyErr_SetString( PyExc_IndexError, "out of bounds" );
00873       return 0;
00874    }
00875 
00876 //- string behavior as primitives ----------------------------------------------
00877 #if PY_VERSION_HEX >= 0x03000000
00878 // TODO: this is wrong, b/c it doesn't order
00879 static int PyObject_Compare( PyObject* one, PyObject* other ) {
00880    return ! PyObject_RichCompareBool( one, other, Py_EQ );
00881 }
00882 #endif
00883 #define PYROOT_IMPLEMENT_STRING_PYTHONIZATION( name, func )                   \
00884    PyObject* name##StringRepr( PyObject* self )                               \
00885    {                                                                          \
00886       PyObject* data = CallPyObjMethod( self, #func );                        \
00887       PyObject* repr = PyROOT_PyUnicode_FromFormat( "\'%s\'", PyROOT_PyUnicode_AsString( data ) ); \
00888       Py_DECREF( data );                                                      \
00889       return repr;                                                            \
00890    }                                                                          \
00891                                                                               \
00892    PyObject* name##StringIsEqual( PyObject* self, PyObject* obj )             \
00893    {                                                                          \
00894       PyObject* data = CallPyObjMethod( self, #func );                        \
00895       PyObject* result = PyObject_RichCompare( data, obj, Py_EQ );            \
00896       Py_DECREF( data );                                                      \
00897       if ( ! result )                                                         \
00898          return 0;                                                            \
00899       return result;                                                          \
00900    }                                                                          \
00901                                                                               \
00902    PyObject* name##StringIsNotEqual( PyObject* self, PyObject* obj )          \
00903    {                                                                          \
00904       PyObject* data = CallPyObjMethod( self, #func );                        \
00905       PyObject* result = PyObject_RichCompare( data, obj, Py_NE );            \
00906       Py_DECREF( data );                                                      \
00907       if ( ! result )                                                         \
00908          return 0;                                                            \
00909       return result;                                                          \
00910    }
00911 
00912    // Only define StlStringCompare:
00913    // TStringCompare is unused and generates a warning;
00914 #define PYROOT_IMPLEMENT_STRING_PYTHONIZATION_CMP( name, func )               \
00915    PyObject* name##StringCompare( PyObject* self, PyObject* obj )             \
00916    {                                                                          \
00917       PyObject* data = CallPyObjMethod( self, #func );                        \
00918       int result = PyObject_Compare( data, obj );                             \
00919       Py_DECREF( data );                                                      \
00920       if ( PyErr_Occurred() )                                                 \
00921          return 0;                                                            \
00922       return PyInt_FromLong( result );                                        \
00923    }                                                                          \
00924                                                                               \
00925    PYROOT_IMPLEMENT_STRING_PYTHONIZATION( name, func )
00926    PYROOT_IMPLEMENT_STRING_PYTHONIZATION_CMP( Stl, c_str )
00927    PYROOT_IMPLEMENT_STRING_PYTHONIZATION(   T, Data )
00928 
00929 
00930 //- TObjString behavior --------------------------------------------------------
00931    PYROOT_IMPLEMENT_STRING_PYTHONIZATION_CMP( TObj, GetName )
00932 
00933 //____________________________________________________________________________
00934    PyObject* TObjStringLength( PyObject* self )
00935    {
00936       PyObject* data = CallPyObjMethod( self, "GetName" );
00937       Py_ssize_t size = PySequence_Size( data );
00938       Py_DECREF( data );
00939       return PyInt_FromSsize_t( size );
00940    }
00941 
00942 
00943 //- TIter behavior -------------------------------------------------------------
00944    PyObject* TIterIter( PyObject* self )
00945    {
00946       Py_INCREF( self );
00947       return self;
00948    }
00949 
00950 //____________________________________________________________________________
00951    PyObject* TIterNext( PyObject* self )
00952    {
00953       PyObject* next = CallPyObjMethod( self, "Next" );
00954 
00955       if ( ! next )
00956          return 0;
00957 
00958       if ( ! PyObject_IsTrue( next ) ) {
00959          Py_DECREF( next );
00960          PyErr_SetString( PyExc_StopIteration, "" );
00961          return 0;
00962       }
00963 
00964       return next;
00965    }
00966 
00967 
00968 //- STL iterator behavior ------------------------------------------------------
00969    PyObject* StlIterNext( PyObject* self )
00970    {
00971       PyObject* next = 0;
00972       PyObject* last = PyObject_GetAttr( self, PyStrings::gEnd );
00973 
00974       if ( last != 0 ) {
00975       // handle special case of empty container (i.e. self is end)
00976          if ( PyObject_RichCompareBool( last, self, Py_EQ ) ) {
00977             PyErr_SetString( PyExc_StopIteration, "" );
00978          } else {
00979             PyObject* dummy = PyInt_FromLong( 1l );
00980             PyObject* iter = CallPyObjMethod( self, "__postinc__", dummy );
00981             Py_DECREF( dummy );
00982             if ( iter != 0 ) {
00983                if ( PyObject_RichCompareBool( last, iter, Py_EQ ) )
00984                   PyErr_SetString( PyExc_StopIteration, "" );
00985                else
00986                   next = CallPyObjMethod( iter, "__deref__" );
00987             } else {
00988                PyErr_SetString( PyExc_StopIteration, "" );
00989             }
00990             Py_XDECREF( iter );
00991          }
00992       } else {
00993          PyErr_SetString( PyExc_StopIteration, "" );
00994       }
00995 
00996       Py_XDECREF( last );
00997       return next;
00998    }
00999 
01000 //____________________________________________________________________________
01001    PyObject* StlIterIsEqual( PyObject* self, PyObject* other )
01002    {
01003    // Called if operator== not available (e.g. if a global overload as under gcc).
01004    // An exception is raised as the user should fix the dictionary.
01005       return PyErr_Format( PyExc_LookupError, 
01006          "No operator==(const %s&, const %s&) available in the dictionary!",
01007          Utility::ClassName( self ).c_str(), Utility::ClassName( other ).c_str()  );
01008    }
01009 
01010 //____________________________________________________________________________
01011    PyObject* StlIterIsNotEqual( PyObject* self, PyObject* other )
01012    {
01013    // Called if operator== not available (e.g. if a global overload as under gcc).
01014    // An exception is raised as the user should fix the dictionary.
01015       return PyErr_Format( PyExc_LookupError,
01016          "No operator!=(const %s&, const %s&) available in the dictionary!", 
01017          Utility::ClassName( self ).c_str(), Utility::ClassName( other ).c_str()  );
01018    }
01019 
01020 
01021 //- TDirectory member templates ----------------------------------------------
01022    PyObject* TDirectoryGetObject( ObjectProxy* self, PyObject* args )
01023    {
01024       PyObject* name = 0; ObjectProxy* ptr = 0;
01025       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!:TDirectory::GetObject" ),
01026                &PyROOT_PyUnicode_Type, &name, &ObjectProxy_Type, &ptr ) )
01027          return 0;
01028 
01029       TDirectory* dir =
01030          (TDirectory*)self->ObjectIsA()->DynamicCast( TDirectory::Class(), self->GetObject() );
01031 
01032       if ( ! dir ) {
01033          PyErr_SetString( PyExc_TypeError,
01034            "TDirectory::GetObject must be called with a TDirectory instance as first argument" );
01035          return 0;
01036       }
01037 
01038       void* address = dir->GetObjectChecked( PyROOT_PyUnicode_AsString( name ), ptr->ObjectIsA() );
01039       if ( address ) {
01040          ptr->Set( address );
01041 
01042          Py_INCREF( Py_None );
01043          return Py_None;
01044       }
01045 
01046       PyErr_Format( PyExc_LookupError, "no such object, \"%s\"", PyROOT_PyUnicode_AsString( name ) );
01047       return 0;
01048    }
01049 
01050 //____________________________________________________________________________
01051    PyObject* TDirectoryWriteObject( ObjectProxy* self, PyObject* args )
01052    {
01053       ObjectProxy *wrt = 0; PyObject *name = 0, *option = 0;
01054       Int_t bufsize = 0;
01055       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!|O!i:TDirectory::WriteObject" ),
01056                &ObjectProxy_Type, &wrt, &PyROOT_PyUnicode_Type, &name,
01057                &PyROOT_PyUnicode_Type, &option, &bufsize ) )
01058          return 0;
01059 
01060       TDirectory* dir =
01061          (TDirectory*)self->ObjectIsA()->DynamicCast( TDirectory::Class(), self->GetObject() );
01062 
01063       if ( ! dir ) {
01064          PyErr_SetString( PyExc_TypeError,
01065            "TDirectory::WriteObject must be called with a TDirectory instance as first argument" );
01066          return 0;
01067       }
01068 
01069       Int_t result = 0;
01070       if ( option != 0 ) {
01071          result = dir->WriteObjectAny( wrt->GetObject(), wrt->ObjectIsA(),
01072             PyROOT_PyUnicode_AsString( name ), PyROOT_PyUnicode_AsString( option ), bufsize );
01073       } else {
01074          result = dir->WriteObjectAny(
01075             wrt->GetObject(), wrt->ObjectIsA(), PyROOT_PyUnicode_AsString( name ) );
01076       }
01077 
01078       return PyInt_FromLong( (Long_t)result );
01079    }
01080 
01081 }
01082 
01083 
01084 namespace PyROOT {      // workaround for Intel icc on Linux
01085 
01086 //- TTree behavior ------------------------------------------------------------
01087    PyObject* TTreeGetAttr( ObjectProxy* self, PyObject* pyname )
01088    {
01089    // allow access to branches/leaves as if they are data members
01090       const char* name = PyROOT_PyUnicode_AsString( pyname );
01091       if ( ! name )
01092          return 0;
01093 
01094    // get hold of actual tree
01095       TTree* tree =
01096          (TTree*)self->ObjectIsA()->DynamicCast( TTree::Class(), self->GetObject() );
01097 
01098       if ( ! tree ) {
01099          PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-pointer" );
01100          return 0;
01101       }
01102 
01103    // search for branch first (typical for objects)
01104       TBranch* branch = tree->GetBranch( name );
01105       if ( ! branch ) {
01106       // for benefit of naming of sub-branches, the actual name may have a trailing '.'
01107          branch = tree->GetBranch( (std::string( name ) + '.' ).c_str() );
01108       }
01109 
01110       if ( branch ) {
01111       // found a branched object, wrap its address for the object it represents
01112          TClass* klass = TClass::GetClass( branch->GetClassName() );
01113          if ( klass && branch->GetAddress() )
01114             return BindRootObjectNoCast( *(char**)branch->GetAddress(), klass );
01115       }
01116 
01117    // if not, try leaf
01118       TLeaf* leaf = tree->GetLeaf( name );
01119       if ( branch && ! leaf ) {
01120          leaf = branch->GetLeaf( name );
01121          if ( ! leaf ) {
01122             TObjArray* leaves = branch->GetListOfLeaves();
01123             if ( leaves->GetSize() && ( leaves->First() == leaves->Last() ) ) {
01124             // i.e., if unambiguously only this one
01125                leaf = (TLeaf*)leaves->At( 0 );
01126             }
01127          }
01128       }
01129 
01130       if ( leaf ) {
01131       // found a leaf, extract value and wrap
01132          if ( 1 < leaf->GetLenStatic() || leaf->GetLeafCount() ) {
01133          // array types
01134             std::string typeName = leaf->GetTypeName();
01135             TConverter* pcnv = CreateConverter( typeName + '*', leaf->GetNdata() );
01136             void* address = (void*)leaf->GetValuePointer();
01137             PyObject* value = pcnv->FromMemory( &address );
01138             delete pcnv;
01139 
01140             return value;
01141          } else {
01142          // value types
01143             TConverter* pcnv = CreateConverter( leaf->GetTypeName() );
01144             PyObject* value = pcnv->FromMemory( (void*)leaf->GetValuePointer() );
01145             delete pcnv;
01146 
01147             return value;
01148          }
01149       }
01150 
01151    // confused
01152       PyErr_Format( PyExc_AttributeError,
01153           "\'%s\' object has no attribute \'%s\'", tree->IsA()->GetName(), name );
01154       return 0;
01155    }
01156 
01157 //____________________________________________________________________________
01158    class TTreeMemberFunction : public PyCallable {
01159    protected:
01160       TTreeMemberFunction( MethodProxy* org ) { Py_INCREF( org ); fOrg = org; }
01161       TTreeMemberFunction( const TTreeMemberFunction& t ) : PyCallable( t )
01162       {
01163          Py_INCREF( t.fOrg );
01164          fOrg = t.fOrg;
01165       }
01166       TTreeMemberFunction& operator=( const TTreeMemberFunction& t )
01167       {
01168          if ( &t != this ) {
01169             Py_INCREF( t.fOrg );
01170             fOrg = t.fOrg;
01171          }
01172          return *this;
01173       }
01174       ~TTreeMemberFunction() { Py_DECREF( fOrg ); fOrg = 0; }
01175 
01176    public:
01177       virtual PyObject* GetSignature() { return PyROOT_PyUnicode_FromString( "(...)" ); }
01178       virtual PyObject* GetPrototype() { return PyObject_GetAttrString( (PyObject*)fOrg, (char*)"__doc__" ); }
01179       virtual PyObject* GetScope()
01180       {
01181          return MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( "TTree" );
01182       }
01183 
01184    protected:
01185       MethodProxy* fOrg;
01186    };
01187 
01188 //____________________________________________________________________________
01189    class TTreeBranch : public TTreeMemberFunction {
01190    public:
01191       TTreeBranch( MethodProxy* org ) : TTreeMemberFunction( org ) {}
01192 
01193    public:
01194       virtual PyCallable* Clone() { return new TTreeBranch( *this ); }
01195 
01196       virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject* kwds, Long_t )
01197       {
01198       // acceptable signatures:
01199       //   ( const char*, void*, const char*, Int_t = 32000 )
01200       //   ( const char*, const char*, T**, Int_t = 32000, Int_t = 99 )
01201       //   ( const char*, T**, Int_t = 32000, Int_t = 99 ) 
01202          int argc = PyTuple_GET_SIZE( args );
01203 
01204          if ( 2 <= argc ) {
01205             TTree* tree =
01206                (TTree*)self->ObjectIsA()->DynamicCast( TTree::Class(), self->GetObject() );
01207 
01208             if ( ! tree ) {
01209                PyErr_SetString( PyExc_TypeError,
01210                   "TTree::Branch must be called with a TTree instance as first argument" );
01211                return 0;
01212             }
01213 
01214             PyObject *name = 0, *clName = 0, *leaflist = 0;
01215             PyObject *address = 0;
01216             PyObject *bufsize = 0, *splitlevel = 0;
01217 
01218          // try: ( const char*, void*, const char*, Int_t = 32000 )
01219             if ( PyArg_ParseTuple( args, const_cast< char* >( "O!OO!|O!:Branch" ),
01220                    &PyROOT_PyUnicode_Type, &name, &address, &PyROOT_PyUnicode_Type,
01221                    &leaflist, &PyInt_Type, &bufsize ) ) {
01222 
01223                void* buf = 0;
01224                if ( ObjectProxy_Check( address ) )
01225                   buf = (void*)((ObjectProxy*)address)->GetObject();
01226                else
01227                   Utility::GetBuffer( address, '*', 1, buf, kFALSE );
01228  
01229                if ( buf != 0 ) {
01230                   TBranch* branch = 0;
01231                   if ( argc == 4 ) {
01232                      branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), buf,
01233                         PyROOT_PyUnicode_AsString( leaflist ), PyInt_AS_LONG( bufsize ) );
01234                   } else {
01235                      branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), buf,
01236                         PyROOT_PyUnicode_AsString( leaflist ) );
01237                   }
01238 
01239                   return BindRootObject( branch, TBranch::Class() );
01240                }
01241 
01242             }
01243             PyErr_Clear();
01244 
01245          // try: ( const char*, const char*, T**, Int_t = 32000, Int_t = 99 )
01246          //  or: ( const char*,              T**, Int_t = 32000, Int_t = 99 ) 
01247             Bool_t bIsMatch = kFALSE;
01248             if ( PyArg_ParseTuple( args, const_cast< char* >( "O!O!O|O!O!:Branch" ),
01249                    &PyROOT_PyUnicode_Type, &name, &PyROOT_PyUnicode_Type, &clName, &address,
01250                    &PyInt_Type, &bufsize, &PyInt_Type, &splitlevel ) ) {
01251                bIsMatch = kTRUE;
01252             } else {
01253                PyErr_Clear(); clName = 0;    // clName no longer used
01254                if ( PyArg_ParseTuple( args, const_cast< char* >( "O!O|O!O!" ),
01255                       &PyROOT_PyUnicode_Type, &name, &address,
01256                       &PyInt_Type, &bufsize, &PyInt_Type, &splitlevel ) ) {
01257                   bIsMatch = kTRUE;
01258                } else
01259                   PyErr_Clear();
01260             }
01261 
01262             if ( bIsMatch == kTRUE ) {
01263                std::string klName = clName ? PyROOT_PyUnicode_AsString( clName ) : "";
01264                void* buf = 0;
01265 
01266                if ( ObjectProxy_Check( address ) ) {
01267                   if ( ((ObjectProxy*)address)->fFlags & ObjectProxy::kIsReference )
01268                      buf = (void*)((ObjectProxy*)address)->fObject;
01269                   else
01270                      buf = (void*)&((ObjectProxy*)address)->fObject;
01271 
01272                   if ( ! clName ) {
01273                      klName = ((ObjectProxy*)address)->ObjectIsA()->GetName();
01274                      argc += 1;
01275                   }
01276                } else
01277                   Utility::GetBuffer( address, '*', 1, buf, kFALSE );
01278 
01279                if ( buf != 0 && klName != "" ) {
01280                   TBranch* branch = 0;
01281                   if ( argc == 3 ) {
01282                      branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), klName.c_str(), buf );
01283                   } else if ( argc == 4 ) {
01284                      branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), klName.c_str(), buf,
01285                         PyInt_AS_LONG( bufsize ) );
01286                   } else if ( argc == 5 ) {
01287                      branch = tree->Branch( PyROOT_PyUnicode_AsString( name ), klName.c_str(), buf,
01288                         PyInt_AS_LONG( bufsize ), PyInt_AS_LONG( splitlevel ) );
01289                   }
01290 
01291                   return BindRootObject( branch, TBranch::Class() );
01292                }
01293             }
01294          }
01295 
01296       // still here? Then call original Branch() to reach the other overloads:
01297          Py_INCREF( (PyObject*)self );
01298          fOrg->fSelf = self;
01299          PyObject* result = PyObject_Call( (PyObject*)fOrg, args, kwds );
01300          fOrg->fSelf = 0;
01301          Py_DECREF( (PyObject*)self );
01302 
01303          return result;
01304       }
01305    };
01306 
01307 //____________________________________________________________________________
01308    class TTreeSetBranchAddress : public TTreeMemberFunction {
01309    public:
01310       TTreeSetBranchAddress( MethodProxy* org ) : TTreeMemberFunction( org ) {}
01311 
01312    public:
01313       virtual PyObject* GetPrototype()
01314       {
01315          return PyROOT_PyUnicode_FromString( "TBranch* TTree::SetBranchAddress( ... )" );
01316       }
01317 
01318       virtual PyCallable* Clone() { return new TTreeSetBranchAddress( *this ); }
01319 
01320       virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject* kwds, Long_t )
01321       {
01322       // acceptable signature:
01323       //   ( const char*, void* )
01324          int argc = PyTuple_GET_SIZE( args );
01325 
01326          if ( 2 == argc ) {
01327             TTree* tree =
01328                (TTree*)self->ObjectIsA()->DynamicCast( TTree::Class(), self->GetObject() );
01329 
01330             if ( ! tree ) {
01331                PyErr_SetString( PyExc_TypeError,
01332                   "TTree::SetBranchAddress must be called with a TTree instance as first argument" );
01333                return 0;
01334             }
01335 
01336             PyObject *name = 0, *address = 0;
01337 
01338          // try: ( const char*, void* )
01339             if ( PyArg_ParseTuple( args, const_cast< char* >( "SO:SetBranchAddress" ),
01340                     &name, &address ) ) {
01341 
01342                void* buf = 0;
01343                if ( ObjectProxy_Check( address ) ) {
01344                   if ( ((ObjectProxy*)address)->fFlags & ObjectProxy::kIsReference )
01345                      buf = (void*)((ObjectProxy*)address)->fObject;
01346                   else
01347                      buf = (void*)&((ObjectProxy*)address)->fObject;
01348                } else
01349                   Utility::GetBuffer( address, '*', 1, buf, kFALSE );
01350 
01351                if ( buf != 0 ) {
01352                   tree->SetBranchAddress( PyROOT_PyUnicode_AsString( name ), buf );
01353 
01354                   Py_INCREF( Py_None );
01355                   return Py_None;
01356                }
01357             }
01358          }
01359 
01360       // still here? Then call original Branch() to reach the other overloads:
01361          Py_INCREF( (PyObject*)self );
01362          fOrg->fSelf = self;
01363          PyObject* result = PyObject_Call( (PyObject*)fOrg, args, kwds );
01364          fOrg->fSelf = 0;
01365          Py_DECREF( (PyObject*)self );
01366 
01367          return result;
01368       }
01369 
01370    protected:
01371       virtual PyObject* ReportTypeError()
01372       {
01373          PyErr_SetString( PyExc_TypeError,
01374             "TTree::SetBranchAddress must be called with a TTree instance as first argument" );
01375          return 0;
01376       }
01377    };
01378 
01379 
01380 // TChain overrides TTree's SetBranchAddress, so set it again (the python method only forwards
01381 //   onto a TTree*, so the C++ virtual function call will make sure the right method is used)
01382    class TChainSetBranchAddress : public TTreeSetBranchAddress {
01383    public:
01384       TChainSetBranchAddress( MethodProxy* org ) : TTreeSetBranchAddress( org ) {}
01385 
01386    public:
01387       virtual PyObject* GetPrototype()
01388       {
01389          return PyROOT_PyUnicode_FromString( "TBranch* TChain::SetBranchAddress( ... )" );
01390       }
01391 
01392       virtual PyCallable* Clone() { return new TChainSetBranchAddress( *this ); }
01393 
01394    protected:
01395       virtual PyObject* ReportTypeError()
01396       {
01397          PyErr_SetString( PyExc_TypeError,
01398             "TChain::SetBranchAddress must be called with a TChain instance as first argument" );
01399          return 0;
01400       }
01401    };
01402 
01403 } // namespace PyROOT
01404 
01405 
01406 namespace {
01407 
01408 // for convenience
01409    using namespace PyROOT;
01410 
01411 //- THN behavior --------------------------------------------------------------
01412    PyObject* THNIMul( PyObject* self, PyObject* scale )
01413    {
01414    // Use THN::Scale to perform *= ... need this stub to return self
01415       PyObject* result = CallPyObjMethod( self, "Scale", scale );
01416       if ( ! result )
01417          return result;
01418 
01419       Py_DECREF( result );
01420       Py_INCREF( self );
01421       return self;
01422    }
01423 
01424 //- TFN behavior --------------------------------------------------------------
01425    int TFNPyCallback( G__value* res, G__CONST char*, struct G__param* libp, int hash )
01426    {
01427       PyObject* result = 0;
01428 
01429    // retrieve function information
01430       Long_t npar = 0;
01431       PyObject* pyfunc = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res), &npar );
01432       if ( ! pyfunc )
01433          return 0;
01434 
01435    // prepare arguments and call
01436       PyObject* arg1 = BufFac_t::Instance()->PyBuffer_FromMemory(
01437          (double*)G__int(libp->para[0]), 4 );
01438       if ( ! arg1 )
01439          return 0;
01440 
01441       if ( npar != 0 ) {
01442          PyObject* arg2 = BufFac_t::Instance()->PyBuffer_FromMemory(
01443             (double*)G__int(libp->para[1]), npar );
01444          result = PyObject_CallFunction( pyfunc, (char*)"OO", arg1, arg2 );
01445          Py_DECREF( arg2 );
01446       } else
01447          result = PyObject_CallFunction( pyfunc, (char*)"O", arg1 );
01448 
01449       Py_DECREF( arg1 );
01450 
01451    // translate result, throw if an error has occurred
01452       double d = 0.;
01453       if ( ! result ) {
01454          PyErr_Print();
01455          throw std::runtime_error( "TFN python function call failed" );
01456       } else {
01457          d = PyFloat_AsDouble( result );
01458          Py_DECREF( result );
01459       }
01460 
01461       G__letdouble( res, 100, d );
01462       return ( 1 || hash || res || libp );
01463    }
01464 
01465 //- TMinuit behavior ----------------------------------------------------------
01466    int TMinuitPyCallback( G__value* res, G__CONST char*, struct G__param* libp, int hash )
01467    {
01468       PyObject* result = 0;
01469 
01470    // retrieve function information
01471       PyObject* pyfunc = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res) );
01472       if ( ! pyfunc )
01473          return 0;
01474 
01475    // prepare arguments
01476       PyObject* arg1 = BufFac_t::Instance()->PyBuffer_FromMemory(
01477          (Int_t*)G__int(libp->para[0]), 1 );
01478       int npar = G__int(libp->para[0]);
01479  
01480       PyObject* arg2 = BufFac_t::Instance()->PyBuffer_FromMemory(
01481          (Double_t*)G__int(libp->para[1]), npar );
01482 
01483       PyObject* arg3 = PyList_New( 1 );
01484       PyList_SetItem( arg3, 0, PyFloat_FromDouble( G__double(libp->para[2]) ) );
01485 
01486       PyObject* arg4 = BufFac_t::Instance()->PyBuffer_FromMemory(
01487          (Double_t*)G__int(libp->para[3]), npar );
01488 
01489    // perform actual call
01490       result = PyObject_CallFunction( pyfunc, (char*)"OOOOi",
01491          arg1, arg2, arg3, arg4, (int)G__int(libp->para[4]) );
01492       *(Double_t*)G__Doubleref(&libp->para[2]) = PyFloat_AsDouble( PyList_GetItem( arg3, 0 ) );
01493 
01494       Py_DECREF( arg4 ); Py_DECREF( arg3 ); Py_DECREF( arg2 ); Py_DECREF( arg1 );
01495 
01496       if ( ! result ) {
01497          PyErr_Print();
01498          throw std::runtime_error( "TMinuit python fit function call failed" );
01499       }
01500 
01501       Py_XDECREF( result );
01502 
01503       G__setnull( res );
01504       return ( 1 || hash || res || libp );
01505    }
01506 
01507 //____________________________________________________________________________
01508    class TPretendInterpreted: public PyCallable {
01509    public:
01510       TPretendInterpreted( int nArgs ) : fNArgs( nArgs ) {}
01511 
01512    public:
01513       Int_t GetNArgs() { return fNArgs; }
01514 
01515       Bool_t IsCallable( PyObject* pyobject )
01516       {
01517          if ( ! pyobject || ! PyCallable_Check( pyobject ) ) {
01518             PyObject* str = pyobject ? PyObject_Str( pyobject ) : PyROOT_PyUnicode_FromString( "null pointer" );
01519             PyErr_Format( PyExc_ValueError,
01520                "\"%s\" is not a valid python callable", PyROOT_PyUnicode_AsString( str ) );
01521             Py_DECREF( str );
01522             return kFALSE;
01523          }
01524 
01525          return kTRUE;
01526       }
01527 
01528    private:
01529       Int_t fNArgs;
01530    };
01531 
01532 //____________________________________________________________________________
01533    class TF1InitWithPyFunc : public TPretendInterpreted {
01534       typedef std::pair< PyObject*, int > pairPyObjInt_t;
01535 
01536    public:
01537       TF1InitWithPyFunc( int ntf = 1 ) : TPretendInterpreted( 2 + 2*ntf ) {}
01538 
01539    public:
01540       virtual PyObject* GetSignature() { return PyROOT_PyUnicode_FromString( "(...)" ); }
01541       virtual PyObject* GetPrototype()
01542       {
01543          return PyROOT_PyUnicode_FromString(
01544             "TF1::TF1(const char* name, PyObject* callable, "
01545             "Double_t xmin, Double_t xmax, Int_t npar = 0)" );
01546       }
01547 
01548       virtual PyCallable* Clone() { return new TF1InitWithPyFunc( *this ); }
01549 
01550       virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject*, Long_t )
01551       {
01552       // expected signature: ( char* name, pyfunc, double xmin, double xmax, int npar = 0 )
01553          int argc = PyTuple_GET_SIZE( args );
01554          const int reqNArgs = GetNArgs();
01555          if ( ! ( argc == reqNArgs || argc == reqNArgs+1 ) ) {
01556             PyErr_Format( PyExc_TypeError,
01557                "TFN::TFN(const char*, PyObject* callable, ...) =>\n"
01558                "    takes at least %d and at most %d arguments (%d given)",
01559                reqNArgs, reqNArgs+1, argc );
01560             return 0;              // reported as an overload failure
01561          }
01562 
01563          PyObject* pyfunc = PyTuple_GET_ITEM( args, 1 );
01564          if ( ! IsCallable( pyfunc ) )
01565             return 0;
01566 
01567       // use requested function name as identifier
01568          const char* name = PyROOT_PyUnicode_AsString( PyTuple_GET_ITEM( args, 0 ) );
01569          if ( PyErr_Occurred() )
01570             return 0;
01571 
01572       // verify/setup the callback parameters
01573          Long_t npar = 0;             // default value if not given
01574          if ( argc == reqNArgs+1 )
01575             npar = PyInt_AsLong( PyTuple_GET_ITEM( args, reqNArgs ) );
01576 
01577       // registration with CINT
01578          Long_t fid = Utility::InstallMethod(
01579             0, pyfunc, name, 0, "D - - 0 - - D - - 0 - -", (void*)TFNPyCallback, 2, npar );
01580 
01581       // get constructor
01582          MethodProxy* method =
01583             (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gInit );
01584 
01585       // build new argument array
01586          PyObject* newArgs = PyTuple_New( reqNArgs + 1 );
01587 
01588          for ( int iarg = 0; iarg < argc; ++iarg ) {
01589             PyObject* item = PyTuple_GET_ITEM( args, iarg );
01590             if ( iarg != 1 ) {
01591                Py_INCREF( item );
01592                PyTuple_SET_ITEM( newArgs, iarg, item );
01593             } else {
01594                PyTuple_SET_ITEM( newArgs, iarg, PyCObject_FromVoidPtr( (void*)fid, NULL ) );
01595             }
01596          }
01597 
01598          if ( argc == reqNArgs )             // meaning: use default for last value
01599             PyTuple_SET_ITEM( newArgs, reqNArgs, PyInt_FromLong( 0l ) );
01600 
01601       // re-run
01602          PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
01603 
01604       // done, may have worked, if not: 0 is returned
01605          Py_DECREF( newArgs );
01606          Py_DECREF( method );
01607          return result;
01608       }
01609    };
01610 
01611 //____________________________________________________________________________
01612    class TF2InitWithPyFunc : public TF1InitWithPyFunc {
01613    public:
01614       TF2InitWithPyFunc() : TF1InitWithPyFunc( 2 ) {}
01615 
01616    public:
01617       virtual PyObject* GetPrototype()
01618       {
01619          return PyROOT_PyUnicode_FromString(
01620             "TF2::TF2(const char* name, PyObject* callable, "
01621             "Double_t xmin, Double_t xmax, "
01622             "Double_t ymin, Double_t ymax, Int_t npar = 0)" );
01623       }
01624 
01625       virtual PyCallable* Clone() { return new TF2InitWithPyFunc( *this ); }
01626    };
01627 
01628 //____________________________________________________________________________
01629    class TF3InitWithPyFunc : public TF1InitWithPyFunc {
01630    public:
01631       TF3InitWithPyFunc() : TF1InitWithPyFunc( 3 ) {}
01632 
01633    public:
01634       virtual PyObject* GetPrototype()
01635       {
01636          return PyROOT_PyUnicode_FromString(
01637             "TF3::TF3(const char* name, PyObject* callable, "
01638             "Double_t xmin, Double_t xmax, "
01639             "Double_t ymin, Double_t ymax, "
01640             "Double_t zmin, Double_t zmax, Int_t npar = 0)" );
01641       }
01642 
01643       virtual PyCallable* Clone() { return new TF3InitWithPyFunc( *this ); }
01644    };
01645 
01646 
01647 //- TFunction behavior ---------------------------------------------------------
01648    PyObject* TFunctionCall( ObjectProxy* self, PyObject* args ) {
01649       return TFunctionHolder< TScopeAdapter, TMemberAdapter >( (TFunction*)self->GetObject() )( self, args, 0 );
01650    }
01651 
01652 
01653 //- TMinuit behavior -----------------------------------------------------------
01654    class TMinuitSetFCN : public TPretendInterpreted {
01655    public:
01656       TMinuitSetFCN() : TPretendInterpreted( 1 ) {}
01657 
01658    public:
01659       virtual PyObject* GetSignature() { return PyROOT_PyUnicode_FromString( "(PyObject* callable)" ); }
01660       virtual PyObject* GetPrototype()
01661       {
01662          return PyROOT_PyUnicode_FromString(
01663             "TMinuit::SetFCN(PyObject* callable)" );
01664       }
01665 
01666       virtual PyCallable* Clone() { return new TMinuitSetFCN( *this ); }
01667 
01668       virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject*, Long_t )
01669       {
01670       // expected signature: ( pyfunc )
01671          int argc = PyTuple_GET_SIZE( args );
01672          if ( argc != 1 ) {
01673             PyErr_Format( PyExc_TypeError,
01674                "TMinuit::SetFCN(PyObject* callable, ...) =>\n"
01675                "    takes exactly 1 argument (%d given)", argc );
01676             return 0;              // reported as an overload failure
01677          }
01678 
01679          PyObject* pyfunc = PyTuple_GET_ITEM( args, 0 );
01680          if ( ! IsCallable( pyfunc ) )
01681             return 0;
01682 
01683       // use callable name (if available) as identifier
01684          PyObject* pyname = PyObject_GetAttr( pyfunc, PyStrings::gName );
01685          const char* name = "dummy";
01686          if ( pyname != 0 )
01687             name = PyROOT_PyUnicode_AsString( pyname );
01688 
01689       // registration with CINT
01690          Long_t fid = Utility::InstallMethod( 0, pyfunc, name, 0,
01691             "i - - 1 - - D - - 0 - - d - - 1 - - D - - 0 - - i - - 0 - -",
01692             (void*)TMinuitPyCallback, 5 );
01693          Py_XDECREF( pyname );
01694 
01695       // get function
01696          MethodProxy* method =
01697             (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gSetFCN );
01698 
01699       // build new argument array
01700          PyObject* newArgs = PyTuple_New( 1 );
01701          PyTuple_SET_ITEM( newArgs, 0, PyCObject_FromVoidPtr( (void*)fid, NULL ) );
01702 
01703       // re-run
01704          PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
01705 
01706       // done, may have worked, if not: 0 is returned
01707          Py_DECREF( newArgs );
01708          Py_DECREF( method );
01709          return result;
01710       }
01711    };
01712 
01713 
01714 //- Fit::TFitter behavior ------------------------------------------------------
01715    PyObject* gFitterPyCallback = 0;
01716 
01717    void FitterPyCallback( int& npar, double* gin, double& f, double* u, int flag )
01718    {
01719       PyObject* result = 0;
01720 
01721    // prepare arguments
01722       PyObject* arg1 = BufFac_t::Instance()->PyBuffer_FromMemory( &npar );
01723 
01724       PyObject* arg2 = BufFac_t::Instance()->PyBuffer_FromMemory( gin );
01725 
01726       PyObject* arg3 = PyList_New( 1 );
01727       PyList_SetItem( arg3, 0, PyFloat_FromDouble( f ) );
01728 
01729       PyObject* arg4 = BufFac_t::Instance()->PyBuffer_FromMemory( u, npar );
01730 
01731    // perform actual call
01732       result = PyObject_CallFunction(
01733          gFitterPyCallback, (char*)"OOOOi", arg1, arg2, arg3, arg4, flag );
01734       f = PyFloat_AsDouble( PyList_GetItem( arg3, 0 ) );
01735 
01736       Py_DECREF( arg4 ); Py_DECREF( arg3 ); Py_DECREF( arg2 ); Py_DECREF( arg1 );
01737 
01738       if ( ! result ) {
01739          PyErr_Print();
01740          throw std::runtime_error( "TMinuit python fit function call failed" );
01741       }
01742 
01743       Py_XDECREF( result );
01744    }
01745 
01746 
01747    class TFitterFitFCN : public TPretendInterpreted {
01748    public:
01749       TFitterFitFCN() : TPretendInterpreted( 2 ) {}
01750 
01751    public:
01752       virtual PyObject* GetSignature()
01753       {
01754          return PyROOT_PyUnicode_FromString(
01755             "(PyObject* callable, int npar = 0, const double* params = 0, unsigned int dataSize = 0, bool chi2fit = false)" );
01756       }
01757 
01758       virtual PyObject* GetPrototype()
01759       {
01760          return PyROOT_PyUnicode_FromString(
01761             "TFitter::FitFCN(PyObject* callable, int npar = 0, const double* params = 0, unsigned int dataSize = 0, bool chi2fit = false)" );
01762       }
01763 
01764       virtual PyCallable* Clone() { return new TFitterFitFCN( *this ); }
01765 
01766       virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject*, Long_t )
01767       {
01768       // expected signature: ( self, pyfunc, int npar = 0, const double* params = 0, unsigned int dataSize = 0, bool chi2fit = false )
01769          int argc = PyTuple_GET_SIZE( args );
01770          if ( argc < 1 ) {
01771             PyErr_Format( PyExc_TypeError,
01772                "TFitter::FitFCN(PyObject* callable, ...) =>\n"
01773                "    takes at least 1 argument (%d given)", argc );
01774             return 0;              // reported as an overload failure
01775          }
01776 
01777          PyObject* pyfunc = PyTuple_GET_ITEM( args, 0 );
01778          if ( ! IsCallable( pyfunc ) )
01779             return 0;
01780 
01781       // global registration
01782          Py_XDECREF( gFitterPyCallback );
01783          Py_INCREF( pyfunc );
01784          gFitterPyCallback = pyfunc;
01785 
01786       // get function
01787          MethodProxy* method =
01788             (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gFitFCN );
01789 
01790       // build new argument array
01791          PyObject* newArgs = PyTuple_New( argc );
01792          PyTuple_SET_ITEM( newArgs, 0, PyCObject_FromVoidPtr( (void*)FitterPyCallback, NULL ) );
01793          for ( int iarg = 1; iarg < argc; ++iarg ) {
01794             PyObject* pyarg = PyTuple_GET_ITEM( args, iarg );
01795             Py_INCREF( pyarg );
01796             PyTuple_SET_ITEM( newArgs, iarg, pyarg );
01797          }
01798 
01799       // re-run
01800          PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
01801 
01802       // done, may have worked, if not: 0 is returned
01803          Py_DECREF( newArgs );
01804          Py_DECREF( method );
01805          return result;
01806       }
01807    };
01808 
01809 
01810 //- simplistic len() functions -------------------------------------------------
01811    PyObject* ReturnThree( ObjectProxy*, PyObject* ) {
01812       return PyInt_FromLong( 3 );
01813    }
01814 
01815    PyObject* ReturnTwo( ObjectProxy*, PyObject* ) {
01816       return PyInt_FromLong( 2 );
01817    }
01818 
01819 } // unnamed namespace
01820 
01821 
01822 //- public functions -----------------------------------------------------------
01823 Bool_t PyROOT::Pythonize( PyObject* pyclass, const std::string& name )
01824 {
01825    if ( pyclass == 0 )
01826       return kFALSE;
01827 
01828 //- method name based pythonization --------------------------------------------
01829 
01830 // for smart pointer style classes (note fall-through)
01831    if ( HasAttrDirect( pyclass, PyStrings::gDeref ) ) {
01832       Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) DeRefGetAttr, METH_O );
01833    } else if ( HasAttrDirect( pyclass, PyStrings::gFollow ) ) {
01834       Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) FollowGetAttr, METH_O );
01835    }
01836 
01837 // for STL containers, and user classes modeled after them
01838    if ( HasAttrDirect( pyclass, PyStrings::gSize ) )
01839       Utility::AddToClass( pyclass, "__len__", "size" );
01840 
01841    if ( HasAttrDirect( pyclass, PyStrings::gBegin ) && HasAttrDirect( pyclass, PyStrings::gEnd ) ) {
01842    // some classes may not have dicts for their iterators, making begin/end useless
01843       PyObject* pyfullname = PyObject_GetAttr( pyclass, PyStrings::gName );
01844       TClass* klass = TClass::GetClass( PyROOT_PyUnicode_AsString( pyfullname ) );
01845       Py_DECREF( pyfullname );
01846       TMethod* meth = klass->GetMethodAllAny( "begin" );
01847 
01848       TClass* iklass = 0;
01849       if ( meth ) {
01850          Int_t oldl = gErrorIgnoreLevel; gErrorIgnoreLevel = 3000;
01851          iklass = TClass::GetClass( meth->GetReturnTypeName() );
01852          gErrorIgnoreLevel = oldl;
01853       }
01854 
01855       if ( iklass && iklass->GetClassInfo() ) {
01856          ((PyTypeObject*)pyclass)->tp_iter     = (getiterfunc)StlSequenceIter;
01857          Utility::AddToClass( pyclass, "__iter__", (PyCFunction) StlSequenceIter, METH_NOARGS );
01858       } else if ( HasAttrDirect( pyclass, PyStrings::gGetItem ) && HasAttrDirect( pyclass, PyStrings::gLen ) ) {
01859          Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
01860          Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
01861       }
01862    }
01863 
01864 // search for global comparator overloads (may fail; not sure whether it isn't better to
01865 // do this lazily just as is done for math operators, but this interplays nicely with the
01866 // generic versions)
01867    Utility::AddBinaryOperator( pyclass, "==", "__eq__" ); 
01868    Utility::AddBinaryOperator( pyclass, "!=", "__ne__" );
01869 
01870 // map operator==() through GenObjectIsEqual to allow comparison to None (kTRUE is to
01871 // require that the located method is a MethodProxy; this prevents circular calls as
01872 // GenObjectIsEqual is no MethodProxy)
01873    if ( HasAttrDirect( pyclass, PyStrings::gEq, kTRUE ) ) {
01874       Utility::AddToClass( pyclass, "__cpp_eq__",  "__eq__" );
01875       Utility::AddToClass( pyclass, "__eq__",  (PyCFunction) GenObjectIsEqual, METH_O );
01876    }
01877 
01878 // map operator!=() through GenObjectIsNotEqual to allow comparison to None (see note
01879 // on kTRUE above for __eq__)
01880    if ( HasAttrDirect( pyclass, PyStrings::gNe, kTRUE ) ) {
01881       Utility::AddToClass( pyclass, "__cpp_ne__",  "__ne__" );
01882       Utility::AddToClass( pyclass, "__ne__",  (PyCFunction) GenObjectIsNotEqual, METH_O );
01883    }
01884 
01885 
01886 //- class name based pythonization ---------------------------------------------
01887 
01888    if ( name == "TObject" ) {
01889    // support for the 'in' operator
01890       Utility::AddToClass( pyclass, "__contains__", (PyCFunction) TObjectContains, METH_O );
01891 
01892    // comparing for lists
01893       Utility::AddToClass( pyclass, "__cmp__", (PyCFunction) TObjectCompare, METH_O );
01894       Utility::AddToClass( pyclass, "__eq__",  (PyCFunction) TObjectIsEqual, METH_O );
01895       Utility::AddToClass( pyclass, "__ne__",  (PyCFunction) TObjectIsNotEqual, METH_O );
01896 
01897       return kTRUE;
01898    }
01899 
01900    if ( name == "TClass" ) {
01901    // make DynamicCast return a usable python object, rather than void*
01902       Utility::AddToClass( pyclass, "_TClass__DynamicCast", "DynamicCast" );
01903       Utility::AddToClass( pyclass, "DynamicCast", (PyCFunction) TClassDynamicCast );
01904 
01905    // the following cast is easier to use (reads both ways)
01906       Utility::AddToClass( pyclass, "StaticCast", (PyCFunction) TClassStaticCast );
01907 
01908       return kTRUE;
01909    }
01910 
01911    if ( name == "TCollection" ) {
01912       Utility::AddToClass( pyclass, "append",   "Add" );
01913       Utility::AddToClass( pyclass, "extend",   (PyCFunction) TCollectionExtend, METH_O );
01914       Utility::AddToClass( pyclass, "remove",   (PyCFunction) TCollectionRemove, METH_O );
01915       Utility::AddToClass( pyclass, "__add__",  (PyCFunction) TCollectionAdd, METH_O );
01916       Utility::AddToClass( pyclass, "__imul__", (PyCFunction) TCollectionIMul, METH_O );
01917       Utility::AddToClass( pyclass, "__mul__",  (PyCFunction) TCollectionMul, METH_O );
01918       Utility::AddToClass( pyclass, "__rmul__", (PyCFunction) TCollectionMul, METH_O );
01919 
01920       Utility::AddToClass( pyclass, "count", (PyCFunction) TCollectionCount, METH_O );
01921 
01922       Utility::AddToClass( pyclass, "__len__",  "GetSize" );
01923       ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)TCollectionIter;
01924       Utility::AddToClass( pyclass, "__iter__",  (PyCFunction)TCollectionIter, METH_NOARGS );
01925 
01926       return kTRUE;
01927    }
01928 
01929    if ( name == "TSeqCollection" ) {
01930       Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) TSeqCollectionGetItem, METH_O );
01931       Utility::AddToClass( pyclass, "__setitem__", (PyCFunction) TSeqCollectionSetItem );
01932       Utility::AddToClass( pyclass, "__delitem__", (PyCFunction) TSeqCollectionDelItem, METH_O );
01933 
01934       Utility::AddToClass( pyclass, "insert",  (PyCFunction) TSeqCollectionInsert );
01935       Utility::AddToClass( pyclass, "pop",     (PyCFunction) TSeqCollectionPop );
01936       Utility::AddToClass( pyclass, "reverse", (PyCFunction) TSeqCollectionReverse, METH_NOARGS );
01937       Utility::AddToClass( pyclass, "sort",    (PyCFunction) TSeqCollectionSort,
01938                            METH_VARARGS | METH_KEYWORDS );
01939 
01940       Utility::AddToClass( pyclass, "index", (PyCFunction) TSeqCollectionIndex, METH_O );
01941 
01942       return kTRUE;
01943    }
01944 
01945    if ( name == "TClonesArray" ) {
01946    // restore base TSeqCollection operator[] to prevent random object creation (it's
01947    // functionality is equivalent to the operator[](int) const of TClonesArray, but
01948    // there's no guarantee it'll be selected over the non-const version)
01949       Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) TSeqCollectionGetItem, METH_O );
01950 
01951    // this setitem should be used with as much care as the C++ one
01952       Utility::AddToClass( pyclass, "__setitem__", (PyCFunction) TClonesArraySetItem );
01953 
01954       return kTRUE;
01955    }
01956 
01957    if ( IsTemplatedSTLClass( name, "vector" ) ) {
01958 
01959       if ( HasAttrDirect( pyclass, PyStrings::gLen ) ) {
01960          Utility::AddToClass( pyclass, "_vector__at", "at" );
01961       // remove iterator that was set earlier (checked __getitem__ will do the trick)
01962          if ( HasAttrDirect( pyclass, PyStrings::gIter ) )
01963             PyObject_DelAttr( pyclass, PyStrings::gIter );
01964       } else if ( HasAttrDirect( pyclass, PyStrings::gGetItem ) ) {
01965          Utility::AddToClass( pyclass, "_vector__at", "__getitem__" );   // unchecked!
01966       // if unchecked getitem, use checked iterator protocol (was set above if begin/end)
01967       }
01968 
01969    // provide a slice-able __getitem__, if possible
01970       if ( HasAttrDirect( pyclass, PyStrings::gVectorAt ) )
01971          Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) VectorGetItem, METH_O );
01972 
01973       return kTRUE;
01974    }
01975 
01976    if ( IsTemplatedSTLClass( name, "map" ) ) {
01977       Utility::AddToClass( pyclass, "__contains__", (PyCFunction) MapContains, METH_O );
01978 
01979       return kTRUE;
01980    }
01981 
01982    if ( IsTemplatedSTLClass( name, "pair" ) ) {
01983       Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) PairUnpack, METH_O );
01984       Utility::AddToClass( pyclass, "__len__", (PyCFunction) ReturnTwo, METH_NOARGS );
01985 
01986       return kTRUE;
01987    }
01988 
01989    if ( name.find( "iterator" ) != std::string::npos ) {
01990       ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)StlIterNext;
01991       Utility::AddToClass( pyclass, "next", (PyCFunction) StlIterNext, METH_NOARGS );
01992 
01993    // special case, if operator== is a global overload and included in the dictionary
01994       if ( ! HasAttrDirect( pyclass, PyStrings::gCppEq, kTRUE ) )
01995          Utility::AddToClass( pyclass, "__eq__",  (PyCFunction) StlIterIsEqual, METH_O );
01996       if ( ! HasAttrDirect( pyclass, PyStrings::gCppNe, kTRUE ) )
01997          Utility::AddToClass( pyclass, "__ne__",  (PyCFunction) StlIterIsNotEqual, METH_O );
01998 
01999       return kTRUE;
02000    }
02001 
02002    if ( name == "string" || name == "std::string" ) {
02003       Utility::AddToClass( pyclass, "__repr__", (PyCFunction) StlStringRepr, METH_NOARGS );
02004       Utility::AddToClass( pyclass, "__str__", "c_str" );
02005       Utility::AddToClass( pyclass, "__cmp__", (PyCFunction) StlStringCompare, METH_O );
02006       Utility::AddToClass( pyclass, "__eq__",  (PyCFunction) StlStringIsEqual, METH_O );
02007       Utility::AddToClass( pyclass, "__ne__",  (PyCFunction) StlStringIsNotEqual, METH_O );
02008 
02009       return kTRUE;
02010    }
02011 
02012    if ( name == "TString" ) {
02013       Utility::AddToClass( pyclass, "__repr__", (PyCFunction) TStringRepr, METH_NOARGS );
02014       Utility::AddToClass( pyclass, "__str__", "Data" );
02015       Utility::AddToClass( pyclass, "__len__", "Length" );
02016 
02017       Utility::AddToClass( pyclass, "__cmp__", "CompareTo" );
02018       Utility::AddToClass( pyclass, "__eq__",  (PyCFunction) TStringIsEqual, METH_O );
02019       Utility::AddToClass( pyclass, "__ne__",  (PyCFunction) TStringIsNotEqual, METH_O );
02020 
02021       return kTRUE;
02022    }
02023 
02024    if ( name == "TObjString" ) {
02025       Utility::AddToClass( pyclass, "__repr__", (PyCFunction) TObjStringRepr, METH_NOARGS );
02026       Utility::AddToClass( pyclass, "__str__",  "GetName" );
02027       Utility::AddToClass( pyclass, "__len__",  (PyCFunction) TObjStringLength, METH_NOARGS );
02028 
02029       Utility::AddToClass( pyclass, "__cmp__", (PyCFunction) TObjStringCompare, METH_O );
02030       Utility::AddToClass( pyclass, "__eq__",  (PyCFunction) TObjStringIsEqual, METH_O );
02031       Utility::AddToClass( pyclass, "__ne__",  (PyCFunction) TObjStringIsNotEqual, METH_O );
02032 
02033       return kTRUE;
02034    }
02035 
02036    if ( name == "TIter" ) {
02037       ((PyTypeObject*)pyclass)->tp_iter     = (getiterfunc)TIterIter;
02038       Utility::AddToClass( pyclass, "__iter__", (PyCFunction) TIterIter, METH_NOARGS );
02039 
02040       ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)TIterNext;
02041       Utility::AddToClass( pyclass, "next", (PyCFunction) TIterNext, METH_NOARGS );
02042 
02043       return kTRUE;
02044    }
02045 
02046    if ( name == "TDirectory" ) {
02047    // note: this replaces the already existing TDirectory::GetObject()
02048       Utility::AddToClass( pyclass, "GetObject", (PyCFunction) TDirectoryGetObject );
02049 
02050    // note: this replaces the already existing TDirectory::WriteObject()
02051       Utility::AddToClass( pyclass, "WriteObject", (PyCFunction) TDirectoryWriteObject );
02052 
02053       return kTRUE;
02054    }
02055 
02056    if ( name == "TTree" ) {
02057    // allow direct browsing of the tree
02058       Utility::AddToClass( pyclass, "__getattr__", (PyCFunction) TTreeGetAttr, METH_O );
02059 
02060    // workaround for templated member Branch()
02061       MethodProxy* original = (MethodProxy*)PyObject_GetAttr( pyclass, PyStrings::gBranch );
02062       MethodProxy* method = MethodProxy_New( "Branch", new TTreeBranch( original ) );
02063       Py_DECREF( original ); original = 0;
02064 
02065       PyObject_SetAttrString(
02066          pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
02067       Py_DECREF( method ); method = 0;
02068 
02069    // workaround for templated member SetBranchAddress()
02070       original = (MethodProxy*)PyObject_GetAttr( pyclass, PyStrings::gSetBranchAddress );
02071       method = MethodProxy_New( "SetBranchAddress", new TTreeSetBranchAddress( original ) );
02072       Py_DECREF( original ); original = 0;
02073 
02074       PyObject_SetAttrString(
02075          pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
02076       Py_DECREF( method ); method = 0;
02077 
02078       return kTRUE;
02079    }
02080 
02081    if ( name == "TChain" ) {
02082    // pretend a using
02083       Utility::AddUsingToClass( pyclass, "Process" );
02084 
02085    // allow SetBranchAddress to take object directly, w/o needing AddressOf()
02086       MethodProxy* original = (MethodProxy*)PyObject_GetAttr( pyclass, PyStrings::gSetBranchAddress );
02087       MethodProxy* method = MethodProxy_New( "SetBranchAddress", new TChainSetBranchAddress( original ) );
02088       Py_DECREF( original ); original = 0;
02089 
02090       PyObject_SetAttrString(
02091          pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
02092       Py_DECREF( method ); method = 0;
02093 
02094       return kTRUE;
02095    }
02096 
02097    if ( name == "TStyle" ) {
02098        MethodProxy* ctor = (MethodProxy*)PyObject_GetAttr( pyclass, PyStrings::gInit );
02099        ctor->fMethodInfo->fFlags &= ~MethodProxy::MethodInfo_t::kIsCreator;
02100        Py_DECREF( ctor );
02101    }
02102 
02103    if ( name == "TH1" )       // allow hist *= scalar
02104       return Utility::AddToClass( pyclass, "__imul__", (PyCFunction) THNIMul, METH_O );
02105 
02106    if ( name == "TF1" )       // allow instantiation with python callable
02107       return Utility::AddToClass( pyclass, "__init__", new TF1InitWithPyFunc );
02108 
02109    if ( name == "TF2" )       // allow instantiation with python callable
02110       return Utility::AddToClass( pyclass, "__init__", new TF2InitWithPyFunc );
02111 
02112    if ( name == "TF3" )       // allow instantiation with python callable
02113       return Utility::AddToClass( pyclass, "__init__", new TF3InitWithPyFunc );
02114 
02115    if ( name == "TFunction" ) // allow direct call
02116       return Utility::AddToClass( pyclass, "__call__", (PyCFunction) TFunctionCall );
02117 
02118    if ( name == "TMinuit" )   // allow call with python callable
02119       return Utility::AddToClass( pyclass, "SetFCN", new TMinuitSetFCN );
02120 
02121    if ( name == "Fitter" )    // really Fit::Fitter, allow call with python callable
02122       return Utility::AddToClass( pyclass, "FitFCN", new TFitterFitFCN );
02123 
02124    if ( name == "TFile" )     // allow member-style access to entries in file
02125       return Utility::AddToClass( pyclass, "__getattr__", "Get" );
02126 
02127    if ( name.substr(0,8) == "TVector3" ) {
02128       Utility::AddToClass( pyclass, "__len__", (PyCFunction) ReturnThree, METH_NOARGS );
02129       Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
02130       Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
02131 
02132       return kTRUE;
02133    }
02134 
02135    if ( name.substr(0,8) == "TVectorT" ) {  // allow proper iteration
02136       Utility::AddToClass( pyclass, "__len__", "GetNoElements" );
02137       Utility::AddToClass( pyclass, "_getitem__unchecked", "__getitem__" );
02138       Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) CheckedGetItem, METH_O );
02139 
02140       return kTRUE;
02141    }
02142 
02143 // Make RooFit 'using' member functions available (not supported by dictionary)
02144    if ( name == "RooDataHist" )
02145       return Utility::AddUsingToClass( pyclass, "plotOn" );
02146 
02147    if ( name == "RooSimultaneous" )
02148       return Utility::AddUsingToClass( pyclass, "plotOn" );
02149 
02150 // default (no pythonization) is by definition ok
02151    return kTRUE;
02152 }

Generated on Tue Jul 5 14:10:15 2011 for ROOT_528-00b_version by  doxygen 1.5.1