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

// Bindings
#include "PyROOT.h"
#include "structmember.h"    // from Python
#if PY_VERSION_HEX >= 0x02050000
#include "code.h"            // from Python
#else
#include "compile.h"         // from Python
#endif
#ifndef CO_NOFREE
// python2.2 does not have CO_NOFREE defined
#define CO_NOFREE       0x0040
#endif
#include "MethodProxy.h"
#include "ObjectProxy.h"
#include "TPyException.h"
#include "Utility.h"
#include "PyStrings.h"

// Standard
#include <algorithm>
#include <functional>
#include <vector>
#include <algorithm>


namespace PyROOT {

namespace {

// helper to test whether a method is used in a pseudo-function modus
   bool inline IsPseudoFunc( MethodProxy* pymeth )
   {
      return (void*)pymeth == (void*)pymeth->fSelf;
   }

// helper for collecting/maintaining exception data in overload dispatch
   struct PyError_t {
      PyError_t() { fType = fValue = fTrace = 0; }

      static void Clear( PyError_t& e )
      {
         Py_XDECREF( e.fType ); Py_XDECREF( e.fValue ); Py_XDECREF( e.fTrace );
         e.fType = e.fValue = e.fTrace = 0;
      }

      PyObject *fType, *fValue, *fTrace;
   };

// helper to hash tuple (using tuple hash would cause self-tailing loops)
   inline Long_t HashSignature( PyObject* args )
   {
      ULong_t hash = 0;

      Int_t nargs = PyTuple_GET_SIZE( args );
      for ( Int_t i = 0; i < nargs; ++i ) {
         hash += (ULong_t) Py_TYPE( PyTuple_GET_ITEM( args, i ) );
         hash += (hash << 10); hash ^= (hash >> 6);
      }

      hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15);

