<commit_before>// @(#)root/pyroot:$Id$
// Author: <NAME>, Jul 2004

// Bindings
#include "PyROOT.h"
#include "PyStrings.h"
#include "Pythonize.h"
#include "ObjectProxy.h"
#include "MethodProxy.h"
#include "RootWrapper.h"
#include "Utility.h"
#include "PyCallable.h"
#include "PyBufferFactory.h"
#include "FunctionHolder.h"
#include "Converters.h"
#include "MemoryRegulator.h"
#include "Adapters.h"
#include "Utility.h"

// ROOT
#include "TClass.h"
#include "TMethod.h"
#include "TCollection.h"
#include "TDirectory.h"
#include "TSeqCollection.h"
#include "TClonesArray.h"
#include "TObject.h"
#include "TFunction.h"
#include "TError.h"

#include "TTree.h"
#include "TBranch.h"
#include "TLeaf.h"

// CINT
#include "Api.h"

// Standard
#include <stdexcept>
#include <string>
#include <stdio.h>
#include <utility>


namespace {

// for convenience
   using namespace PyROOT;

//____________________________________________________________________________
   Bool_t HasAttrDirect( PyObject* pyclass, PyObject* pyname, Bool_t mustBePyROOT = kFALSE ) {
   // prevents calls to pyclass->ob_type->tp_getattr, which is unnecessary for our
   // purposes here and could tickle problems w/ spurious lookups into ROOT meta
      PyObject* attr = PyType_Type.tp_getattro( pyclass, pyname );
      if ( attr != 0 && ( ! mustBePyROOT || MethodProxy_Check( attr ) ) ) {
         Py_DECREF( attr );
         return kTRUE;
      }

      PyErr_Clear();
      return kFALSE;
   }

//____________________________________________________________________________
   inline Bool_t IsTemplatedSTLClass( const std::string& name, const std::string& klass ) {
      const int nsize = (int)name.size();
      const int ksize = (int)klass.size();

      return ( ( ksize   < nsize && name.substr(0,ksize) == klass ) ||
               ( ksize+5 < nsize && name.substr(5,ksize) == klass ) ) &&
             name.find( "::", name.find( ">" ) ) == std::string::npos;
   }

// to prevent compiler warnings about const char* -> char*
   inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth )
   {
      return PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "" ) );
   }

//____________________________________________________________________________
   inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1 )
   {
      return PyObject_CallMethod(
         obj, const_cast< char* >( meth ), const_cast< char* >( "O" ), arg1 );
   }

//____________________________________________________________________________
   inline PyObject* CallPyObjMethod(
      PyObject* obj, const char* meth, PyObject* arg1, PyObject* arg2 )
   {
      return PyObject_CallMethod(
         obj, const_cast< char* >( meth ), const_cast< char* >( "OO" ), arg1, arg2 );
   }

//____________________________________________________________________________
   inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1, int arg2 )
   {
      return PyObject_CallMethod(
         obj, const_cast< char* >( meth ), const_cast< char* >( "Oi" ), arg1, arg2 );
   }


//- helpers --------------------------------------------------------------------
   PyObject* PyStyleIndex( PyObject* self, PyObject* index )
   {
      Py_ssize_t idx = PyInt_AsSsize_t( index );
      if ( idx == (Py_ssize_t)-1 && PyErr_Occurred() )
         return 0;

      Py_ssize_t size = PySequence_Size( self );
      if ( idx >= size || ( idx < 0 && idx < -size ) ) {
         PyErr_SetString( PyExc_IndexError, "index out of range" );
         return 0;
      }

      PyObject* pyindex = 0;
      if ( idx >= 0 ) {
         Py_INCREF( index );
         pyindex = index;
      } else
         pyindex = PyLong_FromLong( size + idx );

      return pyindex;
   }

//____________________________________________________________________________
   inline PyObject* CallSelfIndex( ObjectProxy* self, PyObject* idx, const char* meth )
   {
      PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
      if ( ! pyindex )
         return 0;

      PyObject* result = CallPyObjMethod( (PyObject*)self, meth, pyindex );
      Py_DECREF( pyindex );
      return result;
   }

//- "smart pointer" behavior ---------------------------------------------------
   PyObject* DeRefGetAttr( PyObject* self, PyObject* name )
   {
      if ( ! PyString_Check( name ) )
         PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );

      PyObject* pyptr = CallPyObjMethod( self, "__deref__" );
      if ( ! pyptr )
         return 0;

   // prevent a potential infinite loop
      if ( pyptr->ob_type == self->ob_type ) {
         PyObject* val1 = PyObject_Str( self );
         PyObject* val2 = PyObject_Str( name );
         PyErr_Format( PyExc_AttributeError, "%s has no attribute \'%s\'",
            PyString_AsString( val1 ), PyString_AsString( val2 ) );
         Py_DECREF( val2 );
         Py_DECREF( val1 );

         Py_DECREF( pyptr );
         return 0;
      }

      PyObject* result = PyObject_GetAttr( pyptr, name );
      Py_DECREF( pyptr );
      return result;
   }

