Skip to content

Commit

Permalink
updated pybind11 to support python 3.9
Browse files Browse the repository at this point in the history
  • Loading branch information
Gal Ben David committed Dec 14, 2020
1 parent be3bdb1 commit df08414
Show file tree
Hide file tree
Showing 24 changed files with 1,371 additions and 635 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</p>

![license](https://img.shields.io/badge/MIT-License-blue)
![Python](https://img.shields.io/badge/Python-3.6%20%7C%203.7%20%7C%203.8%20%7C%20pypy3-blue)
![Python](https://img.shields.io/badge/Python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%20pypy3-blue)
![Build](https://github.com/Intsights/PySubstringSearch/workflows/Build/badge.svg)
[![PyPi](https://img.shields.io/pypi/v/PySubstringSearch.svg)](https://pypi.org/project/PySubstringSearch/)

Expand Down
78 changes: 68 additions & 10 deletions src/pybind11/attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include "cast.h"

NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

/// \addtogroup annotations
/// @{
Expand All @@ -23,6 +23,9 @@ struct is_method { handle class_; is_method(const handle &c) : class_(c) { } };
/// Annotation for operators
struct is_operator { };

/// Annotation for classes that cannot be subclassed
struct is_final { };

/// Annotation for parent scope
struct scope { handle value; scope(const handle &s) : value(s) { } };

Expand All @@ -37,8 +40,9 @@ struct sibling { handle value; sibling(const handle &value) : value(value.ptr())

/// Annotation indicating that a class derives from another given type
template <typename T> struct base {

PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_")
base() { }
base() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute
};

/// Keep patient alive while nurse lives
Expand All @@ -58,7 +62,7 @@ struct metaclass {
handle value;

PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.")
metaclass() {}
metaclass() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute

/// Override pybind11's default metaclass
explicit metaclass(handle value) : value(value) { }
Expand All @@ -70,6 +74,9 @@ struct module_local { const bool value; constexpr module_local(bool v = true) :
/// Annotation to mark enums as an arithmetic type
struct arithmetic { };

/// Mark a function for addition at the beginning of the existing overload chain instead of the end
struct prepend { };

/** \rst
A call policy which places one or more guard variables (``Ts...``) around the function call.
Expand Down Expand Up @@ -110,7 +117,7 @@ struct call_guard<T, Ts...> {

/// @} annotations

NAMESPACE_BEGIN(detail)
PYBIND11_NAMESPACE_BEGIN(detail)
/* Forward declarations */
enum op_id : int;
enum op_type : int;
Expand All @@ -134,7 +141,8 @@ struct argument_record {
struct function_record {
function_record()
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
is_operator(false), has_args(false), has_kwargs(false), is_method(false) { }
is_operator(false), is_method(false), has_args(false),
has_kwargs(false), has_kw_only_args(false), prepend(false) { }

/// Function name
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
Expand Down Expand Up @@ -172,18 +180,30 @@ struct function_record {
/// True if this is an operator (__add__), etc.
bool is_operator : 1;

/// True if this is a method
bool is_method : 1;

/// True if the function has a '*args' argument
bool has_args : 1;

/// True if the function has a '**kwargs' argument
bool has_kwargs : 1;

/// True if this is a method
bool is_method : 1;
/// True once a 'py::kw_only' is encountered (any following args are keyword-only)
bool has_kw_only_args : 1;

/// True if this function is to be inserted at the beginning of the overload resolution chain
bool prepend : 1;

/// Number of arguments (including py::args and/or py::kwargs, if present)
std::uint16_t nargs;

/// Number of trailing arguments (counted in `nargs`) that are keyword-only
std::uint16_t nargs_kw_only = 0;

/// Number of leading arguments (counted in `nargs`) that are positional-only
std::uint16_t nargs_pos_only = 0;

/// Python method object
PyMethodDef *def = nullptr;

Expand All @@ -201,7 +221,7 @@ struct function_record {
struct type_record {
PYBIND11_NOINLINE type_record()
: multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false),
default_holder(true), module_local(false) { }
default_holder(true), module_local(false), is_final(false) { }

/// Handle to the parent scope
handle scope;
Expand Down Expand Up @@ -254,6 +274,9 @@ struct type_record {
/// Is the class definition local to the module shared object?
bool module_local : 1;

/// Is the class inheritable from python classes?
bool is_final : 1;

PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) {
auto base_info = detail::get_type_info(base, false);
if (!base_info) {
Expand Down Expand Up @@ -353,12 +376,20 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
};

inline void process_kw_only_arg(const arg &a, function_record *r) {
if (!a.name || strlen(a.name) == 0)
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
++r->nargs_kw_only;
}

/// Process a keyword argument attribute (*without* a default value)
template <> struct process_attribute<arg> : process_attribute_default<arg> {
static void init(const arg &a, function_record *r) {
if (r->is_method && r->args.empty())
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);

if (r->has_kw_only_args) process_kw_only_arg(a, r);
}
};

Expand Down Expand Up @@ -390,6 +421,22 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
#endif
}
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);

if (r->has_kw_only_args) process_kw_only_arg(a, r);
}
};

/// Process a keyword-only-arguments-follow pseudo argument
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
static void init(const kw_only &, function_record *r) {
r->has_kw_only_args = true;
}
};

/// Process a positional-only-argument maker
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
static void init(const pos_only &, function_record *r) {
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
}
};

Expand All @@ -416,6 +463,11 @@ struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr>
static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; }
};

template <>
struct process_attribute<is_final> : process_attribute_default<is_final> {
static void init(const is_final &, type_record *r) { r->is_final = true; }
};

template <>
struct process_attribute<buffer_protocol> : process_attribute_default<buffer_protocol> {
static void init(const buffer_protocol &, type_record *r) { r->buffer_protocol = true; }
Expand All @@ -431,6 +483,12 @@ struct process_attribute<module_local> : process_attribute_default<module_local>
static void init(const module_local &l, type_record *r) { r->module_local = l.value; }
};

/// Process a 'prepend' attribute, putting this at the beginning of the overload chain
template <>
struct process_attribute<prepend> : process_attribute_default<prepend> {
static void init(const prepend &, function_record *r) { r->prepend = true; }
};

/// Process an 'arithmetic' attribute for enums (does nothing here)
template <>
struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {};
Expand Down Expand Up @@ -489,5 +547,5 @@ constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) {
return named == 0 || (self + named + has_args + has_kwargs) == nargs;
}

NAMESPACE_END(detail)
NAMESPACE_END(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
52 changes: 42 additions & 10 deletions src/pybind11/buffer_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,30 @@

#include "detail/common.h"

NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

PYBIND11_NAMESPACE_BEGIN(detail)

// Default, C-style strides
inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
auto ndim = shape.size();
std::vector<ssize_t> strides(ndim, itemsize);
if (ndim > 0)
for (size_t i = ndim - 1; i > 0; --i)
strides[i - 1] = strides[i] * shape[i];
return strides;
}

// F-style strides; default when constructing an array_t with `ExtraFlags & f_style`
inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
auto ndim = shape.size();
std::vector<ssize_t> strides(ndim, itemsize);
for (size_t i = 1; i < ndim; ++i)
strides[i] = strides[i - 1] * shape[i - 1];
return strides;
}

PYBIND11_NAMESPACE_END(detail)

/// Information record describing a Python buffer object
struct buffer_info {
Expand All @@ -24,7 +47,7 @@ struct buffer_info {
std::vector<ssize_t> strides; // Number of bytes between adjacent entries (for each per dimension)
bool readonly = false; // flag to indicate if the underlying storage may be written to

buffer_info() { }
buffer_info() = default;

buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
Expand Down Expand Up @@ -53,8 +76,15 @@ struct buffer_info {

explicit buffer_info(Py_buffer *view, bool ownview = true)
: buffer_info(view->buf, view->itemsize, view->format, view->ndim,
{view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}, view->readonly) {
this->view = view;
{view->shape, view->shape + view->ndim},
/* Though buffer::request() requests PyBUF_STRIDES, ctypes objects
* ignore this flag and return a view with NULL strides.
* When strides are NULL, build them manually. */
view->strides
? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
: detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
view->readonly) {
this->m_view = view;
this->ownview = ownview;
}

Expand All @@ -73,28 +103,30 @@ struct buffer_info {
ndim = rhs.ndim;
shape = std::move(rhs.shape);
strides = std::move(rhs.strides);
std::swap(view, rhs.view);
std::swap(m_view, rhs.m_view);
std::swap(ownview, rhs.ownview);
readonly = rhs.readonly;
return *this;
}

~buffer_info() {
if (view && ownview) { PyBuffer_Release(view); delete view; }
if (m_view && ownview) { PyBuffer_Release(m_view); delete m_view; }
}

Py_buffer *view() const { return m_view; }
Py_buffer *&view() { return m_view; }
private:
struct private_ctr_tag { };

buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in, bool readonly)
: buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) { }

Py_buffer *view = nullptr;
Py_buffer *m_view = nullptr;
bool ownview = false;
};

NAMESPACE_BEGIN(detail)
PYBIND11_NAMESPACE_BEGIN(detail)

template <typename T, typename SFINAE = void> struct compare_buffer_info {
static bool compare(const buffer_info& b) {
Expand All @@ -110,5 +142,5 @@ template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_
}
};

NAMESPACE_END(detail)
NAMESPACE_END(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
Loading

0 comments on commit df08414

Please sign in to comment.