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