//____________________________________________________________________________
   PyObject* FollowGetAttr( PyObject* self, PyObject* name )
   {
      if ( ! PyString_Check( name ) )
         PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );

      PyObject* pyptr = CallPyObjMethod( self, "__follow__" );
      if ( ! pyptr )
         return 0;

      PyObject* result = PyObject_GetAttr( pyptr, name );
      Py_DECREF( pyptr );
      return result;
   }

//- TObject behavior -----------------------------------------------------------
   PyObject* TObjectContains( PyObject* self, PyObject* obj )
   {
      if ( ! ( ObjectProxy_Check( obj ) || PyString_Check( obj ) ) )
         return PyInt_FromLong( 0l );

      PyObject* found = CallPyObjMethod( self, "FindObject", obj );
      PyObject* result = PyInt_FromLong( PyObject_IsTrue( found ) );
      Py_DECREF( found );
      return result;
   }

//____________________________________________________________________________
   PyObject* TObjectCompare( PyObject* self, PyObject* obj )
   {
      if ( ! ObjectProxy_Check( obj ) )
         return PyInt_FromLong( -1l );

      return CallPyObjMethod( self, "Compare", obj );
   }

//____________________________________________________________________________
   PyObject* TObjectIsEqual( PyObject* self, PyObject* obj )
   {
      if ( ! ObjectProxy_Check( obj ) )
         return ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );

      return CallPyObjMethod( self, "IsEqual", obj );
   }

//____________________________________________________________________________
   PyObject* GenObjectIsEqual( PyObject* self, PyObject* obj )
   {
      if ( ! ObjectProxy_Check( obj ) )
         return ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );

      return CallPyObjMethod( self, "__cpp_eq__", obj );
   }

//- TClass behavior ------------------------------------------------------------
   PyObject* TClassStaticCast( ObjectProxy* self, PyObject* args )
   {
   // Implemented somewhat different than TClass::DynamicClass, in that "up" is
   // chosen automatically based on the relationship between self and arg pyclass.
      ObjectProxy* pyclass = 0; PyObject* pyobject = 0;
      if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O:StaticCast" ),<commit_msg>more comparison fine-tuning<commit_after>// @(#)root/pyroot:$Id$
// Author: <NAME>, Jul 2004

// Bindings
#include "PyROOT.h"
#include "PyStrings.h"
#include "Pythonize.h"
#include "ObjectProxy.h"
#include "MethodProxy.h"
#include "RootWrapper.h"
#include "Utility.h"
#include "PyCallable.h"
#include "PyBufferFactory.h"
#include "FunctionHolder.h"
#include "Converters.h"
#include "MemoryRegulator.h"
#include "Adapters.h"
#include "Utility.h"

// ROOT
#include "TClass.h"
#include "TMethod.h"
#include "TCollection.h"
#include "TDirectory.h"
#include "TSeqCollection.h"
#include "TClonesArray.h"
#include "TObject.h"
#include "TFunction.h"
#include "TError.h"

#include "TTree.h"
#include "TBranch.h"
#include "TLeaf.h"

// CINT
#include "Api.h"

// Standard
#include <stdexcept>
#include <string>
#include <stdio.h>
#include <utility>


namespace {

// for convenience
   using namespace PyROOT;

//____________________________________________________________________________
   Bool_t HasAttrDirect( PyObject* pyclass, PyObject* pyname, Bool_t mustBePyROOT = kFALSE ) {
   // prevents calls to pyclass->ob_type->tp_getattr, which is unnecessary for our
   // purposes here and could tickle problems w/ spurious lookups into ROOT meta
      PyObject* attr = PyType_Type.tp_getattro( pyclass, pyname );
      if ( attr != 0 && ( ! mustBePyROOT || MethodProxy_Check( attr ) ) ) {
         Py_DECREF( attr );
         return kTRUE;
      }

      PyErr_Clear();
      return kFALSE;
   }

//____________________________________________________________________________
   inline Bool_t IsTemplatedSTLClass( const std::string& name, const std::string& klass ) {
      const int nsize = (int)name.size();
      const int ksize = (int)klass.size();

      return ( ( ksize   < nsize && name.substr(0,ksize) == klass ) ||
               ( ksize+5 < nsize && name.substr(5,ksize) == klass ) ) &&
             name.find( "::", name.find( ">" ) ) == std::string::npos;
   }

// to prevent compiler warnings about const char* -> char*
   inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth )
   {
      return PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "" ) );
   }

//____________________________________________________________________________
   inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1 )
   {
      return PyObject_CallMethod(
         obj, const_cast< char* >( meth ), const_cast< char* >( "O" ), arg1 );
   }

//____________________________________________________________________________
   inline PyObject* CallPyObjMethod(
      PyObject* obj, const char* meth, PyObject* arg1, PyObject* arg2 )
   {
      return PyObject_CallMethod(
         obj, const_cast< char* >( meth ), const_cast< char* >( "OO" ), arg1, arg2 );
   }

