diff --git a/pyroot/ROOT.py b/pyroot/ROOT.py index d26294fee7dd7900c616a218818fa8724eff3352..baecc2a9a59d8fb94c1e3f2d64cca62aa71e7038 100755 --- a/pyroot/ROOT.py +++ b/pyroot/ROOT.py @@ -1,4 +1,4 @@ -# @(#)root/pyroot:$Name: $:$Id: ROOT.py,v 1.34 2005/12/07 06:16:16 brun Exp $ +# @(#)root/pyroot:$Name: $:$Id: ROOT.py,v 1.35 2006/01/03 08:50:19 brun Exp $ # Author: Wim Lavrijsen (WLavrijsen@lbl.gov) # Created: 02/20/03 # Last: 01/02/06 @@ -78,15 +78,24 @@ if needsGlobal: sys.setdlopenflags( dlflags ) del needsGlobal -## normally, you'll want a ROOT application; fine if one pre-exists from C++ -InitRootApplication() +## choose interactive-favoured policies +SetMemoryPolicy( kMemoryHeuristics ) +SetSignalPolicy( kSignalSafe ) + +## normally, you'll want a ROOT application; don't init any further if +## one pre-exists from some C++ code somewhere +c = MakeRootClass( 'PyROOT::TPyROOTApplication' ) +if c.CreatePyROOTApplication(): + c.InitROOTGlobals() + c.InitCINTMessageCallback(); +del c ## 2.2 has 10 instructions as default, 2.3 has 100 ... make same sys.setcheckinterval( 100 ) ### data ________________________________________________________________________ -__version__ = '3.3.0' +__version__ = '4.0.0' __author__ = 'Wim Lavrijsen (WLavrijsen@lbl.gov)' __pseudo__all__ = [ 'gROOT', 'gSystem', 'gInterpreter', 'gPad', 'gVirtualX', @@ -95,15 +104,9 @@ __all__ = [] # purposedly empty _orig_ehook = sys.excepthook -## for setting memory policies; not exported +## for setting memory and speed policies; not exported _memPolicyAPI = [ 'SetMemoryPolicy', 'SetOwnership', 'kMemoryHeuristics', 'kMemoryStrict' ] -kMemoryHeuristics = 1 -kMemoryStrict = 2 - -## speed hack _sigPolicyAPI = [ 'SetSignalPolicy', 'kSignalFast', 'kSignalSafe' ] -kSignalFast = 1 -kSignalSafe = 2 ### helpers --------------------------------------------------------------------- @@ -114,12 +117,6 @@ def split( str ): else: return str, '' -def safeLookupCall( func, arg ): - try: - return func( arg ) - except: - return None - ### template support ------------------------------------------------------------ class Template: @@ -145,7 +142,7 @@ class std: ### special cases for gPad, gVirtualX (are C++ macro's) ------------------------- class _ExpandMacroFunction( object ): def __init__( self, klass, func ): - c = makeRootClass( klass ) + c = MakeRootClass( klass ) self.func = getattr( c, func ) def __getattr__( self, what ): @@ -242,6 +239,7 @@ def _processRootEvents( controller ): class ModuleFacade( object ): def __init__( self, module ): self.module = module + self.libmodule = sys.modules[ 'libPyROOT' ] # root thread to prevent GUIs from starving if not self.module.gROOT.IsBatch(): @@ -268,36 +266,25 @@ class ModuleFacade( object ): for name in self.module.__pseudo__all__: caller.__dict__[ name ] = getattr( self.module, name ) - sys.modules[ 'libPyROOT' ].gPad = gPad + self.libmodule.gPad = gPad # make the distionary of the calling module ROOT lazy - self.module.setRootLazyLookup( caller.__dict__ ) + self.module.SetRootLazyLookup( caller.__dict__ ) # the actual __all__ is empty return self.module.__all__ - # block search for privates - if name[0:2] == '__': - raise AttributeError( name ) - - # attempt to construct "name" as a ROOT class - attr = safeLookupCall( makeRootClass, name ) - if ( attr == None ): - # no such class ... try global variable or global enum - attr = safeLookupCall( getRootGlobal, name ) - - if ( attr == None ): - # no global either ... try through gROOT (e.g. objects from files) - attr = gROOT.FindObject( name ) - - # if available, cache attribute as appropriate, so we don't come back - if attr != None: - if type(attr) == PropertyProxy: - setattr( self.__class__, name, attr ) # descriptor - return getattr( self, name ) - else: - self.__dict__[ name ] = attr # normal member - return attr + # lookup into ROOT (which may cause python-side enum/class/global creation) + attr = self.libmodule.LookupRootEntity( name ) + + # the call above will raise AttributeError as necessary; so if we get here, + # attr is valid: cache as appropriate, so we don't come back + if type(attr) == PropertyProxy: + setattr( self.__class__, name, attr ) # descriptor + return getattr( self, name ) + else: + self.__dict__[ name ] = attr # normal member + return attr # reaching this point means failure ... raise AttributeError( name ) @@ -322,6 +309,7 @@ def cleanup(): facade.keeppolling = 0 # destroy ROOT module + del facade.libmodule del sys.modules[ 'libPyROOT' ] del facade.module diff --git a/pyroot/inc/LinkDef.h b/pyroot/inc/LinkDef.h index 064eb7f343be57804e2be78ff72833e572afb27c..485633bcff913d0678f8be482d6fe48315cec40d 100644 --- a/pyroot/inc/LinkDef.h +++ b/pyroot/inc/LinkDef.h @@ -6,6 +6,9 @@ #pragma link C++ class TPython; #pragma link C++ class TPyReturn; + +#pragma link C++ namespace PyROOT; #pragma link C++ class PyROOT::TPyException; +#pragma link C++ class PyROOT::TPyROOTApplication; #endif diff --git a/pyroot/inc/TPyException.h b/pyroot/inc/TPyException.h index 7ae4401b9ddb32309623fc3cb0a544601c0d8191..4109465823e16edcf7292b0829548acdcbf8db20 100644 --- a/pyroot/inc/TPyException.h +++ b/pyroot/inc/TPyException.h @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: TPyException.h,v 1.2 2005/03/04 18:44:14 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: TPyException.h,v 1.3 2005/05/06 10:08:53 brun Exp $ // Author: Scott Snyder, Apr 2004 #ifndef ROOT_TPyException @@ -40,14 +40,10 @@ // Standard #include <exception> -// Python -struct _object; -typedef _object PyObject; - namespace PyROOT { -R__EXTERN PyObject* TPyExceptionMagic; +R__EXTERN void* TPyExceptionMagic; class TPyException : public std::exception { public: diff --git a/pyroot/inc/TPyROOTApplication.h b/pyroot/inc/TPyROOTApplication.h new file mode 100644 index 0000000000000000000000000000000000000000..edfc2184b918aaee4585b9176eb6170dfa4bbf27 --- /dev/null +++ b/pyroot/inc/TPyROOTApplication.h @@ -0,0 +1,40 @@ +// Author: Wim Lavrijsen February 2006 + +#ifndef ROOT_TPyROOTApplication +#define ROOT_TPyROOTApplication + +////////////////////////////////////////////////////////////////////////////// +// // +// TPyROOTApplication // +// // +// Setup interactive application. // +// // +////////////////////////////////////////////////////////////////////////////// + + +// ROOT +#ifndef ROOT_TApplication +#include "TApplication.h" +#endif + + +namespace PyROOT { + +class TPyROOTApplication : public TApplication { +public: + static Bool_t CreatePyROOTApplication( Bool_t bLoadLibs = kTRUE ); + + static Bool_t InitROOTGlobals(); + static Bool_t InitCINTMessageCallback(); + +public: + TPyROOTApplication( + const char* acn, Int_t* argc, char** argv, Bool_t bLoadLibs = kTRUE ); + + virtual ~TPyROOTApplication() { } + ClassDef(TPyROOTApplication,0) //Setup interactive application +}; + +} // namespace PyROOT + +#endif diff --git a/pyroot/src/ConstructorHolder.cxx b/pyroot/src/ConstructorHolder.cxx index 08c19176edd9570329d533d065950b915762d4b5..fa95842ecbd4bf3cd650ffd45907e7cfd76d9449 100644 --- a/pyroot/src/ConstructorHolder.cxx +++ b/pyroot/src/ConstructorHolder.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: ConstructorHolder.cxx,v 1.6 2005/06/10 14:30:22 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: ConstructorHolder.cxx,v 1.7 2005/09/09 05:19:10 brun Exp $ // Author: Wim Lavrijsen, Apr 2004 // Bindings @@ -94,8 +94,9 @@ PyObject* PyROOT::TConstructorHolder::operator()( ObjectProxy* self, PyObject* a return Py_None; // by definition } - PyErr_SetString( PyExc_TypeError, const_cast< char* >( - ( std::string( klass->GetName() ) + " constructor failed" ).c_str() ) ); + if ( ! PyErr_Occurred() ) // should be set, otherwise write a generic error msg + PyErr_SetString( PyExc_TypeError, const_cast< char* >( + ( std::string( klass->GetName() ) + " constructor failed" ).c_str() ) ); // do not throw an exception, '0' might trigger the overload handler to choose a // different constructor, which if all fails will throw an exception diff --git a/pyroot/src/Converters.cxx b/pyroot/src/Converters.cxx index 391b1556b3fe6905d8a03bc3c07709153d33641c..9a7c088250fb079d5f2b632fe1858f7ddfa8b164 100644 --- a/pyroot/src/Converters.cxx +++ b/pyroot/src/Converters.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: Converters.cxx,v 1.24 2005/12/05 17:40:54 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: Converters.cxx,v 1.25 2005/12/07 06:16:16 brun Exp $ // Author: Wim Lavrijsen, Jan 2005 // Bindings @@ -75,41 +75,41 @@ Bool_t PyROOT::T##name##Converter::SetArg( PyObject* pyobject, G__CallFunc* func if ( PyString_Check( pyobject ) ) { \ if ( PyString_GET_SIZE( pyobject ) == 1 ) \ func->SetArg( (Long_t)PyString_AS_STRING( pyobject )[0] ); \ - else \ + else { \ PyErr_Format( PyExc_TypeError, \ #type" expected, got string of size %d", PyString_GET_SIZE( pyobject ) );\ - } else { \ - Long_t l = PyLong_AsLong( pyobject ); \ - if ( PyErr_Occurred() ) \ - return kFALSE; \ - if ( ! ( low <= l && l <= high ) ) { \ + return kFALSE; \ + } \ + } else { \ + Long_t l = PyLong_AsLong( pyobject ); \ + if ( PyErr_Occurred() ) \ + return kFALSE; \ + if ( ! ( low <= l && l <= high ) ) { \ PyErr_SetString( PyExc_ValueError, "integer to character: value out of range" );\ - return kFALSE; \ - } \ - func->SetArg( l ); \ - } \ - return kTRUE; \ -} \ - \ -PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \ -{ \ - return PyString_FromFormat( "%c", *((type*)address) ); \ -} \ - \ -Bool_t PyROOT::T##name##Converter::ToMemory( PyObject* value, void* address )\ -{ \ - const char* buf = PyString_AsString( value ); \ - if ( PyErr_Occurred() ) \ - return kFALSE; \ - \ - int len = strlen( buf ); \ - if ( len != 1 ) { \ + return kFALSE; \ + } \ + func->SetArg( l ); \ + } \ + return kTRUE; \ +} \ + \ +PyObject* PyROOT::T##name##Converter::FromMemory( void* address ) \ +{ \ + return PyString_FromFormat( "%c", *((type*)address) ); \ +} \ + \ +Bool_t PyROOT::T##name##Converter::ToMemory( PyObject* value, void* address ) \ +{ \ + const char* buf = PyString_AsString( value ); \ + if ( PyErr_Occurred() ) \ + return kFALSE; \ + int len = strlen( buf ); \ + if ( len != 1 ) { \ PyErr_Format( PyExc_TypeError, #type" expected, got string of size %d", len );\ - return kFALSE; \ - } \ - \ - *((type*)address) = (type)buf[0]; \ - return kTRUE; \ + return kFALSE; \ + } \ + *((type*)address) = (type)buf[0]; \ + return kTRUE; \ } @@ -613,6 +613,7 @@ Bool_t PyROOT::T##name##Converter::ToMemory( PyObject* value, void* address ) \ PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER( TString, TString, Data ) PYROOT_IMPLEMENT_STRING_AS_PRIMITIVE_CONVERTER( STLString, std::string, c_str ) +static int kaas = 0; //____________________________________________________________________________ Bool_t PyROOT::TRootObjectConverter::SetArg( PyObject* pyobject, G__CallFunc* func ) { @@ -638,7 +639,7 @@ Bool_t PyROOT::TRootObjectConverter::SetArg( PyObject* pyobject, G__CallFunc* fu G__ClassInfo* clFormalInfo = fClass->GetClassInfo(); G__ClassInfo* clActualInfo = pyobj->ObjectIsA()->GetClassInfo(); Long_t offset = 0; - if ( clFormalInfo && clActualInfo ) + if ( clFormalInfo && clActualInfo && clFormalInfo != clActualInfo ) offset = G__isanybase( clFormalInfo->Tagnum(), clActualInfo->Tagnum(), (Long_t)obj ); // set pointer (may be null) and declare success diff --git a/pyroot/src/MethodHolder.cxx b/pyroot/src/MethodHolder.cxx index 55d3b9324c327fc48588706b4997d6afc7c1ec57..646a20ba3a63d52f66bb68363deee460e15e85f7 100644 --- a/pyroot/src/MethodHolder.cxx +++ b/pyroot/src/MethodHolder.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: MethodHolder.cxx,v 1.43 2005/12/03 04:00:15 pcanal Exp $ +// @(#)root/pyroot:$Name: $:$Id: MethodHolder.cxx,v 1.44 2005/12/06 11:47:09 brun Exp $ // Author: Wim Lavrijsen, Apr 2004 // Bindings @@ -32,7 +32,7 @@ #include <string> -//- local helpers ------------------------------------------------------------ +//- data and local helpers --------------------------------------------------- namespace { // CINT temp level guard @@ -96,7 +96,7 @@ inline PyObject* PyROOT::TMethodHolder::CallFast( void* self ) try { // C++ try block result = fExecutor->Execute( fMethodCall, (void*)((Long_t)self + fOffset) ); } catch ( TPyException& ) { - result = TPyExceptionMagic; + result = (PyObject*)TPyExceptionMagic; } catch ( std::exception& e ) { PyErr_Format( PyExc_Exception, "%s (C++ exception)", e.what() ); result = 0; @@ -257,6 +257,31 @@ PyObject* PyROOT::TMethodHolder::GetDocString() ( fMethod->Property() & G__BIT_ISSTATIC ) ? "static " : "", fMethod->GetPrototype() ); } +//____________________________________________________________________________ +Int_t PyROOT::TMethodHolder::GetPriority() +{ +// Method priorities exist (in lieu of true overloading) there to prevent +// void* or <unknown>* from usurping otherwise valid calls. TODO: extend this +// to favour classes that are not bases. + + Int_t priority = 0; + + TIter nextarg( fMethod->GetListOfMethodArgs() ); + while ( TMethodArg* arg = (TMethodArg*)nextarg() ) { + G__TypeInfo ti( arg->GetFullTypeName() ); + + if ( ! ti.IsValid() ) + priority -= 1000; // class is gibberish + else if ( (ti.Property() & (kIsClass|kIsStruct)) && ! ti.IsLoaded() ) + priority -= 100; // class is known, but no dictionary available + else if ( TClassEdit::CleanType( ti.TrueName(), 1 ) == "void*" ) + priority -= 10; // void* shouldn't be too greedy + + } + + return priority; +} + //____________________________________________________________________________ Bool_t PyROOT::TMethodHolder::Initialize() { diff --git a/pyroot/src/MethodHolder.h b/pyroot/src/MethodHolder.h index 2b9f365a7d035fad8ab35a91fa5e88c7eb4ae563..80256a6eb1c3082fe6aa08e72add5e35b94e4622 100644 --- a/pyroot/src/MethodHolder.h +++ b/pyroot/src/MethodHolder.h @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: MethodHolder.h,v 1.17 2005/10/25 05:13:15 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: MethodHolder.h,v 1.18 2005/12/06 11:47:09 brun Exp $ // Author: Wim Lavrijsen, Apr 2004 #ifndef PYROOT_TMETHODHOLDER_H @@ -26,7 +26,7 @@ namespace PyROOT { /** Python side ROOT method @author WLAV @date 05/06/2004 - @version 2.0 + @version 2.1 */ class TExecutor; @@ -42,6 +42,7 @@ namespace PyROOT { public: virtual PyObject* GetDocString(); + virtual Int_t GetPriority(); public: virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject* kwds ); diff --git a/pyroot/src/MethodProxy.cxx b/pyroot/src/MethodProxy.cxx index f7ebdcf9662d863e6cb28801e61fbb4929f4e2fc..198e5ce33d1edc77a5a674fa866822d6933fd8f2 100644 --- a/pyroot/src/MethodProxy.cxx +++ b/pyroot/src/MethodProxy.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: MethodProxy.cxx,v 1.8 2005/08/10 05:25:41 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: MethodProxy.cxx,v 1.9 2005/09/09 05:19:10 brun Exp $ // Author: Wim Lavrijsen, Jan 2005 // Bindings @@ -9,6 +9,7 @@ #include "TPyException.h" // Standard +#include <algorithm> #include <functional> #include <vector> #include <algorithm> @@ -47,6 +48,11 @@ namespace { return hash; } +// helper to sort on method priority + int PriorityCmp( PyCallable* left, PyCallable* right ) + { + return left->GetPriority() > right->GetPriority(); + } //= PyROOT method proxy object behaviour ===================================== PyObject* mp_name( MethodProxy* meth, void* ) @@ -108,7 +114,7 @@ namespace { Int_t index = m->second; PyObject* result = (*methods[ index ])( meth->fSelf, args, kwds ); - if ( result == TPyExceptionMagic ) + if ( result == (PyObject*)TPyExceptionMagic ) return 0; // exception info was already set if ( result != 0 ) @@ -119,11 +125,16 @@ namespace { } // ... otherwise loop over all methods and find the one that does not fail + if ( ! meth->fMethodInfo->fIsSorted ) { + std::stable_sort( methods.begin(), methods.end(), PriorityCmp ); + meth->fMethodInfo->fIsSorted = kTRUE; + } + std::vector< PyError_t > errors; for ( Int_t i = 0; i < nMethods; ++i ) { PyObject* result = (*methods[i])( meth->fSelf, args, kwds ); - if ( result == TPyExceptionMagic ) { + if ( result == (PyObject*)TPyExceptionMagic ) { std::for_each( errors.begin(), errors.end(), PyError_t::Clear ); return 0; // exception info was already set } @@ -289,4 +300,5 @@ void PyROOT::MethodProxy::Set( const std::string& name, std::vector< PyCallable* // set method data fMethodInfo->fName = name; fMethodInfo->fMethods.swap( methods ); + fMethodInfo->fIsSorted = kFALSE; } diff --git a/pyroot/src/MethodProxy.h b/pyroot/src/MethodProxy.h index ee8ec19810a6637aa548df3a88eb36e26d6bddb4..a950e138a7d7f4ea1fcbfeff0b46b4e115b2f85e 100644 --- a/pyroot/src/MethodProxy.h +++ b/pyroot/src/MethodProxy.h @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: MethodProxy.h,v 1.2 2005/04/13 05:04:50 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: MethodProxy.h,v 1.3 2005/09/09 05:19:10 brun Exp $ // Author: Wim Lavrijsen, Jan 2005 #ifndef PYROOT_METHODPROXY_H @@ -26,17 +26,18 @@ namespace PyROOT { class MethodProxy { public: - typedef std::map< Long_t, Int_t > DispatchMap_t; + typedef std::map< Long_t, Int_t > DispatchMap_t; typedef std::vector< PyCallable* > Methods_t; struct MethodInfo_t { - MethodInfo_t() { fRefCount = new int(1); } + MethodInfo_t() : fIsSorted( kFALSE ) { fRefCount = new int(1); } ~MethodInfo_t() { delete fRefCount; } std::string fName; MethodProxy::DispatchMap_t fDispatchMap; MethodProxy::Methods_t fMethods; std::string fDoc; + Bool_t fIsSorted; int* fRefCount; }; @@ -45,7 +46,8 @@ namespace PyROOT { void Set( const std::string& name, std::vector< PyCallable* >& methods ); const std::string& GetName() const { return fMethodInfo->fName; } - void AddMethod( PyCallable* pc ) { fMethodInfo->fMethods.push_back( pc ); } + void AddMethod( PyCallable* pc ) { + fMethodInfo->fIsSorted = kFALSE; fMethodInfo->fMethods.push_back( pc ); } public: // public, as the python C-API works with C structs PyObject_HEAD diff --git a/pyroot/src/PyCallable.h b/pyroot/src/PyCallable.h index 8d885940c57194869e0673b721d664f9120aab8c..074d273ab84d97853796b27027e7208249f6ce69 100644 --- a/pyroot/src/PyCallable.h +++ b/pyroot/src/PyCallable.h @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: PyCallable.h,v 1.68 2005/01/28 05:45:41 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: PyCallable.h,v 1.2 2005/03/04 07:44:11 brun Exp $ // Author: Wim Lavrijsen, Aug 2004 #ifndef PYROOT_PYCALLABLE_H @@ -21,6 +21,7 @@ namespace PyROOT { public: virtual PyObject* GetDocString() = 0; + virtual Int_t GetPriority() { return 0; } public: virtual PyObject* operator()( ObjectProxy* self, PyObject* args, PyObject* kwds ) = 0; diff --git a/pyroot/src/Pythonize.cxx b/pyroot/src/Pythonize.cxx index 694ef7df21c96040d24065aa574b60f50d836280..e19e8f9b532d0c68c5404e43ec1a35145375cca9 100644 --- a/pyroot/src/Pythonize.cxx +++ b/pyroot/src/Pythonize.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: Pythonize.cxx,v 1.31 2005/12/03 04:00:15 pcanal Exp $ +// @(#)root/pyroot:$Name: $:$Id: Pythonize.cxx,v 1.33 2005/12/12 18:06:19 brun Exp $ // Author: Wim Lavrijsen, Jul 2004 // Bindings @@ -1300,8 +1300,8 @@ namespace { } } - if ( argc == reqNArgs ) - PyTuple_SET_ITEM( args, reqNArgs, PyInt_FromLong( 0l ) ); + if ( argc == reqNArgs ) // meaning: use default for last value + PyTuple_SET_ITEM( newArgs, reqNArgs, PyInt_FromLong( 0l ) ); // re-run PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs ); diff --git a/pyroot/src/RootModule.cxx b/pyroot/src/RootModule.cxx index e9ca175f52320a446930727cd6947927e20329fe..732348f9e13e7bb854b991b6b60b5480722a9173 100644 --- a/pyroot/src/RootModule.cxx +++ b/pyroot/src/RootModule.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: RootModule.cxx,v 1.20 2005/10/25 05:13:15 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: RootModule.cxx,v 1.21 2005/11/17 06:26:35 brun Exp $ // Author: Wim Lavrijsen, Apr 2004 // Bindings @@ -13,14 +13,7 @@ // ROOT #include "TROOT.h" -#include "TSystem.h" -#include "TInterpreter.h" -#include "TApplication.h" -#include "TBenchmark.h" -#include "TStyle.h" - -// CINT -#include "Api.h" +#include "TObject.h" // Standard #include <string> @@ -35,40 +28,46 @@ namespace { using namespace PyROOT; -//______________________________________________________________________________ - class TPyROOTApplication : public TApplication { - public: - TPyROOTApplication( const char* acn, int* argc, char** argv ) : - TApplication( acn, argc, argv ) +//____________________________________________________________________________ + PyObject* LookupRootEntity( PyObject* pyname, PyObject* args ) + { + if ( ! ( pyname && PyString_CheckExact( pyname ) ) ) + if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "S" ), &pyname ) ) ) + return 0; + + std::string name = PyString_AS_STRING( pyname ); + + // block search for privates + if ( name.size() <= 2 || name.substr( 0, 2 ) != "__" ) { - // follow TRint to minimize differences with CINT - ProcessLine( "#include <iostream>", kTRUE ); - ProcessLine( "#include <_string>", kTRUE ); // for std::string iostream. - ProcessLine( "#include <vector>", kTRUE ); // needed because they're used within the - ProcessLine( "#include <pair>", kTRUE ); // core ROOT dicts and CINT won't be able - // to properly unload these files - - // allow the usage of ClassDef and ClassImp in interpreted macros - ProcessLine( "#include <RtypesCint.h>", kTRUE ); - - // disallow the interpretation of Rtypes.h, TError.h and TGenericClassInfo.h - ProcessLine( "#define ROOT_Rtypes 0", kTRUE ); - ProcessLine( "#define ROOT_TError 0", kTRUE ); - ProcessLine( "#define ROOT_TGenericClassInfo 0", kTRUE ); - - // the following libs are also useful to have, make sure they are loaded... - gROOT->LoadClass("TMinuit", "Minuit"); - gROOT->LoadClass("TPostScript", "Postscript"); - gROOT->LoadClass("THtml", "Html"); - - // save current interpreter context - gInterpreter->SaveContext(); - gInterpreter->SaveGlobalsContext(); - - // prevent ROOT from exiting python - SetReturnFromRun( kTRUE ); + // 1st attempt: look in myself + PyObject* attr = PyObject_GetAttr( gRootModule, pyname ); + if ( attr != 0 ) + return attr; + + // 2nd attempt: construct name as a class + PyErr_Clear(); + attr = MakeRootClassFromString( name ); + if ( attr != 0 ) + return attr; + + // 3rd attempt: lookup name as global variable + PyErr_Clear(); + attr = GetRootGlobalFromString( name ); + if ( attr != 0 ) + return attr; + + // 4th attempt: find existing object (e.g. from file) + PyErr_Clear(); + TObject* object = gROOT->FindObject( name.c_str() ); + if ( object != 0 ) + return BindRootObject( object, object->IsA() ); } - }; + + // still here? raise attribute error + PyErr_Format( PyExc_AttributeError, "%s", name.c_str() ); + return 0; + } //____________________________________________________________________________ PyDictEntry* RootLookDictString( PyDictObject* mp, PyObject* key, Long_t hash ) @@ -83,36 +82,11 @@ namespace { return ep; } - // filter python private variables (C++ discourages __ as variable start) - if ( ! PyString_CheckExact( key ) ) - return ep; - - std::string strkey = PyString_AS_STRING( key ); - if ( 2 < strkey.size() && strkey.substr( 0, 2 ) == "__" ) - return ep; - // all failed, start calling into ROOT gDictLookupActive = kTRUE; // attempt to get ROOT enum/global/class - PyObject* val = PyObject_GetAttr( gRootModule, key ); - - if ( ! val ) { - PyErr_Clear(); - val = MakeRootClassFromString( strkey ); - } - - if ( ! val ) { - PyErr_Clear(); - val = GetRootGlobalFromString( strkey ); - } - - if ( ! val ) { - PyErr_Clear(); - TObject* object = gROOT->FindObject( strkey.c_str() ); - if ( object != 0 ) - val = BindRootObject( object, object->IsA() ); - } + PyObject* val = LookupRootEntity( key, 0 ); if ( val != 0 ) { // success ... @@ -134,7 +108,8 @@ namespace { ep->me_value = val; mp->ma_used++; } - } + } else + PyErr_Clear(); // stopped calling into ROOT gDictLookupActive = kFALSE; @@ -142,44 +117,14 @@ namespace { return ep; } -//____________________________________________________________________________ - PyObject* InitRootApplication() - { - if ( ! gApplication ) { - // retrieve arg list from python, translate to raw C, pass on - PyObject* argl = PySys_GetObject( const_cast< char* >( "argv" ) ); - - int argc = argl ? PyList_Size( argl ) : 1; - char** argv = new char*[ argc ]; - for ( int i = 1; i < argc; ++i ) - argv[ i ] = PyString_AS_STRING( PyList_GET_ITEM( argl, i ) ); - argv[ 0 ] = Py_GetProgramName(); - - gApplication = new TPyROOTApplication( "PyROOT", &argc, argv ); - - // CINT message callback (only if loaded from python, i.e. !gApplication) - G__set_errmsgcallback( (void*)&PyROOT::Utility::ErrMsgCallback ); - } - - // setup some more handy ROOT globals - if ( ! gBenchmark ) gBenchmark = new TBenchmark(); - if ( ! gStyle ) gStyle = new TStyle(); - - if ( ! gProgName ) // should be set by TApplication - gSystem->SetProgname( Py_GetProgramName() ); - - Py_INCREF( Py_None ); - return Py_None; - } - //____________________________________________________________________________ PyObject* SetRootLazyLookup( PyObject*, PyObject* args ) { - PyObject* dict = 0; + PyDictObject* dict = 0; if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyDict_Type, &dict ) ) return 0; - ((DictLookup_t&)((PyDictObject*)dict)->ma_lookup) = RootLookDictString; + ((DictLookup_t&)dict->ma_lookup) = RootLookDictString; Py_INCREF( Py_None ); return Py_None; @@ -377,13 +322,13 @@ namespace { //- data ----------------------------------------------------------------------- static PyMethodDef gPyROOTMethods[] = { - { (char*) "makeRootClass", (PyCFunction)PyROOT::MakeRootClass, + { (char*) "MakeRootClass", (PyCFunction)PyROOT::MakeRootClass, + METH_VARARGS, (char*) "PyROOT internal function" }, + { (char*) "GetRootGlobal", (PyCFunction)PyROOT::GetRootGlobal, METH_VARARGS, (char*) "PyROOT internal function" }, - { (char*) "getRootGlobal", (PyCFunction)PyROOT::GetRootGlobal, + { (char*) "LookupRootEntity", (PyCFunction)LookupRootEntity, METH_VARARGS, (char*) "PyROOT internal function" }, - { (char*) "InitRootApplication", (PyCFunction)InitRootApplication, - METH_NOARGS, (char*) "PyROOT internal function" }, - { (char*) "setRootLazyLookup", (PyCFunction)SetRootLazyLookup, + { (char*) "SetRootLazyLookup", (PyCFunction)SetRootLazyLookup, METH_VARARGS, (char*) "PyROOT internal function" }, { (char*) "MakeRootTemplateClass", (PyCFunction)MakeRootTemplateClass, METH_VARARGS, (char*) "PyROOT internal function" }, @@ -433,6 +378,12 @@ extern "C" void initlibPyROOT() if ( ! Utility::InitProxy( gRootModule, &PropertyProxy_Type, "PropertyProxy" ) ) return; +// policy labels + PyModule_AddObject( gRootModule, (char*)"kMemoryHeuristics", PyInt_FromLong( 1l ) ); + PyModule_AddObject( gRootModule, (char*)"kMemoryStrict", PyInt_FromLong( 2l ) ); + PyModule_AddObject( gRootModule, (char*)"kSignalFast", PyInt_FromLong( 1l ) ); + PyModule_AddObject( gRootModule, (char*)"kSignalSafe", PyInt_FromLong( 2l ) ); + // setup ROOT PyROOT::InitRoot(); diff --git a/pyroot/src/TPyException.cxx b/pyroot/src/TPyException.cxx index 6927763469d098bfd99d26e066d1085db77f3e06..dccb38d17a1e49501068455f8ba557063149d602 100644 --- a/pyroot/src/TPyException.cxx +++ b/pyroot/src/TPyException.cxx @@ -1,4 +1,4 @@ -// @(#)root/pyroot:$Name: $:$Id: TPyException.cxx,v 1.1 2005/03/04 07:44:11 brun Exp $ +// @(#)root/pyroot:$Name: $:$Id: TPyException.cxx,v 1.2 2005/05/06 10:08:53 brun Exp $ // Author: Scott Snyder, Apr 2004 // Bindings @@ -21,7 +21,7 @@ //- data --------------------------------------------------------------------- ClassImp(PyROOT::TPyException) -PyObject* PyROOT::TPyExceptionMagic = (PyObject*)-1; +void* PyROOT::TPyExceptionMagic = (PyObject*)-1; //- constructors/destructor -------------------------------------------------- diff --git a/pyroot/src/TPyROOTApplication.cxx b/pyroot/src/TPyROOTApplication.cxx new file mode 100644 index 0000000000000000000000000000000000000000..80db5268cd44f653ebbcdab21d2d689aec82fde6 --- /dev/null +++ b/pyroot/src/TPyROOTApplication.cxx @@ -0,0 +1,125 @@ +// Author: Wim Lavrijsen, February 2006 + +// Bindings +#include "PyROOT.h" +#include "TPyROOTApplication.h" +#include "Utility.h" + +// ROOT +#include "TROOT.h" +#include "TInterpreter.h" +#include "TSystem.h" +#include "TBenchmark.h" +#include "TStyle.h" + +// CINT +#include "Api.h" + + +//______________________________________________________________________________ +// Setup interactive application +// ============================= +// +// The TPyROOTApplication sets up the nuts and bolts for interactive ROOT use +// from python, closely following TRint. Note that not everything is done here, +// some bits (such as e.g. the use of exception hook for shell escapes) are more +// easily done in python and you'll thus find them ROOT.py +// +// The intended use of this class is from python only. It is used by default in +// ROOT.py, so if you do not want to have a TApplication derived object created +// for you, you'll need to load libPyROOT.so instead. +// +// The static InitXYZ functions are used in conjunction with TPyROOTApplication +// in ROOT.py, but they can be used independently. + + +//- data --------------------------------------------------------------------- +ClassImp(PyROOT::TPyROOTApplication) + + +//- constructors/destructor -------------------------------------------------- +PyROOT::TPyROOTApplication::TPyROOTApplication( + const char* acn, int* argc, char** argv, bool bLoadLibs ) : + TApplication( acn, argc, argv ) +{ +// Create a TApplication derived for use with interactive ROOT from python. A +// set of standard, often used libs is loaded if bLoadLibs is true (default). + + if ( bLoadLibs ) // note that this section could be programmed in python + { + // follow TRint to minimize differences with CINT + ProcessLine( "#include <iostream>", kTRUE ); + ProcessLine( "#include <_string>", kTRUE ); // for std::string iostream. + ProcessLine( "#include <vector>", kTRUE ); // needed because they're used within the + ProcessLine( "#include <pair>", kTRUE ); // core ROOT dicts and CINT won't be able + // to properly unload these files + + // allow the usage of ClassDef and ClassImp in interpreted macros + ProcessLine( "#include <RtypesCint.h>", kTRUE ); + + // disallow the interpretation of Rtypes.h, TError.h and TGenericClassInfo.h + ProcessLine( "#define ROOT_Rtypes 0", kTRUE ); + ProcessLine( "#define ROOT_TError 0", kTRUE ); + ProcessLine( "#define ROOT_TGenericClassInfo 0", kTRUE ); + + // the following libs are also useful to have, make sure they are loaded... + gROOT->LoadClass("TMinuit", "Minuit"); + gROOT->LoadClass("TPostScript", "Postscript"); + gROOT->LoadClass("THtml", "Html"); + } + +// save current interpreter context + gInterpreter->SaveContext(); + gInterpreter->SaveGlobalsContext(); + +// prevent ROOT from exiting python + SetReturnFromRun( kTRUE ); +} + + +//- static public members ---------------------------------------------------- +Bool_t PyROOT::TPyROOTApplication::CreatePyROOTApplication( Bool_t bLoadLibs ) +{ +// Create a TPyROOTApplication. Returns false if a gApplication is not null. + + if ( ! gApplication ) { + // retrieve arg list from python, translate to raw C, pass on + PyObject* argl = PySys_GetObject( const_cast< char* >( "argv" ) ); + + int argc = argl ? PyList_Size( argl ) : 1; + char** argv = new char*[ argc ]; + for ( int i = 1; i < argc; ++i ) + argv[ i ] = PyString_AS_STRING( PyList_GET_ITEM( argl, i ) ); + argv[ 0 ] = Py_GetProgramName(); + + gApplication = new TPyROOTApplication( "PyROOT", &argc, argv, bLoadLibs ); + return kTRUE; + } + + return kFALSE; +} + +//____________________________________________________________________________ +Bool_t PyROOT::TPyROOTApplication::InitROOTGlobals() +{ +// Setup the basic ROOT globals gBenchmark, gStyle, gProgname, if not already +// set. Always returns true. + + if ( ! gBenchmark ) gBenchmark = new TBenchmark(); + if ( ! gStyle ) gStyle = new TStyle(); + + if ( ! gProgName ) // should have been set by TApplication + gSystem->SetProgname( Py_GetProgramName() ); + + return kTRUE; +} + +//____________________________________________________________________________ +Bool_t PyROOT::TPyROOTApplication::InitCINTMessageCallback() +{ +// Install CINT message callback which will turn CINT error message into +// python exceptions. Always returns true. + + G__set_errmsgcallback( (void*)&Utility::ErrMsgCallback ); + return kTRUE; +}