From 48381c94515f15d14df8bfbd35d570f94b561df2 Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Thu, 9 Mar 2006 09:07:02 +0000
Subject: [PATCH] From Pere and Wim:  o) fix TF1/2/3 default value propagation 
 o) turn TPyExceptionMagic into a void* to prevent attempted _object dict
 creation  o) new TPyROOTApplication.h/.cxx accessible from python (created
 from ROOT.py)  o) changed first letter of all exported libPyROOT funcs from
 lower to upper case  o) move policy identifiers from ROOT.py to libPyROOT.so 
 o) fix return code for char converter  o) add sorting which penalizes methods
 with unknown classes and void*'s

This then also fixes outstanding problems as erported by Witek (savannah),
Marco, and Berrie.


git-svn-id: http://root.cern.ch/svn/root/trunk@14208 27541ba8-7e3a-0410-8455-c3a389f83636
---
 pyroot/ROOT.py                    |  72 ++++++-------
 pyroot/inc/LinkDef.h              |   3 +
 pyroot/inc/TPyException.h         |   8 +-
 pyroot/inc/TPyROOTApplication.h   |  40 ++++++++
 pyroot/src/ConstructorHolder.cxx  |   7 +-
 pyroot/src/Converters.cxx         |  67 +++++++------
 pyroot/src/MethodHolder.cxx       |  31 +++++-
 pyroot/src/MethodHolder.h         |   5 +-
 pyroot/src/MethodProxy.cxx        |  18 +++-
 pyroot/src/MethodProxy.h          |  10 +-
 pyroot/src/PyCallable.h           |   3 +-
 pyroot/src/Pythonize.cxx          |   6 +-
 pyroot/src/RootModule.cxx         | 161 +++++++++++-------------------
 pyroot/src/TPyException.cxx       |   4 +-
 pyroot/src/TPyROOTApplication.cxx | 125 +++++++++++++++++++++++
 15 files changed, 353 insertions(+), 207 deletions(-)
 create mode 100644 pyroot/inc/TPyROOTApplication.h
 create mode 100644 pyroot/src/TPyROOTApplication.cxx

diff --git a/pyroot/ROOT.py b/pyroot/ROOT.py
index d26294fee7d..baecc2a9a59 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 064eb7f343b..485633bcff9 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 7ae4401b9dd..4109465823e 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 00000000000..edfc2184b91
--- /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 08c19176edd..fa95842ecbd 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 391b1556b3f..9a7c088250f 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 55d3b9324c3..646a20ba3a6 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 2b9f365a7d0..80256a6eb1c 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 f7ebdcf9662..198e5ce33d1 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 ee8ec19810a..a950e138a7d 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 8d885940c57..074d273ab84 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 694ef7df21c..e19e8f9b532 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 e9ca175f523..732348f9e13 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 6927763469d..dccb38d17a1 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 00000000000..80db5268cd4
--- /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;
+}
-- 
GitLab