<commit_before>#pragma once
#include <boost/python/data_members.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_internal_reference.hpp>
#include <boost/python/import.hpp>

#include "numeric/dense.hpp"

namespace boost { namespace python {

/**
 Return a copy
 */
template<class Function>
object return_copy(Function f) {
    return make_function(f, return_value_policy<return_by_value>());
}

template<class Class, class Data>
object return_copy(Data (Class::*pmf)() const) {
    return make_function([pmf](Class& c) -> Data { return (c.*pmf)(); },
                         return_value_policy<return_by_value>());
}

template<class Class, class Data, class = cpp14::enable_if_t<!std::is_function<Data>::value>>
object return_copy(Data Class::* d) {
    return make_getter(d, return_value_policy<return_by_value>());
}

/**
 Return a copy but keep the parent object alive
 */
template<class Function>
object return_internal_copy(Function f) {
    return make_function(f, return_value_policy<
        return_by_value, with_custodian_and_ward_postcall<0, 1>
    >{});
}

template<class Class, class Data,
         class = cpp14::enable_if_t<!std::is_member_function_pointer<Data Class::*>::value>>
object return_internal_copy(Data Class::* d) {
    return make_getter(d, return_value_policy<
        return_by_value, with_custodian_and_ward_postcall<0, 1>
    >{});
}

/**
 Return a reference and keep the parent object alive
 */
template<class Function>
object return_reference(Function f) {
    return make_function(f, return_internal_reference<>{});
}

template<class Class, class Data,
         class = cpp14::enable_if_t<!std::is_member_function_pointer<Data Class::*>::value>>
object return_reference(Data Class::* d) {
    return make_getter(d, return_internal_reference<>{});
}

/**
 Convert to `arrayref` and return like `return_internal_copy`
 */
template<class Class, class Data>
object return_arrayref(Data (Class::*pmf)() const) {
    return make_function(
        [pmf](Class& c) { return cpb::arrayref((c.*pmf)()); },
        return_value_policy<return_by_value, with_custodian_and_ward_postcall<0, 1>>{}
    );
}

template<class Class, class Data, class = cpp14::enable_if_t<!std::is_function<Data>::value>>
object return_arrayref(Data Class::* d) {
    return make_function(
        [d](Class& c) { return cpb::arrayref(c.*d); },
        return_value_policy<return_by_value, with_custodian_and_ward_postcall<0, 1>>{}
    );
}

namespace detail {
    template<class T>
    object with_changed_class(T const& value, char const* class_name, char const* module_name) {
        auto module = import(module_name);
        auto o = object(value);
        o.attr("__class__") = module.attr(class_name);
        return o;
    }
}

template<class Class, class Data>
object extended(Data (Class::*pmf)() const, char const* class_name,
                char const* module_name = "pybinding") {
    return make_function([=](Class const& c) {
        return detail::with_changed_class((c.*pmf)(), class_name, module_name);
    });
}

template<class Class, class Data, class = cpp14::enable_if_t<!std::is_function<Data>::value>>
object extended(Data Class::* d, char const* class_name, char const* module_name = "pybinding") {
    return make_function([=](Class const& c) {
        return detail::with_changed_class(c.*d, class_name, module_name);
    });
}

/**
 Ensure that the current thread is ready to call the Python C API.
 This is required in non-Python created threads in order to acquire the GIL.
 Python code code may only be executed while GILEnsure is in scope.
*/
class GILEnsure {
public:
    GILEnsure() { gstate = PyGILState_Ensure(); }
    ~GILEnsure() { PyGILState_Release(gstate); }

private:
    PyGILState_STATE gstate;
};

template<class Fn>
inline void gil_ensure(Fn lambda) {
    GILEnsure guard;
    lambda();
}

/**<commit_msg>Fix compilation with AppleClang < v7.0.0<commit_after>#pragma once
#include <boost/python/data_members.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_internal_reference.hpp>
#include <boost/python/import.hpp>

#include "numeric/dense.hpp"

namespace boost { namespace python {

/**
 Return a copy
 */
template<class Function>
object return_copy(Function f) {
    return make_function(f, return_value_policy<return_by_value>());
}

template<class Class, class Data>
object return_copy(Data (Class::*pmf)() const) {
    return make_function([pmf](Class& c) -> Data { return (c.*pmf)(); },
                         return_value_policy<return_by_value>());
}

template<class Class, class Data>
object return_copy(Data Class::* d) {
    return make_getter(d, return_value_policy<return_by_value>());
}

/**
 Return a copy but keep the parent object alive
 */
template<class Function>
object return_internal_copy(Function f) {
    return make_function(f, return_value_policy<
        return_by_value, with_custodian_and_ward_postcall<0, 1>
    >{});
}

template<class Class, class Data,
         class = cpp14::enable_if_t<!std::is_member_function_pointer<Data Class::*>::value>>
object return_internal_copy(Data Class::* d) {
    return make_getter(d, return_value_policy<
        return_by_value, with_custodian_and_ward_postcall<0, 1>
    >{});
}

/**
 Return a reference and keep the parent object alive
 */
template<class Function>
object return_reference(Function f) {
    return make_function(f, return_internal_reference<>{});
}

template<class Class, class Data,
         class = cpp14::enable_if_t<!std::is_member_function_pointer<Data Class::*>::value>>
object return_reference(Data Class::* d) {
    return make_getter(d, return_internal_reference<>{});
}

/**
 Convert to `arrayref` and return like `return_internal_copy`
 */
template<class Class, class Data>
object return_arrayref(Data (Class::*pmf)() const) {
    return make_function(
        [pmf](Class& c) { return cpb::arrayref((c.*pmf)()); },
        return_value_policy<return_by_value, with_custodian_and_ward_postcall<0, 1>>{}
    );
}

template<class Class, class Data>
object return_arrayref(Data Class::* d) {
    return make_function(
        [d](Class& c) { return cpb::arrayref(c.*d); },
        return_value_policy<return_by_value, with_custodian_and_ward_postcall<0, 1>>{}
    );
}

namespace detail {
    template<class T>
    object with_changed_class(T const& value, char const* class_name, char const* module_name) {
        auto module = import(module_name);
        auto o = object(value);
        o.attr("__class__") = module.attr(class_name);
        return o;
    }
}

template<class Class, class Data>
object extended(Data (Class::*pmf)() const, char const* class_name,
                char const* module_name = "pybinding") {
    return make_function([=](Class const& c) {
        return detail::with_changed_class((c.*pmf)(), class_name, module_name);
    });
}

template<class Class, class Data>
object extended(Data Class::* d, char const* class_name, char const* module_name = "pybinding") {
    return make_function([=](Class const& c) {
        return detail::with_changed_class(c.*d, class_name, module_name);
    });
}

/**
 Ensure that the current thread is ready to call the Python C API.
 This is required in non-Python created threads in order to acquire the GIL.
 Python code code may only be executed while GILEnsure is in scope.
*/
class GILEnsure {
public:
    GILEnsure() { gstate = PyGILState_Ensure(); }
    ~GILEnsure() { PyGILState_Release(gstate); }

private:
    PyGILState_STATE gstate;
};

template<class Fn>
inline void gil_ensure(Fn lambda) {
    GILEnsure guard;
    lambda();
}

/**
{'fraction_non_alphanumeric': 0.12916612631305927, 'fraction_numerical': 0.0042796005706134095, 'mean_word_length': 4.560201874549387, 'pattern_counts': {'":': 0, '<': 80, '<?xml version=': 0, '>': 81, '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': '1065753', 'n_tokens_mistral': 2539, 'n_tokens_neox': 2508, 'n_words': 594}