      return hash;
   }

// helper to sort on method priority
   int PriorityCmp( PyCallable* left, PyCallable* right )
   {
      return left->GetPriority() > right->GetPriority();
   }

// helper to factor out return logic of mp_call
   inline PyObject* HandleReturn( MethodProxy* pymeth, PyObject* result ) {

   // special case for python exceptions, propagated through C++ layer
      if ( result == (PyObject*)TPyExceptionMagic )
         return 0;              // exception info was already set

   // if this method creates new objects, always take ownership
      if ( pymeth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsCreator ) {

      // either be a constructor with a fresh object proxy self ... 
         if ( pymeth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsConstructor ) {
            if ( pymeth->fSelf )
               pymeth->fSelf->HoldOn();
         }

      // ... or be a method with an object proxy return value
         else if ( ObjectProxy_Check( result ) )
            ((ObjectProxy*)result)->HoldOn();
      }

#if 0
   // if this new object falls inside self, make sure its lifetime is proper
      if ( pymeth->fSelf && ObjectProxy_Check( result ) ) {
         Long_t ptrdiff = (Long_t)((ObjectProxy*)result)->GetObject() - (Long_t)pymeth->fSelf->GetObject();
         if ( 0 <= ptrdiff && ptrdiff < (Long_t)pymeth->fSelf->ObjectIsA()->Size() ) {
            if ( PyObject_SetAttr( result, PyStrings::gLifeLine, (PyObject*)pymeth->fSelf ) == -1 )
               PyErr_Clear();     // ignored
         }
      }
#endif

      return result;
   }


//= PyROOT method proxy object behaviour =====================================
   PyObject* mp_name( MethodProxy* pymeth, void* )
   {
      return PyROOT_PyUnicode_FromString( pymeth->GetName().c_str() );
   }

//____________________________________________________________________________
   PyObject* mp_module( MethodProxy* /* pymeth */, void* )
   {
      Py_INCREF( PyStrings::gROOTns );
      return PyStrings::gROOTns;
   }

//____________________________________________________________________________
   PyObject* mp_doc( MethodProxy* pymeth, void* )
   {
      MethodProxy::Methods_t& methods = pymeth->fMethodInfo->fMethods;

   // collect doc strings
      Int_t nMethods = methods.size();
      PyObject* doc = methods[0]->GetDocString();

   // simple case<commit_msg>restore lifeline code snippet<commit_after>// @(#)root/pyroot:$Id$
// Author: <NAME>, Jan 2005

// Bindings
#include "PyROOT.h"
#include "structmember.h"    // from Python
#if PY_VERSION_HEX >= 0x02050000
#include "code.h"            // from Python
#else
#include "compile.h"         // from Python
#endif
#ifndef CO_NOFREE
// python2.2 does not have CO_NOFREE defined
#define CO_NOFREE       0x0040
#endif
#include "MethodProxy.h"
#include "ObjectProxy.h"
#include "TPyException.h"
#include "Utility.h"
#include "PyStrings.h"

// Standard
#include <algorithm>
#include <functional>
#include <vector>
#include <algorithm>


namespace PyROOT {

namespace {

// helper to test whether a method is used in a pseudo-function modus
   bool inline IsPseudoFunc( MethodProxy* pymeth )
   {
      return (void*)pymeth == (void*)pymeth->fSelf;
   }

// helper for collecting/maintaining exception data in overload dispatch
   struct PyError_t {
      PyError_t() { fType = fValue = fTrace = 0; }

      static void Clear( PyError_t& e )
      {
         Py_XDECREF( e.fType ); Py_XDECREF( e.fValue ); Py_XDECREF( e.fTrace );
         e.fType = e.fValue = e.fTrace = 0;
      }

      PyObject *fType, *fValue, *fTrace;
   };

// helper to hash tuple (using tuple hash would cause self-tailing loops)
   inline Long_t HashSignature( PyObject* args )
   {
      ULong_t hash = 0;

      Int_t nargs = PyTuple_GET_SIZE( args );
      for ( Int_t i = 0; i < nargs; ++i ) {
         hash += (ULong_t) Py_TYPE( PyTuple_GET_ITEM( args, i ) );
         hash += (hash << 10); hash ^= (hash >> 6);
      }

      hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15);

      return hash;
   }

// helper to sort on method priority
   int PriorityCmp( PyCallable* left, PyCallable* right )
   {
      return left->GetPriority() > right->GetPriority();
   }

// helper to factor out return logic of mp_call
   inline PyObject* HandleReturn( MethodProxy* pymeth, PyObject* result ) {

   // special case for python exceptions, propagated through C++ layer
      if ( result == (PyObject*)TPyExceptionMagic )
         return 0;              // exception info was already set

   // if this method creates new objects, always take ownership
      if ( pymeth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsCreator ) {

      // either be a constructor with a fresh object proxy self ... 
         if ( pymeth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsConstructor ) {
            if ( pymeth->fSelf )
               pymeth->fSelf->HoldOn();
         }

      // ... or be a method with an object proxy return value
         else if ( ObjectProxy_Check( result ) )
            ((ObjectProxy*)result)->HoldOn();
      }

   // if this new object falls inside self, make sure its lifetime is proper
      if ( pymeth->fSelf && ObjectProxy_Check( result ) ) {
         Long_t ptrdiff = (Long_t)((ObjectProxy*)result)->GetObject() - (Long_t)pymeth->fSelf->GetObject();
         if ( 0 <= ptrdiff && ptrdiff < (Long_t)pymeth->fSelf->ObjectIsA()->Size() ) {
            if ( PyObject_SetAttr( result, PyStrings::gLifeLine, (PyObject*)pymeth->fSelf ) == -1 )
               PyErr_Clear();     // ignored
         }
      }

      return result;
   }


//= PyROOT method proxy object behaviour =====================================
   PyObject* mp_name( MethodProxy* pymeth, void* )
   {
      return PyROOT_PyUnicode_FromString( pymeth->GetName().c_str() );
   }

//____________________________________________________________________________
   PyObject* mp_module( MethodProxy* /* pymeth */, void* )
   {
      Py_INCREF( PyStrings::gROOTns );
      return PyStrings::gROOTns;
   }

//____________________________________________________________________________
   PyObject* mp_doc( MethodProxy* pymeth, void* )
   {
      MethodProxy::Methods_t& methods = pymeth->fMethodInfo->fMethods;

   // collect doc strings
      Int_t nMethods = methods.size();
      PyObject* doc = methods[0]->GetDocString();

   // simple case
{'fraction_non_alphanumeric': 0.13145773683555334, 'fraction_numerical': 0.009087514004730486, 'mean_word_length': 2.8057792515395548, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 71, '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': '1062328', 'n_tokens_mistral': 2532, 'n_tokens_neox': 2456, 'n_words': 677}