00001
00002
00003
00004
00005 #include "PyROOT.h"
00006 #include "PyStrings.h"
00007 #include "Utility.h"
00008 #include "ObjectProxy.h"
00009 #include "MethodProxy.h"
00010 #include "FunctionHolder.h"
00011 #include "TCustomPyTypes.h"
00012 #include "RootWrapper.h"
00013 #include "PyCallable.h"
00014 #include "Adapters.h"
00015
00016
00017 #include "TROOT.h"
00018 #include "TObject.h"
00019 #include "TClassEdit.h"
00020 #include "TClassRef.h"
00021 #include "TCollection.h"
00022 #include "TFunction.h"
00023 #include "TMethodArg.h"
00024 #include "TError.h"
00025
00026
00027 #include "Api.h"
00028
00029
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <algorithm>
00034 #include <list>
00035 #include <utility>
00036
00037
00038
00039 PyROOT::DictLookup_t PyROOT::gDictLookupOrg = 0;
00040 Bool_t PyROOT::gDictLookupActive = kFALSE;
00041
00042 PyROOT::Utility::EMemoryPolicy PyROOT::Utility::gMemoryPolicy = PyROOT::Utility::kHeuristics;
00043
00044
00045 PyROOT::Utility::ESignalPolicy PyROOT::Utility::gSignalPolicy = PyROOT::Utility::kSafe;
00046
00047 typedef std::map< std::string, std::string > TC2POperatorMapping_t;
00048 static TC2POperatorMapping_t gC2POperatorMapping;
00049
00050 namespace {
00051
00052 using namespace PyROOT::Utility;
00053
00054 struct InitOperatorMapping_t {
00055 public:
00056 InitOperatorMapping_t() {
00057
00058
00059
00060
00061
00062 gC2POperatorMapping[ "[]" ] = "__getitem__";
00063 gC2POperatorMapping[ "()" ] = "__call__";
00064 gC2POperatorMapping[ "/" ] = PYROOT__div__;
00065 gC2POperatorMapping[ "%" ] = "__mod__";
00066 gC2POperatorMapping[ "**" ] = "__pow__";
00067 gC2POperatorMapping[ "<<" ] = "__lshift__";
00068 gC2POperatorMapping[ ">>" ] = "__rshift__";
00069 gC2POperatorMapping[ "&" ] = "__and__";
00070 gC2POperatorMapping[ "|" ] = "__or__";
00071 gC2POperatorMapping[ "^" ] = "__xor__";
00072 gC2POperatorMapping[ "~" ] = "__inv__";
00073 gC2POperatorMapping[ "+=" ] = "__iadd__";
00074 gC2POperatorMapping[ "-=" ] = "__isub__";
00075 gC2POperatorMapping[ "*=" ] = "__imul__";
00076 gC2POperatorMapping[ "/=" ] = PYROOT__idiv__;
00077 gC2POperatorMapping[ "%=" ] = "__imod__";
00078 gC2POperatorMapping[ "**=" ] = "__ipow__";
00079 gC2POperatorMapping[ "<<=" ] = "__ilshift__";
00080 gC2POperatorMapping[ ">>=" ] = "__irshift__";
00081 gC2POperatorMapping[ "&=" ] = "__iand__";
00082 gC2POperatorMapping[ "|=" ] = "__ior__";
00083 gC2POperatorMapping[ "^=" ] = "__ixor__";
00084 gC2POperatorMapping[ "==" ] = "__eq__";
00085 gC2POperatorMapping[ "!=" ] = "__ne__";
00086 gC2POperatorMapping[ ">" ] = "__gt__";
00087 gC2POperatorMapping[ "<" ] = "__lt__";
00088 gC2POperatorMapping[ ">=" ] = "__ge__";
00089 gC2POperatorMapping[ "<=" ] = "__le__";
00090
00091
00092 gC2POperatorMapping[ "const char*" ] = "__str__";
00093 gC2POperatorMapping[ "char*" ] = "__str__";
00094 gC2POperatorMapping[ "int" ] = "__int__";
00095 gC2POperatorMapping[ "long" ] = PYROOT__long__;
00096 gC2POperatorMapping[ "double" ] = "__float__";
00097
00098
00099
00100
00101 gC2POperatorMapping[ "short" ] = "__int__";
00102 gC2POperatorMapping[ "unsigned short" ] = "__int__";
00103 gC2POperatorMapping[ "unsigned int" ] = PYROOT__long__;
00104 gC2POperatorMapping[ "unsigned long" ] = PYROOT__long__;
00105 gC2POperatorMapping[ "long long" ] = PYROOT__long__;
00106 gC2POperatorMapping[ "unsigned long long" ] = PYROOT__long__;
00107 gC2POperatorMapping[ "float" ] = "__float__";
00108
00109 gC2POperatorMapping[ "->" ] = "__follow__";
00110 gC2POperatorMapping[ "=" ] = "__assign__";
00111
00112 #if PY_VERSION_HEX < 0x03000000
00113 gC2POperatorMapping[ "bool" ] = "__nonzero__";
00114 #else
00115 gC2POperatorMapping[ "bool" ] = "__bool__";
00116 #endif
00117 }
00118 } initOperatorMapping_;
00119
00120
00121 typedef std::pair< PyObject*, Long_t > CallInfo_t;
00122 std::map< int, CallInfo_t > s_PyObjectCallbacks;
00123
00124 }
00125
00126
00127
00128 ULong_t PyROOT::PyLongOrInt_AsULong( PyObject* pyobject )
00129 {
00130
00131 ULong_t ul = PyLong_AsUnsignedLong( pyobject );
00132 if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) {
00133 PyErr_Clear();
00134 Long_t i = PyInt_AS_LONG( pyobject );
00135 if ( 0 <= i ) {
00136 ul = (ULong_t)i;
00137 } else {
00138 PyErr_SetString( PyExc_ValueError,
00139 "can\'t convert negative value to unsigned long" );
00140 }
00141 }
00142
00143 return ul;
00144 }
00145
00146
00147 ULong64_t PyROOT::PyLongOrInt_AsULong64( PyObject* pyobject )
00148 {
00149
00150 ULong64_t ull = PyLong_AsUnsignedLongLong( pyobject );
00151 if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) {
00152 PyErr_Clear();
00153 Long_t i = PyInt_AS_LONG( pyobject );
00154 if ( 0 <= i ) {
00155 ull = (ULong64_t)i;
00156 } else {
00157 PyErr_SetString( PyExc_ValueError,
00158 "can\'t convert negative value to unsigned long long" );
00159 }
00160 }
00161
00162 return ull;
00163 }
00164
00165
00166 Bool_t PyROOT::Utility::SetMemoryPolicy( EMemoryPolicy e )
00167 {
00168 if ( kHeuristics <= e && e <= kStrict ) {
00169 gMemoryPolicy = e;
00170 return kTRUE;
00171 }
00172 return kFALSE;
00173 }
00174
00175
00176 Bool_t PyROOT::Utility::SetSignalPolicy( ESignalPolicy e )
00177 {
00178 if ( kFast <= e && e <= kSafe ) {
00179 gSignalPolicy = e;
00180 return kTRUE;
00181 }
00182 return kFALSE;
00183 }
00184
00185
00186 Bool_t PyROOT::Utility::AddToClass(
00187 PyObject* pyclass, const char* label, PyCFunction cfunc, int flags )
00188 {
00189
00190 static std::list< PyMethodDef > s_pymeths;
00191
00192 s_pymeths.push_back( PyMethodDef() );
00193 PyMethodDef* pdef = &s_pymeths.back();
00194 pdef->ml_name = const_cast< char* >( label );
00195 pdef->ml_meth = cfunc;
00196 pdef->ml_flags = flags;
00197 pdef->ml_doc = NULL;
00198
00199 PyObject* func = PyCFunction_New( pdef, NULL );
00200 PyObject* method = TCustomInstanceMethod_New( func, NULL, pyclass );
00201 Bool_t isOk = PyObject_SetAttrString( pyclass, pdef->ml_name, method ) == 0;
00202 Py_DECREF( method );
00203 Py_DECREF( func );
00204
00205 if ( PyErr_Occurred() )
00206 return kFALSE;
00207
00208 if ( ! isOk ) {
00209 PyErr_Format( PyExc_TypeError, "could not add method %s", label );
00210 return kFALSE;
00211 }
00212
00213 return kTRUE;
00214 }
00215
00216
00217 Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, const char* func )
00218 {
00219 PyObject* pyfunc = PyObject_GetAttrString( pyclass, const_cast< char* >( func ) );
00220 if ( ! pyfunc )
00221 return kFALSE;
00222
00223 Bool_t isOk = PyObject_SetAttrString( pyclass, const_cast< char* >( label ), pyfunc ) == 0;
00224
00225 Py_DECREF( pyfunc );
00226 return isOk;
00227 }
00228
00229
00230 Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, PyCallable* pyfunc )
00231 {
00232 MethodProxy* method =
00233 (MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( label ) );
00234
00235 if ( ! method || ! MethodProxy_Check( method ) ) {
00236
00237 if ( PyErr_Occurred() )
00238 PyErr_Clear();
00239 Py_XDECREF( (PyObject*)method );
00240 method = MethodProxy_New( label, pyfunc );
00241 Bool_t isOk = PyObject_SetAttrString( pyclass, const_cast< char* >( label ), (PyObject*)method ) == 0;
00242 Py_DECREF( method );
00243 return isOk;
00244 }
00245
00246 method->AddMethod( pyfunc );
00247
00248 Py_DECREF( method );
00249 return kTRUE;
00250 }
00251
00252
00253 Bool_t PyROOT::Utility::AddUsingToClass( PyObject* pyclass, const char* method )
00254 {
00255
00256
00257
00258 MethodProxy* derivedMethod =
00259 (MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( method ) );
00260 if ( ! MethodProxy_Check( derivedMethod ) ) {
00261 Py_XDECREF( derivedMethod );
00262 return kFALSE;
00263 }
00264
00265 PyObject* mro = PyObject_GetAttr( pyclass, PyStrings::gMRO );
00266 if ( ! mro || ! PyTuple_Check( mro ) ) {
00267 Py_XDECREF( mro );
00268 Py_DECREF( derivedMethod );
00269 return kFALSE;
00270 }
00271
00272 MethodProxy* baseMethod = 0;
00273 for ( int i = 1; i < PyTuple_GET_SIZE( mro ); ++i ) {
00274 baseMethod = (MethodProxy*)PyObject_GetAttrString(
00275 PyTuple_GET_ITEM( mro, i ), const_cast< char* >( method ) );
00276
00277 if ( ! baseMethod ) {
00278 PyErr_Clear();
00279 continue;
00280 }
00281
00282 if ( MethodProxy_Check( baseMethod ) )
00283 break;
00284
00285 Py_DECREF( baseMethod );
00286 baseMethod = 0;
00287 }
00288
00289 Py_DECREF( mro );
00290
00291 if ( ! MethodProxy_Check( baseMethod ) ) {
00292 Py_XDECREF( baseMethod );
00293 Py_DECREF( derivedMethod );
00294 return kFALSE;
00295 }
00296
00297 derivedMethod->AddMethod( baseMethod );
00298
00299 Py_DECREF( baseMethod );
00300 Py_DECREF( derivedMethod );
00301
00302 return kTRUE;
00303 }
00304
00305
00306 Bool_t PyROOT::Utility::AddBinaryOperator(
00307 PyObject* left, PyObject* right, const char* op, const char* label )
00308 {
00309
00310
00311
00312
00313
00314 if ( ! ObjectProxy_Check( left ) )
00315 return kFALSE;
00316
00317
00318 std::string rcname = ClassName( right );
00319 std::string lcname = ClassName( left );
00320 PyObject* pyclass = PyObject_GetAttr( left, PyStrings::gClass );
00321
00322 Bool_t result = AddBinaryOperator( pyclass, lcname, rcname, op, label );
00323
00324 Py_DECREF( pyclass );
00325 return result;
00326 }
00327
00328
00329 Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const char* op, const char* label )
00330 {
00331
00332 PyObject* pyname = PyObject_GetAttr( pyclass, PyStrings::gName );
00333 std::string cname = TClassEdit::ResolveTypedef( PyROOT_PyUnicode_AsString( pyname ) );
00334 Py_DECREF( pyname ); pyname = 0;
00335
00336 return AddBinaryOperator( pyclass, cname, cname, op, label );
00337 }
00338
00339
00340 static inline TFunction* FindAndAddOperator( const std::string& lcname, const std::string& rcname,
00341 const char* op, TCollection* funcs ) {
00342
00343 std::string opname = "operator";
00344 opname += op;
00345
00346 TIter ifunc( funcs );
00347
00348 TFunction* func = 0;
00349 while ( (func = (TFunction*)ifunc.Next()) ) {
00350 if ( func->GetListOfMethodArgs()->GetSize() != 2 )
00351 continue;
00352
00353 if ( func->GetName() == opname ) {
00354 if ( ( lcname == TClassEdit::ResolveTypedef( TClassEdit::CleanType(
00355 ((TMethodArg*)func->GetListOfMethodArgs()->At(0))->GetTypeName(), 1 ).c_str(), true ) ) &&
00356 ( rcname == TClassEdit::ResolveTypedef( TClassEdit::CleanType(
00357 ((TMethodArg*)func->GetListOfMethodArgs()->At(1))->GetTypeName(), 1 ).c_str(), true ) ) ) {
00358
00359
00360 return func;
00361 }
00362
00363 }
00364 }
00365
00366 return 0;
00367 }
00368
00369 Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const std::string& lcname,
00370 const std::string& rcname, const char* op, const char* label )
00371 {
00372
00373
00374
00375 static TClassRef gnucxx( "__gnu_cxx" );
00376
00377 TFunction* func = 0;
00378 if ( gnucxx.GetClass() ) {
00379 func = FindAndAddOperator( lcname, rcname, op, gnucxx->GetListOfMethods() );
00380 if ( func ) {
00381 PyCallable* pyfunc = new TFunctionHolder< TScopeAdapter, TMemberAdapter >(
00382 TScopeAdapter::ByName( "__gnu_cxx" ), func );
00383 return Utility::AddToClass( pyclass, label ? label : gC2POperatorMapping[ op ].c_str(), pyfunc );
00384 }
00385 }
00386
00387 if ( ! func )
00388 func = FindAndAddOperator( lcname, rcname, op, gROOT->GetListOfGlobalFunctions( kTRUE ) );
00389
00390 if ( func ) {
00391
00392 PyCallable* pyfunc = new TFunctionHolder< TScopeAdapter, TMemberAdapter >( func );
00393 return Utility::AddToClass( pyclass, label ? label : gC2POperatorMapping[ op ].c_str(), pyfunc );
00394 }
00395
00396 return kFALSE;
00397 }
00398
00399
00400 Bool_t PyROOT::Utility::BuildTemplateName( PyObject*& pyname, PyObject* args, int argoff )
00401 {
00402
00403
00404
00405
00406 PyROOT_PyUnicode_AppendAndDel( &pyname, PyROOT_PyUnicode_FromString( "<" ) );
00407
00408 Py_ssize_t nArgs = PyTuple_GET_SIZE( args );
00409 for ( int i = argoff; i < nArgs; ++i ) {
00410
00411 PyObject* tn = PyTuple_GET_ITEM( args, i );
00412 if ( PyROOT_PyUnicode_Check( tn ) )
00413 PyROOT_PyUnicode_Append( &pyname, tn );
00414 else if ( PyObject_HasAttr( tn, PyStrings::gName ) ) {
00415
00416 PyObject* tpName = PyObject_GetAttr( tn, PyStrings::gName );
00417
00418
00419 if ( strcmp( PyROOT_PyUnicode_AsString( tpName ), "str" ) == 0 ) {
00420 Py_DECREF( tpName );
00421 tpName = PyROOT_PyUnicode_FromString( "std::string" );
00422 }
00423
00424 PyROOT_PyUnicode_AppendAndDel( &pyname, tpName );
00425 } else {
00426
00427 PyObject* pystr = PyObject_Str( tn );
00428 if ( ! pystr ) {
00429 return kFALSE;
00430 }
00431
00432 PyROOT_PyUnicode_AppendAndDel( &pyname, pystr );
00433 }
00434
00435
00436 if ( i != nArgs - 1 )
00437 PyROOT_PyUnicode_AppendAndDel( &pyname, PyROOT_PyUnicode_FromString( "," ) );
00438 }
00439
00440
00441 if ( PyROOT_PyUnicode_AsString( pyname )[ PyROOT_PyUnicode_GetSize( pyname ) - 1 ] == '>' )
00442 PyROOT_PyUnicode_AppendAndDel( &pyname, PyROOT_PyUnicode_FromString( " >" ) );
00443 else
00444 PyROOT_PyUnicode_AppendAndDel( &pyname, PyROOT_PyUnicode_FromString( ">" ) );
00445
00446 return kTRUE;
00447 }
00448
00449
00450 Bool_t PyROOT::Utility::InitProxy( PyObject* module, PyTypeObject* pytype, const char* name )
00451 {
00452
00453 if ( PyType_Ready( pytype ) < 0 )
00454 return kFALSE;
00455
00456
00457 Py_INCREF( pytype );
00458 if ( PyModule_AddObject( module, (char*)name, (PyObject*)pytype ) < 0 ) {
00459 Py_DECREF( pytype );
00460 return kFALSE;
00461 }
00462
00463
00464 return kTRUE;
00465 }
00466
00467
00468 int PyROOT::Utility::GetBuffer( PyObject* pyobject, char tc, int size, void*& buf, Bool_t check )
00469 {
00470
00471 if ( PyBytes_Check( pyobject ) )
00472 return 0;
00473
00474
00475 PyBufferProcs* bufprocs = Py_TYPE(pyobject)->tp_as_buffer;
00476
00477 PySequenceMethods* seqmeths = Py_TYPE(pyobject)->tp_as_sequence;
00478 if ( seqmeths != 0 && bufprocs != 0
00479 #if PY_VERSION_HEX < 0x03000000
00480 && bufprocs->bf_getwritebuffer != 0
00481 && (*(bufprocs->bf_getsegcount))( pyobject, 0 ) == 1
00482 #else
00483 && bufprocs->bf_getbuffer != 0
00484 #endif
00485 ) {
00486
00487
00488 #if PY_VERSION_HEX < 0x03000000
00489 Py_ssize_t buflen = (*(bufprocs->bf_getwritebuffer))( pyobject, 0, &buf );
00490 #else
00491 Py_buffer bufinfo;
00492 (*(bufprocs->bf_getbuffer))( pyobject, &bufinfo, PyBUF_WRITABLE );
00493 buf = (char*)bufinfo.buf;
00494 Py_ssize_t buflen = bufinfo.len;
00495 #endif
00496
00497 if ( check == kTRUE ) {
00498
00499 PyObject* pytc = PyObject_GetAttr( pyobject, PyStrings::gTypeCode );
00500 if ( pytc != 0 ) {
00501 if ( PyROOT_PyUnicode_AsString( pytc )[0] != tc )
00502 buf = 0;
00503 Py_DECREF( pytc );
00504 } else if ( seqmeths->sq_length &&
00505 (int)(buflen / (*(seqmeths->sq_length))( pyobject )) == size ) {
00506
00507 PyErr_Clear();
00508 } else if ( buflen == size ) {
00509
00510 PyErr_Clear();
00511 } else {
00512 buf = 0;
00513
00514
00515 PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
00516 PyErr_Fetch( &pytype, &pyvalue, &pytrace );
00517 PyObject* pyvalue2 = PyROOT_PyUnicode_FromFormat(
00518 (char*)"%s and given element size (%ld) do not match needed (%d)",
00519 PyROOT_PyUnicode_AsString( pyvalue ),
00520 seqmeths->sq_length ? (long)(buflen / (*(seqmeths->sq_length))( pyobject )) : (long)buflen,
00521 size );
00522 Py_DECREF( pyvalue );
00523 PyErr_Restore( pytype, pyvalue2, pytrace );
00524 }
00525 }
00526
00527 return buflen;
00528 }
00529
00530 return 0;
00531 }
00532
00533
00534 std::string PyROOT::Utility::MapOperatorName( const std::string& name, Bool_t bTakesParams )
00535 {
00536
00537
00538 if ( 8 < name.size() && name.substr( 0, 8 ) == "operator" ) {
00539 std::string op = name.substr( 8, std::string::npos );
00540
00541
00542 std::string::size_type start = 0, end = op.size();
00543 while ( start < end && isspace( op[ start ] ) ) ++start;
00544 while ( start < end && isspace( op[ end-1 ] ) ) --end;
00545 op = TClassEdit::ResolveTypedef( op.substr( start, end - start ).c_str(), true );
00546
00547
00548 TC2POperatorMapping_t::iterator pop = gC2POperatorMapping.find( op );
00549 if ( pop != gC2POperatorMapping.end() ) {
00550 return pop->second;
00551
00552 } else if ( op == "*" ) {
00553
00554 return bTakesParams ? "__mul__" : "__deref__";
00555
00556 } else if ( op == "+" ) {
00557
00558 return bTakesParams ? "__add__" : "__pos__";
00559
00560 } else if ( op == "-" ) {
00561
00562 return bTakesParams ? "__sub__" : "__neg__";
00563
00564 } else if ( op == "++" ) {
00565
00566 return bTakesParams ? "__postinc__" : "__preinc__";
00567
00568 } else if ( op == "--" ) {
00569
00570 return bTakesParams ? "__postdec__" : "__predec__";
00571 }
00572
00573 }
00574
00575
00576 return name;
00577 }
00578
00579
00580 PyROOT::Utility::EDataType PyROOT::Utility::EffectiveType( const std::string& name )
00581 {
00582 EDataType effType = kOther;
00583
00584 G__TypeInfo ti( name.c_str() );
00585 if ( ti.Property() & G__BIT_ISENUM )
00586 return EDataType( (int) kEnum );
00587
00588 std::string shortName = TClassEdit::ShortType( ti.TrueName(), 1 );
00589
00590 const std::string& cpd = Compound( name );
00591 const int mask = cpd == "*" ? kPtrMask : 0;
00592
00593 if ( shortName == "bool" )
00594 effType = EDataType( (int) kBool | mask );
00595 else if ( shortName == "char" )
00596 effType = EDataType( (int) kChar | mask );
00597 else if ( shortName == "short" )
00598 effType = EDataType( (int) kShort | mask );
00599 else if ( shortName == "int" )
00600 effType = EDataType( (int) kInt | mask );
00601 else if ( shortName == "unsigned int" )
00602 effType = EDataType( (int) kUInt | mask );
00603 else if ( shortName == "long" )
00604 effType = EDataType( (int) kLong | mask );
00605 else if ( shortName == "unsigned long" )
00606 effType = EDataType( (int) kULong | mask );
00607 else if ( shortName == "long long" )
00608 effType = EDataType( (int) kLongLong | mask );
00609 else if ( shortName == "float" )
00610 effType = EDataType( (int) kFloat | mask );
00611 else if ( shortName == "double" )
00612 effType = EDataType( (int) kDouble | mask );
00613 else if ( shortName == "void" )
00614 effType = EDataType( (int) kVoid | mask );
00615 else if ( shortName == "string" && cpd == "" )
00616 effType = kSTLString;
00617 else if ( name == "#define" ) {
00618 effType = kMacro;
00619 }
00620 else
00621 effType = kOther;
00622
00623 return effType;
00624 }
00625
00626
00627 const std::string PyROOT::Utility::Compound( const std::string& name )
00628 {
00629 std::string cleanName = name;
00630 std::string::size_type spos = std::string::npos;
00631 while ( ( spos = cleanName.find( "const" ) ) != std::string::npos ) {
00632 cleanName.swap( cleanName.erase( spos, 5 ) );
00633 }
00634
00635 std::string compound = "";
00636 for ( int ipos = (int)cleanName.size()-1; 0 <= ipos; --ipos ) {
00637 char c = cleanName[ipos];
00638 if ( isspace( c ) ) continue;
00639 if ( isalnum( c ) || c == '_' || c == '>' ) break;
00640
00641 compound = c + compound;
00642 }
00643
00644 return compound;
00645 }
00646
00647
00648 const std::string PyROOT::Utility::ClassName( PyObject* pyobj )
00649 {
00650 std::string clname = "<unknown>";
00651 PyObject* pyclass = PyObject_GetAttr( pyobj, PyStrings::gClass );
00652 if ( pyclass != 0 ) {
00653 PyObject* pyname = PyObject_GetAttr( pyclass, PyStrings::gName );
00654
00655 if ( pyname != 0 ) {
00656 clname = PyROOT_PyUnicode_AsString( pyname );
00657 Py_DECREF( pyname );
00658 } else
00659 PyErr_Clear();
00660
00661 Py_DECREF( pyclass );
00662 } else
00663 PyErr_Clear();
00664
00665 return clname;
00666 }
00667
00668
00669 void PyROOT::Utility::ErrMsgCallback( char* msg )
00670 {
00671
00672
00673
00674 if ( strstr( msg, "error recovered" ) )
00675 return;
00676
00677
00678 if ( strstr( msg, "FILE:" ) )
00679 return;
00680
00681
00682 char* errFile = (char*)G__stripfilename( G__get_ifile()->name );
00683 int errLine = G__get_ifile()->line_number;
00684
00685
00686 char buf[256];
00687 snprintf( buf, 256, "%s:%d:", errFile, errLine );
00688 if ( strstr( msg, buf ) )
00689 return;
00690
00691
00692 int len = strlen( msg );
00693 if ( msg[ len-1 ] == '\n' )
00694 msg[ len-1 ] = '\0';
00695
00696
00697 if ( PyErr_Occurred() ) {
00698 PyObject *etype, *value, *trace;
00699 PyErr_Fetch( &etype, &value, &trace );
00700
00701
00702 if ( PyROOT_PyUnicode_Check( value ) ) {
00703 if ( ! PyErr_GivenExceptionMatches( etype, PyExc_IndexError ) )
00704 PyROOT_PyUnicode_AppendAndDel( &value, PyROOT_PyUnicode_FromString( (char*)"\n " ) );
00705 PyROOT_PyUnicode_AppendAndDel( &value, PyROOT_PyUnicode_FromString( msg ) );
00706 }
00707
00708 PyErr_Restore( etype, value, trace );
00709 return;
00710 }
00711
00712
00713 char* format = (char*)"(file \"%s\", line %d) %s";
00714 char* p = 0;
00715 if ( ( p = strstr( msg, "Syntax Error:" ) ) )
00716 PyErr_Format( PyExc_SyntaxError, format, errFile, errLine, p+14 );
00717 else if ( ( p = strstr( msg, "Error: Array" ) ) )
00718 PyErr_Format( PyExc_IndexError, format, errFile, errLine, p+12 );
00719 else if ( ( p = strstr( msg, "Error:" ) ) )
00720 PyErr_Format( PyExc_RuntimeError, format, errFile, errLine, p+7 );
00721 else if ( ( p = strstr( msg, "Exception:" ) ) )
00722 PyErr_Format( PyExc_RuntimeError, format, errFile, errLine, p+11 );
00723 else if ( ( p = strstr( msg, "Limitation:" ) ) )
00724 PyErr_Format( PyExc_NotImplementedError, format, errFile, errLine, p+12 );
00725 else if ( ( p = strstr( msg, "Internal Error: malloc" ) ) )
00726 PyErr_Format( PyExc_MemoryError, format, errFile, errLine, p+23 );
00727 else if ( ( p = strstr( msg, "Internal Error:" ) ) )
00728 PyErr_Format( PyExc_SystemError, format, errFile, errLine, p+16 );
00729 else if ( ( p = strstr( msg, "Warning:" ) ) )
00730
00731 PyErr_WarnExplicit( NULL, p+9, errFile, errLine, (char*)"CINT", NULL );
00732 else if ( ( p = strstr( msg, "Note:" ) ) )
00733 fprintf( stdout, "Note: (file \"%s\", line %d) %s\n", errFile, errLine, p+6 );
00734 else
00735 fprintf( stdout, "Message: (file \"%s\", line %d) %s\n", errFile, errLine, msg );
00736 }
00737
00738
00739 void PyROOT::Utility::ErrMsgHandler( int level, Bool_t abort, const char* location, const char* msg )
00740 {
00741
00742
00743
00744 if ( gErrorIgnoreLevel == kUnset )
00745 ::DefaultErrorHandler( kUnset - 1, kFALSE, "", "" );
00746
00747 if ( level < gErrorIgnoreLevel )
00748 return;
00749
00750
00751 if (level >= kError)
00752 ::DefaultErrorHandler( level, abort, location, msg );
00753 else if ( level >= kWarning ) {
00754
00755 PyErr_WarnExplicit( NULL, (char*)msg, (char*)location, 0, (char*)"ROOT", NULL );
00756 }
00757 else
00758 ::DefaultErrorHandler( level, abort, location, msg );
00759 }
00760
00761
00762
00763 Long_t PyROOT::Utility::InstallMethod( G__ClassInfo* scope, PyObject* callback,
00764 const std::string& mtName, const char* rtype, const char* signature,
00765 void* func, Int_t npar, Long_t extra )
00766 {
00767 static Long_t s_fid = (Long_t)PyROOT::Utility::InstallMethod;
00768 ++s_fid;
00769
00770
00771
00772 if ( ! PyCallable_Check( callback ) )
00773 return 0;
00774
00775
00776 G__linked_taginfo pti;
00777 pti.tagnum = -1;
00778 pti.tagtype = 'c';
00779 std::string tagname;
00780 if ( rtype ) {
00781 tagname = rtype;
00782 } else {
00783 const char* cname = scope ? scope->Fullname() : 0;
00784 tagname = cname ? std::string( cname ) + "::" + mtName : mtName;
00785 }
00786 pti.tagname = tagname.c_str();
00787 int tagnum = G__get_linked_tagnum( &pti );
00788
00789 if ( scope ) {
00790 G__MethodInfo meth = scope->AddMethod( pti.tagname, mtName.c_str(), signature, 0, 0, func );
00791 } else {
00792
00793
00794
00795 Long_t hash = 0, len = 0;
00796 G__hash( mtName.c_str(), hash, len );
00797 G__lastifuncposition();
00798 G__memfunc_setup( mtName.c_str(), hash,
00799 (G__InterfaceMethod)func, tagnum, tagnum, tagnum, 0, npar, 0, 1, 0, signature, (char*)0, (void*)s_fid, 0 );
00800 G__resetifuncposition();
00801
00802
00803
00804 G__MethodInfo meth = G__ClassInfo().AddMethod( mtName.c_str(), mtName.c_str(), signature, 1, 0, func );
00805 }
00806
00807
00808 Py_INCREF( callback );
00809 std::map< int, CallInfo_t >::iterator old = s_PyObjectCallbacks.find( tagnum );
00810 if ( old != s_PyObjectCallbacks.end() ) {
00811 PyObject* oldp = old->second.first;
00812 Py_XDECREF( oldp );
00813 }
00814 s_PyObjectCallbacks[ tagnum ] = std::make_pair( callback, extra );
00815
00816
00817 return s_fid;
00818 }
00819
00820
00821 PyObject* PyROOT::Utility::GetInstalledMethod( int tagnum, Long_t* extra )
00822 {
00823
00824 CallInfo_t cinfo = s_PyObjectCallbacks[ tagnum ];
00825 if ( extra )
00826 *extra = cinfo.second;
00827 return cinfo.first;
00828 }
00829
00830
00831 PyObject* PyROOT::Utility::PyErr_Occurred_WithGIL()
00832 {
00833
00834
00835
00836 #if PY_VERSION_HEX >= 0x02030000
00837 PyGILState_STATE gstate = PyGILState_Ensure();
00838 PyObject* e = PyErr_Occurred();
00839 PyGILState_Release( gstate );
00840 #else
00841 if ( PyThreadState_GET() )
00842 return PyErr_Occurred();
00843 PyObject* e = 0;
00844 #endif
00845
00846 return e;
00847 }