Skip to content

Commit df08414

Browse files
author
Gal Ben David
committed
updated pybind11 to support python 3.9
1 parent be3bdb1 commit df08414

24 files changed

Lines changed: 1371 additions & 635 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</p>
99

1010
![license](https://img.shields.io/badge/MIT-License-blue)
11-
![Python](https://img.shields.io/badge/Python-3.6%20%7C%203.7%20%7C%203.8%20%7C%20pypy3-blue)
11+
![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)
1212
![Build](https://github.com/Intsights/PySubstringSearch/workflows/Build/badge.svg)
1313
[![PyPi](https://img.shields.io/pypi/v/PySubstringSearch.svg)](https://pypi.org/project/PySubstringSearch/)
1414

src/pybind11/attr.h

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#include "cast.h"
1414

15-
NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
15+
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1616

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

26+
/// Annotation for classes that cannot be subclassed
27+
struct is_final { };
28+
2629
/// Annotation for parent scope
2730
struct scope { handle value; scope(const handle &s) : value(s) { } };
2831

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

3841
/// Annotation indicating that a class derives from another given type
3942
template <typename T> struct base {
43+
4044
PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_")
41-
base() { }
45+
base() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute
4246
};
4347

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

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

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

77+
/// Mark a function for addition at the beginning of the existing overload chain instead of the end
78+
struct prepend { };
79+
7380
/** \rst
7481
A call policy which places one or more guard variables (``Ts...``) around the function call.
7582
@@ -110,7 +117,7 @@ struct call_guard<T, Ts...> {
110117

111118
/// @} annotations
112119

113-
NAMESPACE_BEGIN(detail)
120+
PYBIND11_NAMESPACE_BEGIN(detail)
114121
/* Forward declarations */
115122
enum op_id : int;
116123
enum op_type : int;
@@ -134,7 +141,8 @@ struct argument_record {
134141
struct function_record {
135142
function_record()
136143
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
137-
is_operator(false), has_args(false), has_kwargs(false), is_method(false) { }
144+
is_operator(false), is_method(false), has_args(false),
145+
has_kwargs(false), has_kw_only_args(false), prepend(false) { }
138146

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

183+
/// True if this is a method
184+
bool is_method : 1;
185+
175186
/// True if the function has a '*args' argument
176187
bool has_args : 1;
177188

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

181-
/// True if this is a method
182-
bool is_method : 1;
192+
/// True once a 'py::kw_only' is encountered (any following args are keyword-only)
193+
bool has_kw_only_args : 1;
194+
195+
/// True if this function is to be inserted at the beginning of the overload resolution chain
196+
bool prepend : 1;
183197

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

201+
/// Number of trailing arguments (counted in `nargs`) that are keyword-only
202+
std::uint16_t nargs_kw_only = 0;
203+
204+
/// Number of leading arguments (counted in `nargs`) that are positional-only
205+
std::uint16_t nargs_pos_only = 0;
206+
187207
/// Python method object
188208
PyMethodDef *def = nullptr;
189209

@@ -201,7 +221,7 @@ struct function_record {
201221
struct type_record {
202222
PYBIND11_NOINLINE type_record()
203223
: multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false),
204-
default_holder(true), module_local(false) { }
224+
default_holder(true), module_local(false), is_final(false) { }
205225

206226
/// Handle to the parent scope
207227
handle scope;
@@ -254,6 +274,9 @@ struct type_record {
254274
/// Is the class definition local to the module shared object?
255275
bool module_local : 1;
256276

277+
/// Is the class inheritable from python classes?
278+
bool is_final : 1;
279+
257280
PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) {
258281
auto base_info = detail::get_type_info(base, false);
259282
if (!base_info) {
@@ -353,12 +376,20 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
353376
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
354377
};
355378

379+
inline void process_kw_only_arg(const arg &a, function_record *r) {
380+
if (!a.name || strlen(a.name) == 0)
381+
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
382+
++r->nargs_kw_only;
383+
}
384+
356385
/// Process a keyword argument attribute (*without* a default value)
357386
template <> struct process_attribute<arg> : process_attribute_default<arg> {
358387
static void init(const arg &a, function_record *r) {
359388
if (r->is_method && r->args.empty())
360389
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
361390
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
391+
392+
if (r->has_kw_only_args) process_kw_only_arg(a, r);
362393
}
363394
};
364395

@@ -390,6 +421,22 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
390421
#endif
391422
}
392423
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
424+
425+
if (r->has_kw_only_args) process_kw_only_arg(a, r);
426+
}
427+
};
428+
429+
/// Process a keyword-only-arguments-follow pseudo argument
430+
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
431+
static void init(const kw_only &, function_record *r) {
432+
r->has_kw_only_args = true;
433+
}
434+
};
435+
436+
/// Process a positional-only-argument maker
437+
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
438+
static void init(const pos_only &, function_record *r) {
439+
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
393440
}
394441
};
395442

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

466+
template <>
467+
struct process_attribute<is_final> : process_attribute_default<is_final> {
468+
static void init(const is_final &, type_record *r) { r->is_final = true; }
469+
};
470+
419471
template <>
420472
struct process_attribute<buffer_protocol> : process_attribute_default<buffer_protocol> {
421473
static void init(const buffer_protocol &, type_record *r) { r->buffer_protocol = true; }
@@ -431,6 +483,12 @@ struct process_attribute<module_local> : process_attribute_default<module_local>
431483
static void init(const module_local &l, type_record *r) { r->module_local = l.value; }
432484
};
433485

486+
/// Process a 'prepend' attribute, putting this at the beginning of the overload chain
487+
template <>
488+
struct process_attribute<prepend> : process_attribute_default<prepend> {
489+
static void init(const prepend &, function_record *r) { r->prepend = true; }
490+
};
491+
434492
/// Process an 'arithmetic' attribute for enums (does nothing here)
435493
template <>
436494
struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {};
@@ -489,5 +547,5 @@ constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) {
489547
return named == 0 || (self + named + has_args + has_kwargs) == nargs;
490548
}
491549

492-
NAMESPACE_END(detail)
493-
NAMESPACE_END(PYBIND11_NAMESPACE)
550+
PYBIND11_NAMESPACE_END(detail)
551+
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

src/pybind11/buffer_info.h

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,30 @@
1111

1212
#include "detail/common.h"
1313

14-
NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
14+
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
15+
16+
PYBIND11_NAMESPACE_BEGIN(detail)
17+
18+
// Default, C-style strides
19+
inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
20+
auto ndim = shape.size();
21+
std::vector<ssize_t> strides(ndim, itemsize);
22+
if (ndim > 0)
23+
for (size_t i = ndim - 1; i > 0; --i)
24+
strides[i - 1] = strides[i] * shape[i];
25+
return strides;
26+
}
27+
28+
// F-style strides; default when constructing an array_t with `ExtraFlags & f_style`
29+
inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
30+
auto ndim = shape.size();
31+
std::vector<ssize_t> strides(ndim, itemsize);
32+
for (size_t i = 1; i < ndim; ++i)
33+
strides[i] = strides[i - 1] * shape[i - 1];
34+
return strides;
35+
}
36+
37+
PYBIND11_NAMESPACE_END(detail)
1538

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

27-
buffer_info() { }
50+
buffer_info() = default;
2851

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

5477
explicit buffer_info(Py_buffer *view, bool ownview = true)
5578
: buffer_info(view->buf, view->itemsize, view->format, view->ndim,
56-
{view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}, view->readonly) {
57-
this->view = view;
79+
{view->shape, view->shape + view->ndim},
80+
/* Though buffer::request() requests PyBUF_STRIDES, ctypes objects
81+
* ignore this flag and return a view with NULL strides.
82+
* When strides are NULL, build them manually. */
83+
view->strides
84+
? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
85+
: detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
86+
view->readonly) {
87+
this->m_view = view;
5888
this->ownview = ownview;
5989
}
6090

@@ -73,28 +103,30 @@ struct buffer_info {
73103
ndim = rhs.ndim;
74104
shape = std::move(rhs.shape);
75105
strides = std::move(rhs.strides);
76-
std::swap(view, rhs.view);
106+
std::swap(m_view, rhs.m_view);
77107
std::swap(ownview, rhs.ownview);
78108
readonly = rhs.readonly;
79109
return *this;
80110
}
81111

82112
~buffer_info() {
83-
if (view && ownview) { PyBuffer_Release(view); delete view; }
113+
if (m_view && ownview) { PyBuffer_Release(m_view); delete m_view; }
84114
}
85115

116+
Py_buffer *view() const { return m_view; }
117+
Py_buffer *&view() { return m_view; }
86118
private:
87119
struct private_ctr_tag { };
88120

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

93-
Py_buffer *view = nullptr;
125+
Py_buffer *m_view = nullptr;
94126
bool ownview = false;
95127
};
96128

97-
NAMESPACE_BEGIN(detail)
129+
PYBIND11_NAMESPACE_BEGIN(detail)
98130

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

113-
NAMESPACE_END(detail)
114-
NAMESPACE_END(PYBIND11_NAMESPACE)
145+
PYBIND11_NAMESPACE_END(detail)
146+
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

0 commit comments

Comments
 (0)