#include "PyROOT.h"
#include "PyStrings.h"
#include "TPython.h"
#include "ObjectProxy.h"
#include "MethodProxy.h"
#include "RootWrapper.h"
#include "TPyClassGenerator.h"
#include "TROOT.h"
#include "TClassRef.h"
#include "TObject.h"
#include <stdio.h>
#include <Riostream.h>
#include <string>
ClassImp(TPython)
static PyObject* gMainDict = 0;
namespace PyROOT {
R__EXTERN PyObject* gRootModule;
}
Bool_t TPython::Initialize()
{
static Bool_t isInitialized = kFALSE;
if ( isInitialized )
return kTRUE;
if ( ! Py_IsInitialized() ) {
PyEval_InitThreads();
Py_Initialize();
if ( ! Py_IsInitialized() ) {
std::cerr << "Error: python has not been intialized; returning." << std::endl;
return kFALSE;
}
#if PY_VERSION_HEX < 0x03000000
char* argv[] = { const_cast< char* >( "root" ) };
#else
wchar_t* argv[] = { const_cast< wchar_t* >( L"root" ) };
#endif
PySys_SetArgv( sizeof(argv)/sizeof(argv[0]), argv );
PyRun_SimpleString( const_cast< char* >( "import ROOT" ) );
}
if ( ! gMainDict ) {
gMainDict = PyModule_GetDict(
PyImport_AddModule( const_cast< char* >( "__main__" ) ) );
Py_INCREF( gMainDict );
}
gROOT->AddClassGenerator( new TPyClassGenerator );
isInitialized = kTRUE;
return kTRUE;
}
Bool_t TPython::Import( const char* mod_name )
{
if ( ! Initialize() )
return kFALSE;
PyObject* mod = PyImport_ImportModule( mod_name );
if ( ! mod ) {
PyErr_Print();
return kFALSE;
}
Py_INCREF( mod );
PyModule_AddObject( PyROOT::gRootModule, mod_name, mod );
TClass::GetClass( mod_name, kTRUE );
PyObject* dct = PyModule_GetDict( mod );
PyObject* values = PyDict_Values( dct );
for ( int i = 0; i < PyList_GET_SIZE( values ); ++i ) {
PyObject* value = PyList_GET_ITEM( values, i );
Py_INCREF( value );
if ( PyClass_Check( value ) || PyObject_HasAttr( value, PyROOT::PyStrings::gBases ) ) {
PyObject* pyClName = PyObject_GetAttr( value, PyROOT::PyStrings::gName );
if ( PyErr_Occurred() )
PyErr_Clear();
std::string fullname = mod_name;
fullname += ".";
fullname += PyROOT_PyUnicode_AsString( pyClName );
TClass::GetClass( fullname.c_str(), kTRUE );
Py_XDECREF( pyClName );
}
Py_DECREF( value );
}
Py_DECREF( values );
if ( PyErr_Occurred() )
return kFALSE;
return kTRUE;
}
void TPython::LoadMacro( const char* name )
{
if ( ! Initialize() )
return;
PyObject* old = PyDict_Values( gMainDict );
Exec( (std::string( "execfile(\"" ) + name + "\")").c_str() );
PyObject* current = PyDict_Values( gMainDict );
for ( int i = 0; i < PyList_GET_SIZE( current ); ++i ) {
PyObject* value = PyList_GET_ITEM( current, i );
Py_INCREF( value );
if ( ! PySequence_Contains( old, value ) ) {
if ( PyClass_Check( value ) || PyObject_HasAttr( value, PyROOT::PyStrings::gBases ) ) {
PyObject* pyModName = PyObject_GetAttr( value, PyROOT::PyStrings::gModule );
PyObject* pyClName = PyObject_GetAttr( value, PyROOT::PyStrings::gName );
if ( PyErr_Occurred() )
PyErr_Clear();
if ( (pyModName && pyClName) &&\
( (PyBytes_CheckExact( pyModName ) && PyBytes_CheckExact( pyClName )) ||\
(PyBytes_Check( pyModName ) && PyBytes_Check( pyClName ))\
) ) {
std::string fullname = PyROOT_PyUnicode_AsString( pyModName );
fullname += '.';
fullname += PyROOT_PyUnicode_AsString( pyClName );
TClass::GetClass( fullname.c_str(), kTRUE );
}
Py_XDECREF( pyClName );
Py_XDECREF( pyModName );
}
}
Py_DECREF( value );
}
Py_DECREF( current );
Py_DECREF( old );
}
void TPython::ExecScript( const char* name, int argc, const char**
#if PY_VERSION_HEX < 0x03000000
argv
#endif
)
{
if ( ! Initialize() )
return;
if ( ! name ) {
std::cerr << "Error: no file name specified." << std::endl;
return;
}
FILE* fp = fopen( name, "r" );
if ( ! fp ) {
std::cerr << "Error: could not open file \"" << name << "\"." << std::endl;
return;
}
PyObject* oldargv = PySys_GetObject( const_cast< char* >( "argv" ) );
if ( ! oldargv )
PyErr_Clear();
else {
PyObject* l = PyList_New( PyList_GET_SIZE( oldargv ) );
for ( int i = 0; i < PyList_GET_SIZE( oldargv ); ++i ) {
PyObject* item = PyList_GET_ITEM( oldargv, i );
Py_INCREF( item );
PyList_SET_ITEM( l, i, item );
}
oldargv = l;
}
argc += 1;
#if PY_VERSION_HEX < 0x03000000
const char** argv2 = new const char*[ argc ];
for ( int i = 1; i < argc; ++i ) argv2[ i ] = argv[ i-1 ];
argv2[ 0 ] = Py_GetProgramName();
PySys_SetArgv( argc, const_cast< char** >( argv2 ) );
delete [] argv2;
#else
#endif
PyObject* gbl = PyDict_Copy( gMainDict );
PyObject* result =
PyRun_FileEx( fp, const_cast< char* >( name ), Py_file_input, gbl, gbl, 1 );
if ( ! result )
PyErr_Print();
Py_XDECREF( result );
Py_DECREF( gbl );
if ( oldargv ) {
PySys_SetObject( const_cast< char* >( "argv" ), oldargv );
Py_DECREF( oldargv );
}
}
Bool_t TPython::Exec( const char* cmd )
{
if ( ! Initialize() )
return kFALSE;
PyObject* result =
PyRun_String( const_cast< char* >( cmd ), Py_file_input, gMainDict, gMainDict );
if ( result ) {
Py_DECREF( result );
return kTRUE;
} else {
PyErr_Print();
return kFALSE;
}
}
const TPyReturn TPython::Eval( const char* expr )
{
if ( ! Initialize() )
return TPyReturn();
PyObject* result =
PyRun_String( const_cast< char* >( expr ), Py_eval_input, gMainDict, gMainDict );
if ( ! result ) {
PyErr_Print();
return TPyReturn();
}
if ( result == Py_None || PyROOT::ObjectProxy_Check( result ) ||
PyBytes_Check( result ) ||
PyFloat_Check( result ) || PyLong_Check( result ) || PyInt_Check( result ) )
return TPyReturn( result );
PyObject* pyclass = PyObject_GetAttr( result, PyROOT::PyStrings::gClass );
if ( pyclass != 0 ) {
PyObject* name = PyObject_GetAttr( pyclass, PyROOT::PyStrings::gName );
PyObject* module = PyObject_GetAttr( pyclass, PyROOT::PyStrings::gModule );
std::string qname =
std::string( PyROOT_PyUnicode_AsString( module ) ) + '.' + PyROOT_PyUnicode_AsString( name );
Py_DECREF( module );
Py_DECREF( name );
Py_DECREF( pyclass );
TClass* klass = TClass::GetClass( qname.c_str() );
if ( klass != 0 )
return TPyReturn( result );
} else
PyErr_Clear();
Py_DECREF( result );
return TPyReturn();
}
Bool_t TPython::Bind( TObject* object, const char* label )
{
if ( ! ( object && Initialize() ) )
return kFALSE;
TClass* klass = object->IsA();
if ( klass != 0 ) {
PyObject* bound = PyROOT::BindCppObject( (void*)object, klass->GetName() );
if ( bound ) {
Bool_t bOk = PyDict_SetItemString( gMainDict, const_cast< char* >( label ), bound ) == 0;
Py_DECREF( bound );
return bOk;
}
}
return kFALSE;
}
void TPython::Prompt() {
if ( ! Initialize() ) {
return;
}
PyRun_InteractiveLoop( stdin, const_cast< char* >( "\0" ) );
}
Bool_t TPython::ObjectProxy_Check( PyObject* pyobject )
{
if ( ! Initialize() )
return kFALSE;
return PyROOT::ObjectProxy_Check( pyobject );
}
Bool_t TPython::ObjectProxy_CheckExact( PyObject* pyobject )
{
if ( ! Initialize() )
return kFALSE;
return PyROOT::ObjectProxy_CheckExact( pyobject );
}
Bool_t TPython::MethodProxy_Check( PyObject* pyobject )
{
if ( ! Initialize() )
return kFALSE;
return PyROOT::MethodProxy_Check( pyobject );
}
Bool_t TPython::MethodProxy_CheckExact( PyObject* pyobject )
{
if ( ! Initialize() )
return kFALSE;
return PyROOT::MethodProxy_CheckExact( pyobject );
}
void* TPython::ObjectProxy_AsVoidPtr( PyObject* pyobject )
{
if ( ! Initialize() )
return 0;
if ( ! PyROOT::ObjectProxy_Check( pyobject ) )
return 0;
return ((PyROOT::ObjectProxy*)pyobject)->GetObject();
}
PyObject* TPython::ObjectProxy_FromVoidPtr(
void* addr, const char* classname, Bool_t python_owns )
{
if ( ! Initialize() )
return 0;
PyObject* pyobject = PyROOT::BindCppObjectNoCast( addr, Cppyy::GetScope( classname ), kFALSE );
if ( python_owns && PyROOT::ObjectProxy_Check( pyobject ) )
((PyROOT::ObjectProxy*)pyobject)->HoldOn();
return pyobject;
}