<commit_before>require 'ffi'
require 'open3'

module RubyPython
  #This module provides access to the Python C API functions via the Ruby ffi
  #gem. Documentation for these functions may be found [here](http://docs.python.org/c-api/). Likewise the FFI gem documentation may be found [here](http://rdoc.info/projects/ffi/ffi).
  module Python
    extend FFI::Library
    PYTHON_VERSION = Open3.popen3("python --version") { |i,o,e| e.read}.chomp.split[1].to_f
    PYTHON_NAME = "python#{PYTHON_VERSION}"
    LIB_NAME = "lib#{PYTHON_NAME}"
    LIB_EXT = FFI::Platform::LIBSUFFIX
    LIB = File.join(`python -c "import sys; print(sys.prefix)"`.chomp,
      "lib", "#{PYTHON_NAME}", "config", "#{LIB_NAME}.#{LIB_EXT}")
    @ffi_libs = [FFI::DynamicLibrary.open(LIB, FFI::DynamicLibrary::RTLD_LAZY|FFI::DynamicLibrary::RTLD_GLOBAL)]

    #The class is a little bit of a hack to extract the address of global
    #structs. If someone knows a better way please let me know.
    class DummyStruct < FFI::Struct
      layout :dummy_var, :int
    end

    #Python interpreter startup and shutdown
    attach_function :Py_IsInitialized, [], :int
    attach_function :Py_Initialize, [], :void
    attach_function :Py_Finalize, [], :void

    #Module methods
    attach_function :PyImport_ImportModule, [:string], :pointer

    #Object Methods
    attach_function :PyObject_HasAttrString, [:pointer, :string], :int
    attach_function :PyObject_GetAttrString, [:pointer, :string], :pointer
    attach_function :PyObject_SetAttrString, [:pointer, :string, :pointer], :int

    attach_function :PyObject_Compare, [:pointer, :pointer], :int<commit_msg>Fixing FFI DLopen for python on 10.6.<commit_after>require 'ffi'
require 'open3'

module RubyPython
  #This module provides access to the Python C API functions via the Ruby ffi
  #gem. Documentation for these functions may be found [here](http://docs.python.org/c-api/). Likewise the FFI gem documentation may be found [here](http://rdoc.info/projects/ffi/ffi).
  module Python
    extend FFI::Library

    # This much we can assume works without anything special at all.
    PYTHON_VERSION = Open3.popen3("python --version") { |i,o,e| e.read }.chomp.split[1].to_f
    PYTHON_NAME = "python#{PYTHON_VERSION}"
    LIB_NAME = "#{FFI::Platform::LIBPREFIX}#{PYTHON_NAME}"
    LIB_EXT = FFI::Platform::LIBSUFFIX
    PYTHON_SYS_PREFIX = %x{#{PYTHON_NAME} -c "import sys; print(sys.prefix)"}.chomp

    # Here's where we run into problems, as not everything works quite the
    # way we expect it to.
    #
    # The default libname will be something like libpython2.6.so (or .dylib)
    # or maybe even python2.6.dll on Windows.
    libname = "#{LIB_NAME}.#{LIB_EXT}"

    # We may need to look in multiple locations for Python, so let's build
    # this as an array.
    locations = [ File.join(PYTHON_SYS_PREFIX, "lib", libname) ]

    if FFI::Platform.mac?
      # On the Mac, let's add a special case that has even a different
      # libname. This may not be fully useful on future versions of OS X,
      # but it should work on 10.5 and 10.6. Even if it doesn't, the next
      # step will (/usr/lib/libpython<version>.dylib is a symlink to the
      # correct location).
      locations << File.join(PYTHON_SYS_PREFIX, "Python")
      # Let's also look in the location that was originally set in this
      # library:
      File.join(PYTHON_SYS_PREFIX, "lib", "#{PYTHON_NAME}", "config",
                libname)
    end

    if FFI::Platform.unix?
      # On Unixes, let's look in alternative places, too. Just in case.
      locations << File.join("/opt/local/lib", libname)
      locations << File.join("/opt/lib", libname)
      locations << File.join("/usr/local/lib", libname)
      locations << File.join("/usr/lib", libname)
    end

    # Get rid of redundant locations.
    locations.uniq!

    dyld_flags = FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL
    exceptions = []

    locations.each do |location|
      begin
        @ffi_libs = [ FFI::DynamicLibrary.open(location, dyld_flags) ]
        LIB = location
        break
      rescue LoadError => ex
        @ffi_libs = nil
        exceptions << ex
      end
    end

    raise exceptions.first if @ffi_libs.nil?

    #The class is a little bit of a hack to extract the address of global
    #structs. If someone knows a better way please let me know.
    class DummyStruct < FFI::Struct
      layout :dummy_var, :int
    end

    #Python interpreter startup and shutdown
    attach_function :Py_IsInitialized, [], :int
    attach_function :Py_Initialize, [], :void
    attach_function :Py_Finalize, [], :void

    #Module methods
    attach_function :PyImport_ImportModule, [:string], :pointer

    #Object Methods
    attach_function :PyObject_HasAttrString, [:pointer, :string], :int
    attach_function :PyObject_GetAttrString, [:pointer, :string], :pointer
    attach_function :PyObject_SetAttrString, [:pointer, :string, :pointer], :int

    attach_function :PyObject_Compare, [:pointer, :pointer], :int
{'fraction_non_alphanumeric': 0.11320754716981132, 'fraction_numerical': 0.004170804369414101, 'mean_word_length': 3.5247079964061094, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 5, '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': '2232134', 'n_tokens_mistral': 1616, 'n_tokens_neox': 1577, 'n_words': 483}