6 #include "structmember.h"
7 #if PY_VERSION_HEX >= 0x02050000
14 #define CO_NOFREE 0x0040
30 class TPythonCallback :
public PyCallable {
34 TPythonCallback( PyObject* callable ):
37 if ( !PyCallable_Check( callable ) ) {
38 PyErr_SetString(PyExc_TypeError,
"parameter must be callable");
42 Py_INCREF( fCallable );
45 virtual ~TPythonCallback() {
46 Py_DECREF( fCallable );
50 virtual PyObject* GetSignature() {
return PyROOT_PyUnicode_FromString(
"*args, **kwargs" ); } ;
51 virtual PyObject* GetPrototype() {
return PyROOT_PyUnicode_FromString(
"<callback>" ); } ;
52 virtual PyObject* GetDocString() {
53 if ( PyObject_HasAttrString( fCallable,
"__doc__" )) {
54 return PyObject_GetAttrString( fCallable,
"__doc__" );
56 return GetPrototype();
60 virtual Int_t GetPriority() {
return 100; };
62 virtual Int_t GetMaxArgs() {
return 100; };
63 virtual PyObject* GetCoVarNames() {
67 virtual PyObject* GetArgDefault( Int_t ) {
72 virtual PyObject* GetScopeProxy() {
77 virtual PyCallable* Clone() {
return new TPythonCallback( *
this ); }
79 virtual PyObject* Call(
80 ObjectProxy*&
self, PyObject* args, PyObject* kwds, TCallContext* ) {
82 PyObject* newArgs =
nullptr;
84 Py_ssize_t nargs = PyTuple_Size( args );
85 newArgs = PyTuple_New( nargs+1 );
87 PyTuple_SET_ITEM( newArgs, 0, (PyObject*)
self );
88 for ( Py_ssize_t iarg = 0; iarg < nargs; ++iarg ) {
89 PyObject* pyarg = PyTuple_GET_ITEM( args, iarg );
91 PyTuple_SET_ITEM( newArgs, iarg+1, pyarg );
97 return PyObject_Call( fCallable, newArgs, kwds );
104 Bool_t
inline IsPseudoFunc( MethodProxy* pymeth )
106 return (
void*)pymeth == (
void*)pymeth->fSelf;
111 PyError_t() { fType = fValue = fTrace = 0; }
113 static void Clear( PyError_t& e )
116 Py_XDECREF( e.fType ); Py_XDECREF( e.fValue ); Py_XDECREF( e.fTrace );
117 e.fType = e.fValue = e.fTrace = 0;
120 PyObject *fType, *fValue, *fTrace;
124 inline Long_t HashSignature( PyObject* args )
129 Int_t nargs = PyTuple_GET_SIZE( args );
130 for ( Int_t i = 0; i < nargs; ++i ) {
131 hash += (ULong_t) Py_TYPE( PyTuple_GET_ITEM( args, i ) );
132 hash += (hash << 10); hash ^= (hash >> 6);
135 hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15);
141 int PriorityCmp( PyCallable* left, PyCallable* right )
143 return left->GetPriority() > right->GetPriority();
147 inline void ResetCallState( ObjectProxy*& selfnew, ObjectProxy* selfold, Bool_t clear ) {
148 if ( selfnew != selfold ) {
149 Py_XDECREF( selfnew );
158 inline PyObject* HandleReturn( MethodProxy* pymeth, ObjectProxy* oldSelf, PyObject* result ) {
164 if ( IsCreator( pymeth->fMethodInfo->fFlags ) ) {
167 if ( IsConstructor( pymeth->fMethodInfo->fFlags ) ) {
169 pymeth->fSelf->HoldOn();
173 else if ( ObjectProxy_Check( result ) )
174 ((ObjectProxy*)result)->HoldOn();
178 if ( ObjectProxy_Check( pymeth->fSelf ) && ObjectProxy_Check( result ) ) {
179 Long_t ptrdiff = (Long_t)((ObjectProxy*)result)->GetObject() - (Long_t)pymeth->fSelf->GetObject();
180 if ( 0 <= ptrdiff && ptrdiff < (Long_t)Cppyy::SizeOf( pymeth->fSelf->ObjectIsA() ) ) {
181 if ( PyObject_SetAttr( result, PyStrings::gLifeLine, (PyObject*)pymeth->fSelf ) == -1 )
188 ResetCallState( pymeth->fSelf, oldSelf, kFALSE );
195 PyObject* mp_name( MethodProxy* pymeth,
void* )
197 return PyROOT_PyUnicode_FromString( pymeth->GetName().c_str() );
202 PyObject* mp_module( MethodProxy* ,
void* )
204 Py_INCREF( PyStrings::gROOTns );
205 return PyStrings::gROOTns;
211 PyObject* mp_doc( MethodProxy* pymeth,
void* )
213 MethodProxy::Methods_t& methods = pymeth->fMethodInfo->fMethods;
216 Int_t nMethods = methods.size();
222 PyObject* doc = methods[0]->GetDocString();
229 PyObject* separator = PyROOT_PyUnicode_FromString(
"\n" );
230 for ( Int_t i = 1; i < nMethods; ++i ) {
231 PyROOT_PyUnicode_Append( &doc, separator );
232 PyROOT_PyUnicode_AppendAndDel( &doc, methods[i]->GetDocString() );
234 Py_DECREF( separator );
242 PyObject* mp_meth_func( MethodProxy* pymeth,
void* )
244 MethodProxy* newPyMeth = (MethodProxy*)MethodProxy_Type.tp_alloc( &MethodProxy_Type, 0 );
247 *pymeth->fMethodInfo->fRefCount += 1;
248 newPyMeth->fMethodInfo = pymeth->fMethodInfo;
252 newPyMeth->fSelf = (ObjectProxy*)newPyMeth;
254 return (PyObject*)newPyMeth;
261 PyObject* mp_meth_self( MethodProxy* pymeth,
void* )
263 if ( IsPseudoFunc( pymeth ) ) {
264 PyErr_Format( PyExc_AttributeError,
265 "function %s has no attribute \'im_self\'", pymeth->fMethodInfo->fName.c_str() );
267 }
else if ( pymeth->fSelf != 0 ) {
268 Py_INCREF( (PyObject*)pymeth->fSelf );
269 return (PyObject*)pymeth->fSelf;
272 Py_INCREF( Py_None );
280 PyObject* mp_meth_class( MethodProxy* pymeth,
void* )
282 if ( ! IsPseudoFunc( pymeth ) ) {
283 PyObject* pyclass = pymeth->fMethodInfo->fMethods[0]->GetScopeProxy();
285 PyErr_Format( PyExc_AttributeError,
286 "function %s has no attribute \'im_class\'", pymeth->fMethodInfo->fName.c_str() );
290 Py_INCREF( Py_None );
297 PyObject* mp_func_closure( MethodProxy* ,
void* )
299 Py_INCREF( Py_None );
306 PyObject* mp_func_code( MethodProxy* pymeth,
void* )
308 #if PY_VERSION_HEX < 0x03000000
309 MethodProxy::Methods_t& methods = pymeth->fMethodInfo->fMethods;
313 PyObject* co_varnames = methods.size() == 1 ? methods[0]->GetCoVarNames() : NULL;
314 if ( !co_varnames ) {
316 co_varnames = PyTuple_New( 1 + 1 );
317 PyTuple_SET_ITEM( co_varnames, 0, PyROOT_PyUnicode_FromString(
"self" ) );
318 PyTuple_SET_ITEM( co_varnames, 1, PyROOT_PyUnicode_FromString(
"*args" ) );
321 int co_argcount = PyTuple_Size( co_varnames );
324 PyObject* co_code = PyString_FromStringAndSize(
"d\x00\x00S", 4 );
327 PyObject* co_consts = PyTuple_New( 0 );
328 PyObject* co_names = PyTuple_New( 0 );
331 PyObject* co_unused = PyTuple_New( 0 );
334 PyObject* co_filename = PyString_FromString(
"ROOT.py" );
337 PyObject* co_name = PyString_FromString( pymeth->GetName().c_str() );
342 PyObject* co_lnotab = PyString_FromString(
"\x00\x01\x0c\x01" );
344 PyObject* code = (PyObject*)PyCode_New(
348 CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE,
360 Py_DECREF( co_lnotab );
361 Py_DECREF( co_name );
362 Py_DECREF( co_unused );
363 Py_DECREF( co_filename );
364 Py_DECREF( co_varnames );
365 Py_DECREF( co_names );
366 Py_DECREF( co_consts );
367 Py_DECREF( co_code );
373 if ( pymeth || !pymeth) Py_INCREF( Py_None );
382 PyObject* mp_func_defaults( MethodProxy* pymeth,
void* )
384 MethodProxy::Methods_t& methods = pymeth->fMethodInfo->fMethods;
386 if ( methods.size() != 1 )
387 return PyTuple_New( 0 );
389 int maxarg = methods[0]->GetMaxArgs();
391 PyObject* defaults = PyTuple_New( maxarg );
394 for (
int iarg = 0; iarg < maxarg; ++iarg ) {
395 PyObject* defvalue = methods[0]->GetArgDefault( iarg );
397 PyTuple_SET_ITEM( defaults, itup++, defvalue );
399 _PyTuple_Resize( &defaults, itup );
408 PyObject* mp_func_globals( MethodProxy* ,
void* )
410 PyObject* pyglobal = PyModule_GetDict( PyImport_AddModule( (
char*)
"ROOT" ) );
411 Py_XINCREF( pyglobal );
418 PyObject* mp_getcreates( MethodProxy* pymeth,
void* )
420 return PyInt_FromLong( (Bool_t)IsCreator( pymeth->fMethodInfo->fFlags ) );
426 int mp_setcreates( MethodProxy* pymeth, PyObject* value,
void* )
429 pymeth->fMethodInfo->fFlags &= ~TCallContext::kIsCreator;
433 Long_t iscreator = PyLong_AsLong( value );
434 if ( iscreator == -1 && PyErr_Occurred() ) {
435 PyErr_SetString( PyExc_ValueError,
"a boolean 1 or 0 is required for _creates" );
440 pymeth->fMethodInfo->fFlags |= TCallContext::kIsCreator;
442 pymeth->fMethodInfo->fFlags &= ~TCallContext::kIsCreator;
450 PyObject* mp_getmempolicy( MethodProxy* pymeth,
void* )
452 if ( (Bool_t)(pymeth->fMethodInfo->fFlags & TCallContext::kUseHeuristics ) )
453 return PyInt_FromLong( TCallContext::kUseHeuristics );
455 if ( (Bool_t)(pymeth->fMethodInfo->fFlags & TCallContext::kUseStrict ) )
456 return PyInt_FromLong( TCallContext::kUseStrict );
458 return PyInt_FromLong( -1 );
464 int mp_setmempolicy( MethodProxy* pymeth, PyObject* value,
void* )
466 Long_t mempolicy = PyLong_AsLong( value );
467 if ( mempolicy == TCallContext::kUseHeuristics ) {
468 pymeth->fMethodInfo->fFlags |= TCallContext::kUseHeuristics;
469 pymeth->fMethodInfo->fFlags &= ~TCallContext::kUseStrict;
470 }
else if ( mempolicy == TCallContext::kUseStrict ) {
471 pymeth->fMethodInfo->fFlags |= TCallContext::kUseStrict;
472 pymeth->fMethodInfo->fFlags &= ~TCallContext::kUseHeuristics;
474 PyErr_SetString( PyExc_ValueError,
475 "expected kMemoryStrict or kMemoryHeuristics as value for _mempolicy" );
486 PyObject* mp_get_manage_smart_ptr( MethodProxy* pymeth,
void* )
488 return PyInt_FromLong(
489 (Bool_t)(pymeth->fMethodInfo->fFlags & TCallContext::kManageSmartPtr) );
496 int mp_set_manage_smart_ptr( MethodProxy* pymeth, PyObject* value,
void* )
498 Long_t policy = PyLong_AsLong( value );
499 if ( policy == -1 && PyErr_Occurred() ) {
500 PyErr_SetString( PyExc_ValueError,
"a boolean 1 or 0 is required for _manage_smart_ptr" );
504 pymeth->fMethodInfo->fFlags |= TCallContext::kManageSmartPtr;
512 PyObject* mp_getthreaded( MethodProxy* pymeth,
void* )
514 return PyInt_FromLong(
515 (Bool_t)(pymeth->fMethodInfo->fFlags & TCallContext::kReleaseGIL) );
521 int mp_setthreaded( MethodProxy* pymeth, PyObject* value,
void* )
523 Long_t isthreaded = PyLong_AsLong( value );
524 if ( isthreaded == -1 && PyErr_Occurred() ) {
525 PyErr_SetString( PyExc_ValueError,
"a boolean 1 or 0 is required for _creates" );
530 pymeth->fMethodInfo->fFlags |= TCallContext::kReleaseGIL;
532 pymeth->fMethodInfo->fFlags &= ~TCallContext::kReleaseGIL;
539 PyGetSetDef mp_getset[] = {
540 { (
char*)
"__name__", (getter)mp_name, NULL, NULL, NULL },
541 { (
char*)
"__module__", (getter)mp_module, NULL, NULL, NULL },
542 { (
char*)
"__doc__", (getter)mp_doc, NULL, NULL, NULL },
547 { (
char*)
"im_func", (getter)mp_meth_func, NULL, NULL, NULL },
548 { (
char*)
"im_self", (getter)mp_meth_self, NULL, NULL, NULL },
549 { (
char*)
"im_class", (getter)mp_meth_class, NULL, NULL, NULL },
551 { (
char*)
"func_closure", (getter)mp_func_closure, NULL, NULL, NULL },
552 { (
char*)
"func_code", (getter)mp_func_code, NULL, NULL, NULL },
553 { (
char*)
"func_defaults", (getter)mp_func_defaults, NULL, NULL, NULL },
554 { (
char*)
"func_globals", (getter)mp_func_globals, NULL, NULL, NULL },
555 { (
char*)
"func_doc", (getter)mp_doc, NULL, NULL, NULL },
556 { (
char*)
"func_name", (getter)mp_name, NULL, NULL, NULL },
558 { (
char*)
"_creates", (getter)mp_getcreates, (setter)mp_setcreates,
559 (
char*)
"For ownership rules of result: if true, objects are python-owned", NULL },
560 { (
char*)
"__creates__", (getter)mp_getcreates, (setter)mp_setcreates,
561 (
char*)
"For ownership rules of result: if true, objects are python-owned", NULL },
562 { (
char*)
"_mempolicy", (getter)mp_getmempolicy, (setter)mp_setmempolicy,
563 (
char*)
"For argument ownership rules: like global, either heuristic or strict", NULL },
564 { (
char*)
"__mempolicy__", (getter)mp_getmempolicy, (setter)mp_setmempolicy,
565 (
char*)
"For argument ownership rules: like global, either heuristic or strict", NULL },
566 { (
char*)
"_manage_smart_ptr", (getter)mp_get_manage_smart_ptr, (setter)mp_set_manage_smart_ptr,
567 (
char*)
"If a smart pointer is returned, determines management policy.", NULL },
568 { (
char*)
"_threaded", (getter)mp_getthreaded, (setter)mp_setthreaded,
569 (
char*)
"If true, releases GIL on call into C++", NULL },
570 { (
char*)
"__release_gil__", (getter)mp_getthreaded, (setter)mp_setthreaded,
571 (
char*)
"If true, releases GIL on call into C++", NULL },
572 { (
char*)NULL, NULL, NULL, NULL, NULL }
576 PyObject* mp_call( MethodProxy* pymeth, PyObject* args, PyObject* kwds )
582 if ( IsPseudoFunc( pymeth ) )
583 pymeth->fSelf = NULL;
585 ObjectProxy* oldSelf = pymeth->fSelf;
588 auto& methods = pymeth->fMethodInfo->fMethods;
589 auto& dispatchMap = pymeth->fMethodInfo->fDispatchMap;
590 auto& mflags = pymeth->fMethodInfo->fFlags;
592 Int_t nMethods = methods.size();
594 TCallContext ctxt = { 0 };
595 ctxt.fFlags |= (mflags & TCallContext::kUseHeuristics);
596 ctxt.fFlags |= (mflags & TCallContext::kUseStrict);
597 ctxt.fFlags |= (mflags & TCallContext::kManageSmartPtr);
598 if ( ! ctxt.fFlags ) ctxt.fFlags |= TCallContext::sMemoryPolicy;
599 ctxt.fFlags |= (mflags & TCallContext::kReleaseGIL);
602 if ( nMethods == 1 ) {
603 PyObject* result = methods[0]->Call( pymeth->fSelf, args, kwds, &ctxt );
604 return HandleReturn( pymeth, oldSelf, result );
608 Long_t sighash = HashSignature( args );
611 MethodProxy::DispatchMap_t::iterator m = dispatchMap.find( sighash );
612 if ( m != dispatchMap.end() ) {
613 Int_t index = m->second;
614 PyObject* result = methods[ index ]->Call( pymeth->fSelf, args, kwds, &ctxt );
615 result = HandleReturn( pymeth, oldSelf, result );
621 ResetCallState( pymeth->fSelf, oldSelf, kTRUE );
625 if ( ! IsSorted( mflags ) ) {
626 std::stable_sort( methods.begin(), methods.end(), PriorityCmp );
627 mflags |= TCallContext::kIsSorted;
630 std::vector< PyError_t > errors;
631 for ( Int_t i = 0; i < nMethods; ++i ) {
632 PyObject* result = methods[i]->Call( pymeth->fSelf, args, kwds, &ctxt );
636 dispatchMap[ sighash ] = i;
637 std::for_each( errors.begin(), errors.end(), PyError_t::Clear );
638 return HandleReturn( pymeth, oldSelf, result );
642 if ( ! PyErr_Occurred() ) {
644 PyObject* sig = methods[i]->GetPrototype();
645 PyErr_Format( PyExc_SystemError,
"%s =>\n %s",
646 PyROOT_PyUnicode_AsString( sig ), (
char*)
"NULL result without error in mp_call" );
650 PyErr_Fetch( &e.fType, &e.fValue, &e.fTrace );
651 errors.push_back( e );
652 ResetCallState( pymeth->fSelf, oldSelf, kFALSE );
656 PyObject* value = PyROOT_PyUnicode_FromFormat(
657 "none of the %d overloaded methods succeeded. Full details:", nMethods );
658 PyObject* separator = PyROOT_PyUnicode_FromString(
"\n " );
661 PyObject* exc_type = NULL;
662 for ( std::vector< PyError_t >::iterator e = errors.begin(); e != errors.end(); ++e ) {
663 if ( e->fType != PyExc_NotImplementedError ) {
664 if ( ! exc_type ) exc_type = e->fType;
665 else if ( exc_type != e->fType ) exc_type = PyExc_TypeError;
667 PyROOT_PyUnicode_Append( &value, separator );
668 PyROOT_PyUnicode_Append( &value, e->fValue );
671 Py_DECREF( separator );
672 std::for_each( errors.begin(), errors.end(), PyError_t::Clear );
675 PyErr_SetObject( exc_type ? exc_type : PyExc_TypeError, value );
683 MethodProxy* mp_descrget( MethodProxy* pymeth, ObjectProxy* pyobj, PyObject* )
685 MethodProxy* newPyMeth = (MethodProxy*)MethodProxy_Type.tp_alloc( &MethodProxy_Type, 0 );
688 *pymeth->fMethodInfo->fRefCount += 1;
689 newPyMeth->fMethodInfo = pymeth->fMethodInfo;
692 Py_XINCREF( (PyObject*)pyobj );
693 newPyMeth->fSelf = pyobj;
700 MethodProxy* mp_new( PyTypeObject*, PyObject*, PyObject* )
703 MethodProxy* pymeth = PyObject_GC_New( MethodProxy, &MethodProxy_Type );
704 pymeth->fSelf = NULL;
705 pymeth->fMethodInfo =
new MethodProxy::MethodInfo_t;
707 PyObject_GC_Track( pymeth );
714 void mp_dealloc( MethodProxy* pymeth )
716 PyObject_GC_UnTrack( pymeth );
718 if ( ! IsPseudoFunc( pymeth ) )
719 Py_CLEAR( pymeth->fSelf );
720 pymeth->fSelf = NULL;
722 if ( --(*pymeth->fMethodInfo->fRefCount) <= 0 ) {
723 delete pymeth->fMethodInfo;
726 PyObject_GC_Del( pymeth );
734 Long_t mp_hash( MethodProxy* pymeth )
736 return _Py_HashPointer( pymeth->fMethodInfo );
742 int mp_traverse( MethodProxy* pymeth, visitproc visit,
void* args )
744 if ( pymeth->fSelf && ! IsPseudoFunc( pymeth ) )
745 return visit( (PyObject*)pymeth->fSelf, args );
753 int mp_clear( MethodProxy* pymeth )
755 if ( ! IsPseudoFunc( pymeth ) )
756 Py_CLEAR( pymeth->fSelf );
757 pymeth->fSelf = NULL;
765 PyObject* mp_richcompare( MethodProxy*
self, MethodProxy* other,
int op )
768 return PyType_Type.tp_richcompare( (PyObject*)
self, (PyObject*)other, op );
771 if ( ( Py_TYPE(
self) == Py_TYPE(other) && self->fMethodInfo == other->fMethodInfo ) && \
772 ( ( IsPseudoFunc(
self ) && IsPseudoFunc( other ) ) || self->fSelf == other->fSelf ) ) {
773 Py_INCREF( Py_True );
776 Py_INCREF( Py_False );
782 PyObject* mp_disp( MethodProxy* pymeth, PyObject* sigarg )
785 if ( ! PyROOT_PyUnicode_Check( sigarg ) ) {
786 PyErr_Format( PyExc_TypeError,
"disp() argument 1 must be string, not %.50s",
787 sigarg == Py_None ?
"None" : Py_TYPE(sigarg)->tp_name );
791 PyObject* sig1 = PyROOT_PyUnicode_FromFormat(
"(%s)", PyROOT_PyUnicode_AsString( sigarg ) );
793 MethodProxy::Methods_t& methods = pymeth->fMethodInfo->fMethods;
794 for ( Int_t i = 0; i < (Int_t)methods.size(); ++i ) {
796 PyObject* sig2 = methods[ i ]->GetSignature();
797 if ( PyObject_RichCompareBool( sig1, sig2, Py_EQ ) ) {
800 MethodProxy* newmeth = mp_new( NULL, NULL, NULL );
801 MethodProxy::Methods_t vec; vec.push_back( methods[ i ]->Clone() );
802 newmeth->Set( pymeth->fMethodInfo->fName, vec );
804 if ( pymeth->fSelf && ! IsPseudoFunc( pymeth ) ) {
805 Py_INCREF( pymeth->fSelf );
806 newmeth->fSelf = pymeth->fSelf;
810 return (PyObject*)newmeth;
817 PyErr_Format( PyExc_LookupError,
"signature \"%s\" not found", PyROOT_PyUnicode_AsString( sigarg ) );
822 PyObject* mp_add_overload( MethodProxy* pymeth, PyObject* new_overload )
824 TPythonCallback* cb =
new TPythonCallback(new_overload);
825 pymeth->AddMethod( cb );
826 Py_INCREF( Py_None );
830 PyMethodDef mp_methods[] = {
831 { (
char*)
"disp", (PyCFunction)mp_disp, METH_O, (
char*)
"select overload for dispatch" },
832 { (
char*)
"__add_overload__", (PyCFunction)mp_add_overload, METH_O, (
char*)
"add a new overload" },
833 { (
char*)NULL, NULL, 0, NULL }
842 PyTypeObject MethodProxy_Type = {
843 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
844 (
char*)
"ROOT.MethodProxy",
847 (destructor)mp_dealloc,
857 (ternaryfunc)mp_call,
862 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
863 (
char*)
"PyROOT method proxy (internal)",
864 (traverseproc)mp_traverse,
866 (richcmpfunc)mp_richcompare,
875 (descrgetfunc)mp_descrget,
888 #if PY_VERSION_HEX >= 0x02030000
891 #if PY_VERSION_HEX >= 0x02060000
894 #if PY_VERSION_HEX >= 0x03040000
903 void PyROOT::MethodProxy::Set(
const std::string& name, std::vector< PyCallable* >& methods )
906 fMethodInfo->fName = name;
907 fMethodInfo->fMethods.swap( methods );
908 fMethodInfo->fFlags &= ~TCallContext::kIsSorted;
909 fMethodInfo->fFlags |= TCallContext::kManageSmartPtr;
912 if ( name ==
"__init__" )
913 fMethodInfo->fFlags |= (TCallContext::kIsCreator | TCallContext::kIsConstructor);
916 if ( TCallContext::sMemoryPolicy == TCallContext::kUseHeuristics && \
917 name.find(
"Clone" ) != std::string::npos )
918 fMethodInfo->fFlags |= TCallContext::kIsCreator;
924 void PyROOT::MethodProxy::AddMethod( PyCallable* pc )
926 fMethodInfo->fMethods.push_back( pc );
927 fMethodInfo->fFlags &= ~TCallContext::kIsSorted;
932 void PyROOT::MethodProxy::AddMethod( MethodProxy* meth )
934 fMethodInfo->fMethods.insert( fMethodInfo->fMethods.end(),
935 meth->fMethodInfo->fMethods.begin(), meth->fMethodInfo->fMethods.end() );
936 fMethodInfo->fFlags &= ~TCallContext::kIsSorted;
942 PyROOT::MethodProxy::MethodInfo_t::~MethodInfo_t()
944 for ( Methods_t::iterator it = fMethods.begin(); it != fMethods.end(); ++it ) {