//____________________________________________________________________________
   inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1, int arg2 )
   {
      return PyObject_CallMethod(
         obj, const_cast< char* >( meth ), const_cast< char* >( "Oi" ), arg1, arg2 );
   }


//- helpers --------------------------------------------------------------------
   PyObject* PyStyleIndex( PyObject* self, PyObject* index )
   {
      Py_ssize_t idx = PyInt_AsSsize_t( index );
      if ( idx == (Py_ssize_t)-1 && PyErr_Occurred() )
         return 0;

      Py_ssize_t size = PySequence_Size( self );
      if ( idx >= size || ( idx < 0 && idx < -size ) ) {
         PyErr_SetString( PyExc_IndexError, "index out of range" );
         return 0;
      }

      PyObject* pyindex = 0;
      if ( idx >= 0 ) {
         Py_INCREF( index );
         pyindex = index;
      } else
         pyindex = PyLong_FromLong( size + idx );

      return pyindex;
   }

//____________________________________________________________________________
   inline PyObject* CallSelfIndex( ObjectProxy* self, PyObject* idx, const char* meth )
   {
      PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
      if ( ! pyindex )
         return 0;

      PyObject* result = CallPyObjMethod( (PyObject*)self, meth, pyindex );
      Py_DECREF( pyindex );
      return result;
   }

//- "smart pointer" behavior ---------------------------------------------------
   PyObject* DeRefGetAttr( PyObject* self, PyObject* name )
   {
      if ( ! PyString_Check( name ) )
         PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );

      PyObject* pyptr = CallPyObjMethod( self, "__deref__" );
      if ( ! pyptr )
         return 0;

   // prevent a potential infinite loop
      if ( pyptr->ob_type == self->ob_type ) {
         PyObject* val1 = PyObject_Str( self );
         PyObject* val2 = PyObject_Str( name );
         PyErr_Format( PyExc_AttributeError, "%s has no attribute \'%s\'",
            PyString_AsString( val1 ), PyString_AsString( val2 ) );
         Py_DECREF( val2 );
         Py_DECREF( val1 );

         Py_DECREF( pyptr );
         return 0;
      }

      PyObject* result = PyObject_GetAttr( pyptr, name );
      Py_DECREF( pyptr );
      return result;
   }

//____________________________________________________________________________
   PyObject* FollowGetAttr( PyObject* self, PyObject* name )
   {
      if ( ! PyString_Check( name ) )
         PyErr_SetString( PyExc_TypeError, "getattr(): attribute name must be string" );

      PyObject* pyptr = CallPyObjMethod( self, "__follow__" );
      if ( ! pyptr )
         return 0;

      PyObject* result = PyObject_GetAttr( pyptr, name );
      Py_DECREF( pyptr );
      return result;
   }

//- TObject behavior -----------------------------------------------------------
   PyObject* TObjectContains( PyObject* self, PyObject* obj )
   {
      if ( ! ( ObjectProxy_Check( obj ) || PyString_Check( obj ) ) )
         return PyInt_FromLong( 0l );

      PyObject* found = CallPyObjMethod( self, "FindObject", obj );
      PyObject* result = PyInt_FromLong( PyObject_IsTrue( found ) );
      Py_DECREF( found );
      return result;
   }

//____________________________________________________________________________
   PyObject* TObjectCompare( PyObject* self, PyObject* obj )
   {
      if ( ! ObjectProxy_Check( obj ) )
         return PyInt_FromLong( -1l );

      return CallPyObjMethod( self, "Compare", obj );
   }

//____________________________________________________________________________
   PyObject* TObjectIsEqual( PyObject* self, PyObject* obj )
   {
      if ( ! ObjectProxy_Check( obj ) || ! ((ObjectProxy*)obj)->fObject )
         return ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );

      return CallPyObjMethod( self, "IsEqual", obj );
   }

//____________________________________________________________________________
   PyObject* GenObjectIsEqual( PyObject* self, PyObject* obj )
   {
      if ( ! ObjectProxy_Check( obj ) || ! ((ObjectProxy*)obj)->fObject )
         return ObjectProxy_Type.tp_richcompare( self, obj, Py_EQ );

      return CallPyObjMethod( self, "__cpp_eq__", obj );
   }

//- TClass behavior ------------------------------------------------------------
   PyObject* TClassStaticCast( ObjectProxy* self, PyObject* args )
   {
   // Implemented somewhat different than TClass::DynamicClass, in that "up" is
   // chosen automatically based on the relationship between self and arg pyclass.
      ObjectProxy* pyclass = 0; PyObject* pyobject = 0;
      if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O:StaticCast" ),
{'fraction_non_alphanumeric': 0.14451293045692082, 'fraction_numerical': 0.005091786144981911, 'mean_word_length': 2.8137455288707205, 'pattern_counts': {'":': 2, '<': 39, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7567930', 'n_tokens_mistral': 4332, 'n_tokens_neox': 4387, 'n_words': 1126}