mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
Adding .clang-tidy readability-braces-around-statements option.
clang-tidy automatic changes. NO manual changes.
This commit is contained in:
parent
8581584e60
commit
ddbc74c674
@ -31,6 +31,7 @@ modernize-use-override,
|
||||
modernize-use-using,
|
||||
*performance*,
|
||||
readability-avoid-const-params-in-decls,
|
||||
readability-braces-around-statements,
|
||||
readability-const-return-type,
|
||||
readability-container-size-empty,
|
||||
readability-delete-null-pointer,
|
||||
|
@ -330,11 +330,13 @@ struct type_record {
|
||||
|
||||
bases.append((PyObject *) base_info->type);
|
||||
|
||||
if (base_info->type->tp_dictoffset != 0)
|
||||
if (base_info->type->tp_dictoffset != 0) {
|
||||
dynamic_attr = true;
|
||||
}
|
||||
|
||||
if (caster)
|
||||
if (caster) {
|
||||
base_info->implicit_casts.emplace_back(type, caster);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -410,13 +412,16 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
|
||||
};
|
||||
|
||||
inline void check_kw_only_arg(const arg &a, function_record *r) {
|
||||
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0'))
|
||||
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or args() argument");
|
||||
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0')) {
|
||||
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or "
|
||||
"args() argument");
|
||||
}
|
||||
}
|
||||
|
||||
inline void append_self_arg_if_needed(function_record *r) {
|
||||
if (r->is_method && r->args.empty())
|
||||
r->args.emplace_back("self", nullptr, handle(), /*convert=*/ true, /*none=*/ false);
|
||||
if (r->is_method && r->args.empty()) {
|
||||
r->args.emplace_back("self", nullptr, handle(), /*convert=*/true, /*none=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Process a keyword argument attribute (*without* a default value)
|
||||
@ -432,8 +437,10 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
||||
/// Process a keyword argument attribute (*with* a default value)
|
||||
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||
static void init(const arg_v &a, function_record *r) {
|
||||
if (r->is_method && r->args.empty())
|
||||
r->args.emplace_back("self", /*descr=*/ nullptr, /*parent=*/ handle(), /*convert=*/ true, /*none=*/ false);
|
||||
if (r->is_method && r->args.empty()) {
|
||||
r->args.emplace_back(
|
||||
"self", /*descr=*/nullptr, /*parent=*/handle(), /*convert=*/true, /*none=*/false);
|
||||
}
|
||||
|
||||
if (!a.value) {
|
||||
#if !defined(NDEBUG)
|
||||
@ -466,8 +473,10 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
||||
static void init(const kw_only &, function_record *r) {
|
||||
append_self_arg_if_needed(r);
|
||||
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size()))
|
||||
pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative argument location (or omit kw_only() entirely)");
|
||||
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size())) {
|
||||
pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative "
|
||||
"argument location (or omit kw_only() entirely)");
|
||||
}
|
||||
r->nargs_pos = static_cast<std::uint16_t>(r->args.size());
|
||||
}
|
||||
};
|
||||
@ -477,8 +486,9 @@ template <> struct process_attribute<pos_only> : process_attribute_default<pos_o
|
||||
static void init(const pos_only &, function_record *r) {
|
||||
append_self_arg_if_needed(r);
|
||||
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
|
||||
if (r->nargs_pos_only > r->nargs_pos)
|
||||
if (r->nargs_pos_only > r->nargs_pos) {
|
||||
pybind11_fail("pos_only(): cannot follow a py::args() argument");
|
||||
}
|
||||
// It also can't follow a kw_only, but a static_assert in pybind11.h checks that
|
||||
}
|
||||
};
|
||||
|
@ -19,9 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
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)
|
||||
if (ndim > 0) {
|
||||
for (size_t i = ndim - 1; i > 0; --i) {
|
||||
strides[i - 1] = strides[i] * shape[i];
|
||||
}
|
||||
}
|
||||
return strides;
|
||||
}
|
||||
|
||||
@ -29,8 +31,9 @@ inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t
|
||||
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)
|
||||
for (size_t i = 1; i < ndim; ++i) {
|
||||
strides[i] = strides[i - 1] * shape[i - 1];
|
||||
}
|
||||
return strides;
|
||||
}
|
||||
|
||||
@ -53,10 +56,12 @@ struct buffer_info {
|
||||
detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
|
||||
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
|
||||
shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
|
||||
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size())
|
||||
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) {
|
||||
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
|
||||
for (size_t i = 0; i < (size_t) ndim; ++i)
|
||||
}
|
||||
for (size_t i = 0; i < (size_t) ndim; ++i) {
|
||||
size *= shape[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -60,8 +60,10 @@ public:
|
||||
static constexpr auto name = caster_t::name;
|
||||
static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) {
|
||||
// It is definitely wrong to take ownership of this pointer, so mask that rvp
|
||||
if (policy == return_value_policy::take_ownership || policy == return_value_policy::automatic)
|
||||
if (policy == return_value_policy::take_ownership
|
||||
|| policy == return_value_policy::automatic) {
|
||||
policy = return_value_policy::automatic_reference;
|
||||
}
|
||||
return caster_t::cast(&src.get(), policy, parent);
|
||||
}
|
||||
template <typename T> using cast_op_type = std::reference_wrapper<type>;
|
||||
@ -112,8 +114,9 @@ public:
|
||||
bool load(handle src, bool convert) {
|
||||
py_type py_value;
|
||||
|
||||
if (!src)
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(PYPY_VERSION)
|
||||
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
|
||||
@ -124,10 +127,11 @@ public:
|
||||
#endif
|
||||
|
||||
if (std::is_floating_point<T>::value) {
|
||||
if (convert || PyFloat_Check(src.ptr()))
|
||||
if (convert || PyFloat_Check(src.ptr())) {
|
||||
py_value = (py_type) PyFloat_AsDouble(src.ptr());
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (PyFloat_Check(src.ptr())
|
||||
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
|
||||
return false;
|
||||
@ -214,8 +218,9 @@ public:
|
||||
template<typename T> struct void_caster {
|
||||
public:
|
||||
bool load(handle src, bool) {
|
||||
if (src && src.is_none())
|
||||
if (src && src.is_none()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static handle cast(T, return_value_policy /* policy */, handle /* parent */) {
|
||||
@ -257,8 +262,9 @@ public:
|
||||
}
|
||||
|
||||
static handle cast(const void *ptr, return_value_policy /* policy */, handle /* parent */) {
|
||||
if (ptr)
|
||||
if (ptr) {
|
||||
return capsule(ptr).release();
|
||||
}
|
||||
return none().inc_ref();
|
||||
}
|
||||
|
||||
@ -274,7 +280,9 @@ template <> class type_caster<std::nullptr_t> : public void_caster<std::nullptr_
|
||||
template <> class type_caster<bool> {
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!src) return false;
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
if (src.ptr() == Py_True) {
|
||||
value = true;
|
||||
return true;
|
||||
@ -391,8 +399,9 @@ template <typename StringType, bool IsView = false> struct string_caster {
|
||||
value = StringType(buffer, length);
|
||||
|
||||
// If we're loading a string_view we need to keep the encoded Python object alive:
|
||||
if (IsView)
|
||||
if (IsView) {
|
||||
loader_life_support::add_patient(utfNbytes);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -401,7 +410,9 @@ template <typename StringType, bool IsView = false> struct string_caster {
|
||||
const char *buffer = reinterpret_cast<const char *>(src.data());
|
||||
auto nbytes = ssize_t(src.size() * sizeof(CharT));
|
||||
handle s = decode_utfN(buffer, nbytes);
|
||||
if (!s) throw error_already_set();
|
||||
if (!s) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -463,10 +474,14 @@ template <typename CharT> struct type_caster<CharT, enable_if_t<is_std_char_type
|
||||
CharT one_char = 0;
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!src) return false;
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
if (src.is_none()) {
|
||||
// Defer accepting None to other overloads (if we aren't in convert mode):
|
||||
if (!convert) return false;
|
||||
if (!convert) {
|
||||
return false;
|
||||
}
|
||||
none = true;
|
||||
return true;
|
||||
}
|
||||
@ -474,14 +489,18 @@ public:
|
||||
}
|
||||
|
||||
static handle cast(const CharT *src, return_value_policy policy, handle parent) {
|
||||
if (src == nullptr) return pybind11::none().inc_ref();
|
||||
if (src == nullptr) {
|
||||
return pybind11::none().inc_ref();
|
||||
}
|
||||
return StringCaster::cast(StringType(src), policy, parent);
|
||||
}
|
||||
|
||||
static handle cast(CharT src, return_value_policy policy, handle parent) {
|
||||
if (std::is_same<char, CharT>::value) {
|
||||
handle s = PyUnicode_DecodeLatin1((const char *) &src, 1, nullptr);
|
||||
if (!s) throw error_already_set();
|
||||
if (!s) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return StringCaster::cast(StringType(1, src), policy, parent);
|
||||
@ -491,13 +510,15 @@ public:
|
||||
return none ? nullptr : const_cast<CharT *>(static_cast<StringType &>(str_caster).c_str());
|
||||
}
|
||||
explicit operator CharT &() {
|
||||
if (none)
|
||||
if (none) {
|
||||
throw value_error("Cannot convert None to a character");
|
||||
}
|
||||
|
||||
auto &value = static_cast<StringType &>(str_caster);
|
||||
size_t str_len = value.size();
|
||||
if (str_len == 0)
|
||||
if (str_len == 0) {
|
||||
throw value_error("Cannot convert empty string to a character");
|
||||
}
|
||||
|
||||
// If we're in UTF-8 mode, we have two possible failures: one for a unicode character that
|
||||
// is too high, and one for multiple unicode characters (caught later), so we need to figure
|
||||
@ -531,12 +552,14 @@ public:
|
||||
// string was too long" error).
|
||||
else if (PYBIND11_SILENCE_MSVC_C4127(StringCaster::UTF_N == 16) && str_len == 2) {
|
||||
one_char = static_cast<CharT>(value[0]);
|
||||
if (one_char >= 0xD800 && one_char < 0xE000)
|
||||
if (one_char >= 0xD800 && one_char < 0xE000) {
|
||||
throw value_error("Character code point not in range(0x10000)");
|
||||
}
|
||||
}
|
||||
|
||||
if (str_len != 1)
|
||||
if (str_len != 1) {
|
||||
throw value_error("Expected a character, but multi-character string found");
|
||||
}
|
||||
|
||||
one_char = value[0];
|
||||
return one_char;
|
||||
@ -554,11 +577,13 @@ template <template<typename...> class Tuple, typename... Ts> class tuple_caster
|
||||
public:
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<sequence>(src))
|
||||
if (!isinstance<sequence>(src)) {
|
||||
return false;
|
||||
}
|
||||
const auto seq = reinterpret_borrow<sequence>(src);
|
||||
if (seq.size() != size)
|
||||
if (seq.size() != size) {
|
||||
return false;
|
||||
}
|
||||
return load_impl(seq, convert, indices{});
|
||||
}
|
||||
|
||||
@ -570,7 +595,9 @@ public:
|
||||
// copied from the PYBIND11_TYPE_CASTER macro
|
||||
template <typename T>
|
||||
static handle cast(T *src, return_value_policy policy, handle parent) {
|
||||
if (!src) return none().release();
|
||||
if (!src) {
|
||||
return none().release();
|
||||
}
|
||||
if (policy == return_value_policy::take_ownership) {
|
||||
auto h = cast(std::move(*src), policy, parent);
|
||||
delete src;
|
||||
@ -597,8 +624,9 @@ protected:
|
||||
template <size_t... Is>
|
||||
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
|
||||
#ifdef __cpp_fold_expressions
|
||||
if ((... || !std::get<Is>(subcasters).load(seq[Is], convert)))
|
||||
if ((... || !std::get<Is>(subcasters).load(seq[Is], convert))) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
for (bool r : {std::get<Is>(subcasters).load(seq[Is], convert)...})
|
||||
if (!r)
|
||||
@ -615,13 +643,16 @@ protected:
|
||||
std::array<object, size> entries{{
|
||||
reinterpret_steal<object>(make_caster<Ts>::cast(std::get<Is>(std::forward<T>(src)), policy, parent))...
|
||||
}};
|
||||
for (const auto &entry: entries)
|
||||
if (!entry)
|
||||
for (const auto &entry : entries) {
|
||||
if (!entry) {
|
||||
return handle();
|
||||
}
|
||||
}
|
||||
tuple result(size);
|
||||
int counter = 0;
|
||||
for (auto & entry: entries)
|
||||
for (auto &entry : entries) {
|
||||
PyTuple_SET_ITEM(result.ptr(), counter++, entry.release().ptr());
|
||||
}
|
||||
return result.release();
|
||||
}
|
||||
|
||||
@ -676,8 +707,9 @@ public:
|
||||
protected:
|
||||
friend class type_caster_generic;
|
||||
void check_holder_compat() {
|
||||
if (typeinfo->default_holder)
|
||||
if (typeinfo->default_holder) {
|
||||
throw cast_error("Unable to load a custom holder type from a default-holder instance");
|
||||
}
|
||||
}
|
||||
|
||||
bool load_value(value_and_holder &&v_h) {
|
||||
@ -793,8 +825,9 @@ struct pyobject_caster {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if (!isinstance<type>(src))
|
||||
if (!isinstance<type>(src)) {
|
||||
return false;
|
||||
}
|
||||
value = reinterpret_borrow<type>(src);
|
||||
return true;
|
||||
}
|
||||
@ -901,12 +934,14 @@ template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> =
|
||||
object cast(T &&value, return_value_policy policy = return_value_policy::automatic_reference,
|
||||
handle parent = handle()) {
|
||||
using no_ref_T = typename std::remove_reference<T>::type;
|
||||
if (policy == return_value_policy::automatic)
|
||||
if (policy == return_value_policy::automatic) {
|
||||
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::take_ownership :
|
||||
std::is_lvalue_reference<T>::value ? return_value_policy::copy : return_value_policy::move;
|
||||
else if (policy == return_value_policy::automatic_reference)
|
||||
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::reference :
|
||||
std::is_lvalue_reference<T>::value ? return_value_policy::copy : return_value_policy::move;
|
||||
} else if (policy == return_value_policy::automatic_reference) {
|
||||
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::reference
|
||||
: std::is_lvalue_reference<T>::value ? return_value_policy::copy
|
||||
: return_value_policy::move;
|
||||
}
|
||||
return reinterpret_steal<object>(detail::make_caster<T>::cast(std::forward<T>(value), policy, parent));
|
||||
}
|
||||
|
||||
@ -939,8 +974,9 @@ template <typename T> detail::enable_if_t<detail::move_always<T>::value, T> cast
|
||||
return move<T>(std::move(object));
|
||||
}
|
||||
template <typename T> detail::enable_if_t<detail::move_if_unreferenced<T>::value, T> cast(object &&object) {
|
||||
if (object.ref_count() > 1)
|
||||
if (object.ref_count() > 1) {
|
||||
return cast<T>(object);
|
||||
}
|
||||
return move<T>(std::move(object));
|
||||
}
|
||||
template <typename T> detail::enable_if_t<detail::move_never<T>::value, T> cast(object &&object) {
|
||||
@ -1018,8 +1054,9 @@ template <return_value_policy policy = return_value_policy::automatic_reference,
|
||||
}
|
||||
tuple result(size);
|
||||
int counter = 0;
|
||||
for (auto &arg_value : args)
|
||||
for (auto &arg_value : args) {
|
||||
PyTuple_SET_ITEM(result.ptr(), counter++, arg_value.release().ptr());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1231,8 +1268,9 @@ public:
|
||||
/// Call a Python function and pass the collected arguments
|
||||
object call(PyObject *ptr) const {
|
||||
PyObject *result = PyObject_CallObject(ptr, m_args.ptr());
|
||||
if (!result)
|
||||
if (!result) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
@ -1264,8 +1302,9 @@ public:
|
||||
/// Call a Python function and pass the collected arguments
|
||||
object call(PyObject *ptr) const {
|
||||
PyObject *result = PyObject_Call(ptr, m_args.ptr(), m_kwargs.ptr());
|
||||
if (!result)
|
||||
if (!result) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
@ -1285,8 +1324,9 @@ private:
|
||||
}
|
||||
|
||||
void process(list &args_list, detail::args_proxy ap) {
|
||||
for (auto a : ap)
|
||||
for (auto a : ap) {
|
||||
args_list.append(a);
|
||||
}
|
||||
}
|
||||
|
||||
void process(list &/*args_list*/, arg_v a) {
|
||||
@ -1315,8 +1355,9 @@ private:
|
||||
}
|
||||
|
||||
void process(list &/*args_list*/, detail::kwargs_proxy kp) {
|
||||
if (!kp)
|
||||
if (!kp) {
|
||||
return;
|
||||
}
|
||||
for (auto k : reinterpret_borrow<dict>(kp)) {
|
||||
if (m_kwargs.contains(k.first)) {
|
||||
#if defined(NDEBUG)
|
||||
|
@ -46,7 +46,9 @@ public:
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
|
||||
if (!src) return false;
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
// If invoked with datetime.delta object
|
||||
if (PyDelta_Check(src.ptr())) {
|
||||
value = type(duration_cast<duration<rep, period>>(
|
||||
@ -124,7 +126,9 @@ public:
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
|
||||
if (!src) return false;
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tm cal;
|
||||
microseconds msecs;
|
||||
@ -156,8 +160,9 @@ public:
|
||||
cal.tm_year = 70; // earliest available date for Python's datetime
|
||||
cal.tm_isdst = -1;
|
||||
msecs = microseconds(PyDateTime_TIME_GET_MICROSECOND(src.ptr()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
|
||||
value = time_point_cast<Duration>(system_clock::from_time_t(std::mktime(&cal)) + msecs);
|
||||
return true;
|
||||
@ -173,8 +178,9 @@ public:
|
||||
// (cfr. https://github.com/pybind/pybind11/issues/2417)
|
||||
using us_t = duration<int, std::micro>;
|
||||
auto us = duration_cast<us_t>(src.time_since_epoch() % seconds(1));
|
||||
if (us.count() < 0)
|
||||
if (us.count() < 0) {
|
||||
us += seconds(1);
|
||||
}
|
||||
|
||||
// Subtract microseconds BEFORE `system_clock::to_time_t`, because:
|
||||
// > If std::time_t has lower precision, it is implementation-defined whether the value is rounded or truncated.
|
||||
@ -183,8 +189,9 @@ public:
|
||||
|
||||
std::tm localtime;
|
||||
std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime);
|
||||
if (!localtime_ptr)
|
||||
if (!localtime_ptr) {
|
||||
throw cast_error("Unable to represent system_clock in local time");
|
||||
}
|
||||
return PyDateTime_FromDateAndTime(localtime.tm_year + 1900,
|
||||
localtime.tm_mon + 1,
|
||||
localtime.tm_mday,
|
||||
|
@ -42,10 +42,12 @@ template <typename T> struct is_fmt_numeric<std::complex<T>, detail::enable_if_t
|
||||
template <typename T> class type_caster<std::complex<T>> {
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!src)
|
||||
if (!src) {
|
||||
return false;
|
||||
if (!convert && !PyComplex_Check(src.ptr()))
|
||||
}
|
||||
if (!convert && !PyComplex_Check(src.ptr())) {
|
||||
return false;
|
||||
}
|
||||
Py_complex result = PyComplex_AsCComplex(src.ptr());
|
||||
if (result.real == -1.0 && PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
|
@ -66,8 +66,9 @@ inline PyTypeObject *make_static_property_type() {
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||
if (!heap_type)
|
||||
if (!heap_type) {
|
||||
pybind11_fail("make_static_property_type(): error allocating type!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
@ -81,8 +82,9 @@ inline PyTypeObject *make_static_property_type() {
|
||||
type->tp_descr_get = pybind11_static_get;
|
||||
type->tp_descr_set = pybind11_static_set;
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail("make_static_property_type(): failure in PyType_Ready()!");
|
||||
}
|
||||
|
||||
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||
@ -209,19 +211,21 @@ extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
|
||||
auto tindex = std::type_index(*tinfo->cpptype);
|
||||
internals.direct_conversions.erase(tindex);
|
||||
|
||||
if (tinfo->module_local)
|
||||
if (tinfo->module_local) {
|
||||
get_local_internals().registered_types_cpp.erase(tindex);
|
||||
else
|
||||
} else {
|
||||
internals.registered_types_cpp.erase(tindex);
|
||||
}
|
||||
internals.registered_types_py.erase(tinfo->type);
|
||||
|
||||
// Actually just `std::erase_if`, but that's only available in C++20
|
||||
auto &cache = internals.inactive_override_cache;
|
||||
for (auto it = cache.begin(), last = cache.end(); it != last; ) {
|
||||
if (it->first == (PyObject *) tinfo->type)
|
||||
if (it->first == (PyObject *) tinfo->type) {
|
||||
it = cache.erase(it);
|
||||
else
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
delete tinfo;
|
||||
@ -242,8 +246,9 @@ inline PyTypeObject* make_default_metaclass() {
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||
if (!heap_type)
|
||||
if (!heap_type) {
|
||||
pybind11_fail("make_default_metaclass(): error allocating metaclass!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
@ -264,8 +269,9 @@ inline PyTypeObject* make_default_metaclass() {
|
||||
|
||||
type->tp_dealloc = pybind11_meta_dealloc;
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail("make_default_metaclass(): failure in PyType_Ready()!");
|
||||
}
|
||||
|
||||
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||
@ -283,8 +289,9 @@ inline void traverse_offset_bases(void *valueptr, const detail::type_info *tinfo
|
||||
for (auto &c : parent_tinfo->implicit_casts) {
|
||||
if (c.first == tinfo->cpptype) {
|
||||
auto *parentptr = c.second(valueptr);
|
||||
if (parentptr != valueptr)
|
||||
if (parentptr != valueptr) {
|
||||
f(parentptr, self);
|
||||
}
|
||||
traverse_offset_bases(parentptr, parent_tinfo, self, f);
|
||||
break;
|
||||
}
|
||||
@ -311,14 +318,16 @@ inline bool deregister_instance_impl(void *ptr, instance *self) {
|
||||
|
||||
inline void register_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||
register_instance_impl(valptr, self);
|
||||
if (!tinfo->simple_ancestors)
|
||||
if (!tinfo->simple_ancestors) {
|
||||
traverse_offset_bases(valptr, tinfo, self, register_instance_impl);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||
bool ret = deregister_instance_impl(valptr, self);
|
||||
if (!tinfo->simple_ancestors)
|
||||
if (!tinfo->simple_ancestors) {
|
||||
traverse_offset_bases(valptr, tinfo, self, deregister_instance_impl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -377,8 +386,9 @@ inline void clear_patients(PyObject *self) {
|
||||
auto patients = std::move(pos->second);
|
||||
internals.patients.erase(pos);
|
||||
instance->has_patients = false;
|
||||
for (PyObject *&patient : patients)
|
||||
for (PyObject *&patient : patients) {
|
||||
Py_CLEAR(patient);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears all internal data from the instance and removes it from registered instances in
|
||||
@ -392,25 +402,32 @@ inline void clear_instance(PyObject *self) {
|
||||
|
||||
// We have to deregister before we call dealloc because, for virtual MI types, we still
|
||||
// need to be able to get the parent pointers.
|
||||
if (v_h.instance_registered() && !deregister_instance(instance, v_h.value_ptr(), v_h.type))
|
||||
pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||
if (v_h.instance_registered()
|
||||
&& !deregister_instance(instance, v_h.value_ptr(), v_h.type)) {
|
||||
pybind11_fail(
|
||||
"pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||
}
|
||||
|
||||
if (instance->owned || v_h.holder_constructed())
|
||||
if (instance->owned || v_h.holder_constructed()) {
|
||||
v_h.type->dealloc(v_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Deallocate the value/holder layout internals:
|
||||
instance->deallocate_layout();
|
||||
|
||||
if (instance->weakrefs)
|
||||
if (instance->weakrefs) {
|
||||
PyObject_ClearWeakRefs(self);
|
||||
}
|
||||
|
||||
PyObject **dict_ptr = _PyObject_GetDictPtr(self);
|
||||
if (dict_ptr)
|
||||
if (dict_ptr) {
|
||||
Py_CLEAR(*dict_ptr);
|
||||
}
|
||||
|
||||
if (instance->has_patients)
|
||||
if (instance->has_patients) {
|
||||
clear_patients(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Instance destructor function for all pybind11 types. It calls `type_info.dealloc`
|
||||
@ -448,8 +465,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||
if (!heap_type)
|
||||
if (!heap_type) {
|
||||
pybind11_fail("make_object_base_type(): error allocating type!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
@ -469,8 +487,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||
/* Support weak references (needed for the keep_alive feature) */
|
||||
type->tp_weaklistoffset = offsetof(instance, weakrefs);
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail("PyType_Ready failed in make_object_base_type():" + error_string());
|
||||
}
|
||||
|
||||
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||
@ -482,8 +501,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||
/// dynamic_attr: Support for `d = instance.__dict__`.
|
||||
extern "C" inline PyObject *pybind11_get_dict(PyObject *self, void *) {
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(self);
|
||||
if (!dict)
|
||||
if (!dict) {
|
||||
dict = PyDict_New();
|
||||
}
|
||||
Py_XINCREF(dict);
|
||||
return dict;
|
||||
}
|
||||
@ -538,12 +558,14 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
|
||||
type_info *tinfo = nullptr;
|
||||
for (auto type : reinterpret_borrow<tuple>(Py_TYPE(obj)->tp_mro)) {
|
||||
tinfo = get_type_info((PyTypeObject *) type.ptr());
|
||||
if (tinfo && tinfo->get_buffer)
|
||||
if (tinfo && tinfo->get_buffer) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (view == nullptr || !tinfo || !tinfo->get_buffer) {
|
||||
if (view)
|
||||
if (view) {
|
||||
view->obj = nullptr;
|
||||
}
|
||||
PyErr_SetString(PyExc_BufferError, "pybind11_getbuffer(): Internal error");
|
||||
return -1;
|
||||
}
|
||||
@ -561,11 +583,13 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
|
||||
view->buf = info->ptr;
|
||||
view->itemsize = info->itemsize;
|
||||
view->len = view->itemsize;
|
||||
for (auto s : info->shape)
|
||||
for (auto s : info->shape) {
|
||||
view->len *= s;
|
||||
}
|
||||
view->readonly = static_cast<int>(info->readonly);
|
||||
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
|
||||
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
|
||||
view->format = const_cast<char *>(info->format.c_str());
|
||||
}
|
||||
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
|
||||
view->ndim = (int) info->ndim;
|
||||
view->strides = info->strides.data();
|
||||
@ -608,10 +632,11 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
|
||||
object module_;
|
||||
if (rec.scope) {
|
||||
if (hasattr(rec.scope, "__module__"))
|
||||
if (hasattr(rec.scope, "__module__")) {
|
||||
module_ = rec.scope.attr("__module__");
|
||||
else if (hasattr(rec.scope, "__name__"))
|
||||
} else if (hasattr(rec.scope, "__name__")) {
|
||||
module_ = rec.scope.attr("__name__");
|
||||
}
|
||||
}
|
||||
|
||||
auto full_name = c_str(
|
||||
@ -642,8 +667,9 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
: internals.default_metaclass;
|
||||
|
||||
auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||
if (!heap_type)
|
||||
if (!heap_type) {
|
||||
pybind11_fail(std::string(rec.name) + ": Unable to create type object!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name.release().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
@ -655,8 +681,9 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
type->tp_doc = tp_doc;
|
||||
type->tp_base = type_incref((PyTypeObject *)base);
|
||||
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
|
||||
if (!bases.empty())
|
||||
if (!bases.empty()) {
|
||||
type->tp_bases = bases.release().ptr();
|
||||
}
|
||||
|
||||
/* Don't inherit base __init__ */
|
||||
type->tp_init = pybind11_object_init;
|
||||
@ -674,31 +701,38 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
|
||||
#endif
|
||||
if (!rec.is_final)
|
||||
if (!rec.is_final) {
|
||||
type->tp_flags |= Py_TPFLAGS_BASETYPE;
|
||||
}
|
||||
|
||||
if (rec.dynamic_attr)
|
||||
if (rec.dynamic_attr) {
|
||||
enable_dynamic_attributes(heap_type);
|
||||
}
|
||||
|
||||
if (rec.buffer_protocol)
|
||||
if (rec.buffer_protocol) {
|
||||
enable_buffer_protocol(heap_type);
|
||||
}
|
||||
|
||||
if (rec.custom_type_setup_callback)
|
||||
if (rec.custom_type_setup_callback) {
|
||||
rec.custom_type_setup_callback(heap_type);
|
||||
}
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail(std::string(rec.name) + ": PyType_Ready failed (" + error_string() + ")!");
|
||||
}
|
||||
|
||||
assert(!rec.dynamic_attr || PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||
|
||||
/* Register type with the parent scope */
|
||||
if (rec.scope)
|
||||
if (rec.scope) {
|
||||
setattr(rec.scope, rec.name, (PyObject *) type);
|
||||
else
|
||||
} else {
|
||||
Py_INCREF(type); // Keep it alive forever (reference leak)
|
||||
}
|
||||
|
||||
if (module_) // Needed by pydoc
|
||||
if (module_) { // Needed by pydoc
|
||||
setattr((PyObject *) type, "__module__", module_);
|
||||
}
|
||||
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, qualname);
|
||||
|
||||
|
@ -33,7 +33,9 @@ private:
|
||||
PYBIND11_NAMESPACE_BEGIN(initimpl)
|
||||
|
||||
inline void no_nullptr(void *ptr) {
|
||||
if (!ptr) throw type_error("pybind11::init(): factory function returned nullptr");
|
||||
if (!ptr) {
|
||||
throw type_error("pybind11::init(): factory function returned nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
// Implementing functions for all forms of py::init<...> and py::init(...)
|
||||
@ -136,9 +138,10 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
|
||||
auto *ptr = holder_helper<Holder<Class>>::get(holder);
|
||||
no_nullptr(ptr);
|
||||
// If we need an alias, check that the held pointer is actually an alias instance
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr))
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) {
|
||||
throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
|
||||
"is not an alias instance");
|
||||
}
|
||||
|
||||
v_h.value_ptr() = ptr;
|
||||
v_h.type->init_instance(v_h.inst, &holder);
|
||||
@ -153,10 +156,11 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||
static_assert(std::is_move_constructible<Cpp<Class>>::value,
|
||||
"pybind11::init() return-by-value factory function requires a movable class");
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias)
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias) {
|
||||
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
|
||||
else
|
||||
} else {
|
||||
v_h.value_ptr() = new Cpp<Class>(std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
// return-by-value version 2: returning a value of the alias type itself. We move-construct an
|
||||
@ -183,12 +187,19 @@ struct constructor {
|
||||
enable_if_t<Class::has_alias &&
|
||||
std::is_constructible<Cpp<Class>, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
cl.def("__init__", [](value_and_holder &v_h, Args... args) {
|
||||
if (Py_TYPE(v_h.inst) == v_h.type->type)
|
||||
v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||
else
|
||||
v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
cl.def(
|
||||
"__init__",
|
||||
[](value_and_holder &v_h, Args... args) {
|
||||
if (Py_TYPE(v_h.inst) == v_h.type->type) {
|
||||
v_h.value_ptr()
|
||||
= construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||
} else {
|
||||
v_h.value_ptr()
|
||||
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
}
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
|
||||
template <typename Class, typename... Extra,
|
||||
|
@ -398,8 +398,9 @@ inline void translate_local_exception(std::exception_ptr p) {
|
||||
/// Return a reference to the current `internals` data
|
||||
PYBIND11_NOINLINE internals &get_internals() {
|
||||
auto **&internals_pp = get_internals_pp();
|
||||
if (internals_pp && *internals_pp)
|
||||
if (internals_pp && *internals_pp) {
|
||||
return **internals_pp;
|
||||
}
|
||||
|
||||
// Ensure that the GIL is held since we will need to make Python calls.
|
||||
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
|
||||
@ -425,7 +426,9 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
(*internals_pp)->registered_exception_translators.push_front(&translate_local_exception);
|
||||
#endif
|
||||
} else {
|
||||
if (!internals_pp) internals_pp = new internals*();
|
||||
if (!internals_pp) {
|
||||
internals_pp = new internals *();
|
||||
}
|
||||
auto *&internals_ptr = *internals_pp;
|
||||
internals_ptr = new internals();
|
||||
#if defined(WITH_THREAD)
|
||||
|
@ -69,11 +69,13 @@ public:
|
||||
|
||||
/// ... and destroyed after it returns
|
||||
~loader_life_support() {
|
||||
if (get_stack_top() != this)
|
||||
if (get_stack_top() != this) {
|
||||
pybind11_fail("loader_life_support: internal error");
|
||||
}
|
||||
set_stack_top(parent);
|
||||
for (auto* item : keep_alive)
|
||||
for (auto *item : keep_alive) {
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// This can only be used inside a pybind11-bound function, either by `argument_loader`
|
||||
@ -90,8 +92,9 @@ public:
|
||||
"of temporary values");
|
||||
}
|
||||
|
||||
if (frame->keep_alive.insert(h.ptr()).second)
|
||||
if (frame->keep_alive.insert(h.ptr()).second) {
|
||||
Py_INCREF(h.ptr());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -103,14 +106,17 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
|
||||
// Populates a just-created cache entry.
|
||||
PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_info *> &bases) {
|
||||
std::vector<PyTypeObject *> check;
|
||||
for (handle parent : reinterpret_borrow<tuple>(t->tp_bases))
|
||||
for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
|
||||
check.push_back((PyTypeObject *) parent.ptr());
|
||||
}
|
||||
|
||||
auto const &type_dict = get_internals().registered_types_py;
|
||||
for (size_t i = 0; i < check.size(); i++) {
|
||||
auto type = check[i];
|
||||
// Ignore Python2 old-style class super type:
|
||||
if (!PyType_Check((PyObject *) type)) continue;
|
||||
if (!PyType_Check((PyObject *) type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check `type` in the current set of registered python types:
|
||||
auto it = type_dict.find(type);
|
||||
@ -127,7 +133,9 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
|
||||
for (auto *known : bases) {
|
||||
if (known == tinfo) { found = true; break; }
|
||||
}
|
||||
if (!found) bases.push_back(tinfo);
|
||||
if (!found) {
|
||||
bases.push_back(tinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type->tp_bases) {
|
||||
@ -140,8 +148,9 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
|
||||
check.pop_back();
|
||||
i--;
|
||||
}
|
||||
for (handle parent : reinterpret_borrow<tuple>(type->tp_bases))
|
||||
for (handle parent : reinterpret_borrow<tuple>(type->tp_bases)) {
|
||||
check.push_back((PyTypeObject *) parent.ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,9 +167,10 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
|
||||
*/
|
||||
inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) {
|
||||
auto ins = all_type_info_get_cache(type);
|
||||
if (ins.second)
|
||||
if (ins.second) {
|
||||
// New cache entry: populate it
|
||||
all_type_info_populate(type, ins.first->second);
|
||||
}
|
||||
|
||||
return ins.first->second;
|
||||
}
|
||||
@ -172,36 +182,43 @@ inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type)
|
||||
*/
|
||||
PYBIND11_NOINLINE detail::type_info* get_type_info(PyTypeObject *type) {
|
||||
auto &bases = all_type_info(type);
|
||||
if (bases.empty())
|
||||
if (bases.empty()) {
|
||||
return nullptr;
|
||||
if (bases.size() > 1)
|
||||
pybind11_fail("pybind11::detail::get_type_info: type has multiple pybind11-registered bases");
|
||||
}
|
||||
if (bases.size() > 1) {
|
||||
pybind11_fail(
|
||||
"pybind11::detail::get_type_info: type has multiple pybind11-registered bases");
|
||||
}
|
||||
return bases.front();
|
||||
}
|
||||
|
||||
inline detail::type_info *get_local_type_info(const std::type_index &tp) {
|
||||
auto &locals = get_local_internals().registered_types_cpp;
|
||||
auto it = locals.find(tp);
|
||||
if (it != locals.end())
|
||||
if (it != locals.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline detail::type_info *get_global_type_info(const std::type_index &tp) {
|
||||
auto &types = get_internals().registered_types_cpp;
|
||||
auto it = types.find(tp);
|
||||
if (it != types.end())
|
||||
if (it != types.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Return the type info for a given C++ type; on lookup failure can either throw or return nullptr.
|
||||
PYBIND11_NOINLINE detail::type_info *get_type_info(const std::type_index &tp,
|
||||
bool throw_if_missing = false) {
|
||||
if (auto ltype = get_local_type_info(tp))
|
||||
if (auto ltype = get_local_type_info(tp)) {
|
||||
return ltype;
|
||||
if (auto gtype = get_global_type_info(tp))
|
||||
}
|
||||
if (auto gtype = get_global_type_info(tp)) {
|
||||
return gtype;
|
||||
}
|
||||
|
||||
if (throw_if_missing) {
|
||||
std::string tname = tp.name();
|
||||
@ -222,8 +239,9 @@ PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
|
||||
auto it_instances = get_internals().registered_instances.equal_range(src);
|
||||
for (auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) {
|
||||
for (auto instance_type : detail::all_type_info(Py_TYPE(it_i->second))) {
|
||||
if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype))
|
||||
if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype)) {
|
||||
return handle((PyObject *) it_i->second).inc_ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
return handle();
|
||||
@ -263,12 +281,13 @@ struct value_and_holder {
|
||||
}
|
||||
// NOLINTNEXTLINE(readability-make-member-function-const)
|
||||
void set_holder_constructed(bool v = true) {
|
||||
if (inst->simple_layout)
|
||||
if (inst->simple_layout) {
|
||||
inst->simple_holder_constructed = v;
|
||||
else if (v)
|
||||
} else if (v) {
|
||||
inst->nonsimple.status[index] |= instance::status_holder_constructed;
|
||||
else
|
||||
} else {
|
||||
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_holder_constructed;
|
||||
}
|
||||
}
|
||||
bool instance_registered() const {
|
||||
return inst->simple_layout
|
||||
@ -277,12 +296,13 @@ struct value_and_holder {
|
||||
}
|
||||
// NOLINTNEXTLINE(readability-make-member-function-const)
|
||||
void set_instance_registered(bool v = true) {
|
||||
if (inst->simple_layout)
|
||||
if (inst->simple_layout) {
|
||||
inst->simple_instance_registered = v;
|
||||
else if (v)
|
||||
} else if (v) {
|
||||
inst->nonsimple.status[index] |= instance::status_instance_registered;
|
||||
else
|
||||
} else {
|
||||
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_instance_registered;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -317,8 +337,9 @@ public:
|
||||
bool operator==(const iterator &other) const { return curr.index == other.curr.index; }
|
||||
bool operator!=(const iterator &other) const { return curr.index != other.curr.index; }
|
||||
iterator &operator++() {
|
||||
if (!inst->simple_layout)
|
||||
if (!inst->simple_layout) {
|
||||
curr.vh += 1 + (*types)[curr.index]->holder_size_in_ptrs;
|
||||
}
|
||||
++curr.index;
|
||||
curr.type = curr.index < types->size() ? (*types)[curr.index] : nullptr;
|
||||
return *this;
|
||||
@ -332,7 +353,9 @@ public:
|
||||
|
||||
iterator find(const type_info *find_type) {
|
||||
auto it = begin(), endit = end();
|
||||
while (it != endit && it->type != find_type) ++it;
|
||||
while (it != endit && it->type != find_type) {
|
||||
++it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
@ -351,16 +374,19 @@ public:
|
||||
*/
|
||||
PYBIND11_NOINLINE value_and_holder instance::get_value_and_holder(const type_info *find_type /*= nullptr default in common.h*/, bool throw_if_missing /*= true in common.h*/) {
|
||||
// Optimize common case:
|
||||
if (!find_type || Py_TYPE(this) == find_type->type)
|
||||
if (!find_type || Py_TYPE(this) == find_type->type) {
|
||||
return value_and_holder(this, find_type, 0, 0);
|
||||
}
|
||||
|
||||
detail::values_and_holders vhs(this);
|
||||
auto it = vhs.find(find_type);
|
||||
if (it != vhs.end())
|
||||
if (it != vhs.end()) {
|
||||
return *it;
|
||||
}
|
||||
|
||||
if (!throw_if_missing)
|
||||
if (!throw_if_missing) {
|
||||
return value_and_holder();
|
||||
}
|
||||
|
||||
#if defined(NDEBUG)
|
||||
pybind11_fail("pybind11::detail::instance::get_value_and_holder: "
|
||||
@ -378,8 +404,10 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
|
||||
|
||||
const size_t n_types = tinfo.size();
|
||||
|
||||
if (n_types == 0)
|
||||
pybind11_fail("instance allocation failed: new instance has no pybind11-registered base types");
|
||||
if (n_types == 0) {
|
||||
pybind11_fail(
|
||||
"instance allocation failed: new instance has no pybind11-registered base types");
|
||||
}
|
||||
|
||||
simple_layout =
|
||||
n_types == 1 && tinfo.front()->holder_size_in_ptrs <= instance_simple_holder_in_ptrs();
|
||||
@ -410,7 +438,9 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
|
||||
// just wrappers around malloc.
|
||||
#if PY_VERSION_HEX >= 0x03050000
|
||||
nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
|
||||
if (!nonsimple.values_and_holders) throw std::bad_alloc();
|
||||
if (!nonsimple.values_and_holders) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
#else
|
||||
nonsimple.values_and_holders = (void **) PyMem_New(void *, space);
|
||||
if (!nonsimple.values_and_holders) throw std::bad_alloc();
|
||||
@ -423,14 +453,16 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
|
||||
|
||||
// NOLINTNEXTLINE(readability-make-member-function-const)
|
||||
PYBIND11_NOINLINE void instance::deallocate_layout() {
|
||||
if (!simple_layout)
|
||||
if (!simple_layout) {
|
||||
PyMem_Free(nonsimple.values_and_holders);
|
||||
}
|
||||
}
|
||||
|
||||
PYBIND11_NOINLINE bool isinstance_generic(handle obj, const std::type_info &tp) {
|
||||
handle type = detail::get_type_handle(tp, false);
|
||||
if (!type)
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
return isinstance(obj, type);
|
||||
}
|
||||
|
||||
@ -447,14 +479,16 @@ PYBIND11_NOINLINE std::string error_string() {
|
||||
errorString += handle(scope.type).attr("__name__").cast<std::string>();
|
||||
errorString += ": ";
|
||||
}
|
||||
if (scope.value)
|
||||
if (scope.value) {
|
||||
errorString += (std::string) str(scope.value);
|
||||
}
|
||||
|
||||
PyErr_NormalizeException(&scope.type, &scope.value, &scope.trace);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
if (scope.trace != nullptr)
|
||||
if (scope.trace != nullptr) {
|
||||
PyException_SetTraceback(scope.value, scope.trace);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(PYPY_VERSION)
|
||||
@ -462,8 +496,9 @@ PYBIND11_NOINLINE std::string error_string() {
|
||||
auto *trace = (PyTracebackObject *) scope.trace;
|
||||
|
||||
/* Get the deepest trace possible */
|
||||
while (trace->tb_next)
|
||||
while (trace->tb_next) {
|
||||
trace = trace->tb_next;
|
||||
}
|
||||
|
||||
PyFrameObject *frame = trace->tb_frame;
|
||||
errorString += "\n\nAt:\n";
|
||||
@ -493,8 +528,9 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
|
||||
auto range = instances.equal_range(ptr);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
for (const auto &vh : values_and_holders(it->second)) {
|
||||
if (vh.type == type)
|
||||
if (vh.type == type) {
|
||||
return handle((PyObject *) it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
return handle();
|
||||
@ -535,15 +571,18 @@ public:
|
||||
void *(*copy_constructor)(const void *),
|
||||
void *(*move_constructor)(const void *),
|
||||
const void *existing_holder = nullptr) {
|
||||
if (!tinfo) // no type info: error will be set already
|
||||
if (!tinfo) { // no type info: error will be set already
|
||||
return handle();
|
||||
}
|
||||
|
||||
void *src = const_cast<void *>(_src);
|
||||
if (src == nullptr)
|
||||
if (src == nullptr) {
|
||||
return none().release();
|
||||
}
|
||||
|
||||
if (handle registered_inst = find_registered_python_instance(src, tinfo))
|
||||
if (handle registered_inst = find_registered_python_instance(src, tinfo)) {
|
||||
return registered_inst;
|
||||
}
|
||||
|
||||
auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type));
|
||||
auto wrapper = reinterpret_cast<instance *>(inst.ptr());
|
||||
@ -564,9 +603,9 @@ public:
|
||||
break;
|
||||
|
||||
case return_value_policy::copy:
|
||||
if (copy_constructor)
|
||||
if (copy_constructor) {
|
||||
valueptr = copy_constructor(src);
|
||||
else {
|
||||
} else {
|
||||
#if defined(NDEBUG)
|
||||
throw cast_error("return_value_policy = copy, but type is "
|
||||
"non-copyable! (compile in debug mode for details)");
|
||||
@ -581,11 +620,11 @@ public:
|
||||
break;
|
||||
|
||||
case return_value_policy::move:
|
||||
if (move_constructor)
|
||||
if (move_constructor) {
|
||||
valueptr = move_constructor(src);
|
||||
else if (copy_constructor)
|
||||
} else if (copy_constructor) {
|
||||
valueptr = copy_constructor(src);
|
||||
else {
|
||||
} else {
|
||||
#if defined(NDEBUG)
|
||||
throw cast_error("return_value_policy = move, but type is neither "
|
||||
"movable nor copyable! "
|
||||
@ -650,8 +689,9 @@ public:
|
||||
}
|
||||
bool try_direct_conversions(handle src) {
|
||||
for (auto &converter : *typeinfo->direct_conversions) {
|
||||
if (converter(src.ptr(), value))
|
||||
if (converter(src.ptr(), value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -659,8 +699,9 @@ public:
|
||||
|
||||
PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) {
|
||||
auto caster = type_caster_generic(ti);
|
||||
if (caster.load(src, false))
|
||||
if (caster.load(src, false)) {
|
||||
return caster.value;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -669,14 +710,16 @@ public:
|
||||
PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src) {
|
||||
constexpr auto *local_key = PYBIND11_MODULE_LOCAL_ID;
|
||||
const auto pytype = type::handle_of(src);
|
||||
if (!hasattr(pytype, local_key))
|
||||
if (!hasattr(pytype, local_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr(pytype, local_key));
|
||||
// Only consider this foreign loader if actually foreign and is a loader of the correct cpp type
|
||||
if (foreign_typeinfo->module_local_load == &local_load
|
||||
|| (cpptype && !same_type(*cpptype, *foreign_typeinfo->cpptype)))
|
||||
|| (cpptype && !same_type(*cpptype, *foreign_typeinfo->cpptype))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto result = foreign_typeinfo->module_local_load(src.ptr(), foreign_typeinfo)) {
|
||||
value = result;
|
||||
@ -690,8 +733,12 @@ public:
|
||||
// logic (without having to resort to virtual inheritance).
|
||||
template <typename ThisT>
|
||||
PYBIND11_NOINLINE bool load_impl(handle src, bool convert) {
|
||||
if (!src) return false;
|
||||
if (!typeinfo) return try_load_foreign_module_local(src);
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
if (!typeinfo) {
|
||||
return try_load_foreign_module_local(src);
|
||||
}
|
||||
|
||||
auto &this_ = static_cast<ThisT &>(*this);
|
||||
this_.check_holder_compat();
|
||||
@ -734,8 +781,9 @@ public:
|
||||
// Case 2c: C++ multiple inheritance is involved and we couldn't find an exact type match
|
||||
// in the registered bases, above, so try implicit casting (needed for proper C++ casting
|
||||
// when MI is involved).
|
||||
if (this_.try_implicit_casts(src, convert))
|
||||
if (this_.try_implicit_casts(src, convert)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform an implicit conversion
|
||||
@ -747,8 +795,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this_.try_direct_conversions(src))
|
||||
if (this_.try_direct_conversions(src)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to match local typeinfo. Try again with global.
|
||||
@ -767,7 +816,9 @@ public:
|
||||
// Custom converters didn't take None, now we convert None to nullptr.
|
||||
if (src.is_none()) {
|
||||
// Defer accepting None to other overloads (if we aren't in convert mode):
|
||||
if (!convert) return false;
|
||||
if (!convert) {
|
||||
return false;
|
||||
}
|
||||
value = nullptr;
|
||||
return true;
|
||||
}
|
||||
@ -907,8 +958,10 @@ public:
|
||||
explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) { }
|
||||
|
||||
static handle cast(const itype &src, return_value_policy policy, handle parent) {
|
||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||
if (policy == return_value_policy::automatic
|
||||
|| policy == return_value_policy::automatic_reference) {
|
||||
policy = return_value_policy::copy;
|
||||
}
|
||||
return cast(&src, policy, parent);
|
||||
}
|
||||
|
||||
@ -960,7 +1013,12 @@ public:
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator itype*() { return (type *) value; }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator itype&() { if (!value) throw reference_cast_error(); return *((itype *) value); }
|
||||
operator itype&() {
|
||||
if (!value) {
|
||||
throw reference_cast_error();
|
||||
}
|
||||
return *((itype *) value);
|
||||
}
|
||||
|
||||
protected:
|
||||
using Constructor = void *(*)(const void *);
|
||||
|
@ -24,7 +24,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
inline void erase_all(std::string &string, const std::string &search) {
|
||||
for (size_t pos = 0;;) {
|
||||
pos = string.find(search, pos);
|
||||
if (pos == std::string::npos) break;
|
||||
if (pos == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
string.erase(pos, search.length());
|
||||
}
|
||||
}
|
||||
@ -34,8 +36,9 @@ PYBIND11_NOINLINE void clean_type_id(std::string &name) {
|
||||
int status = 0;
|
||||
std::unique_ptr<char, void (*)(void *)> res {
|
||||
abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free };
|
||||
if (status == 0)
|
||||
if (status == 0) {
|
||||
name = res.get();
|
||||
}
|
||||
#else
|
||||
detail::erase_all(name, "class ");
|
||||
detail::erase_all(name, "struct ");
|
||||
|
@ -145,8 +145,9 @@ template <typename Type_> struct EigenProps {
|
||||
// (preferring the latter if it will fit in either, i.e. for a fully dynamic matrix type).
|
||||
static EigenConformable<row_major> conformable(const array &a) {
|
||||
const auto dims = a.ndim();
|
||||
if (dims < 1 || dims > 2)
|
||||
if (dims < 1 || dims > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dims == 2) { // Matrix type: require exact match (or dynamic)
|
||||
|
||||
@ -155,9 +156,10 @@ template <typename Type_> struct EigenProps {
|
||||
np_cols = a.shape(1),
|
||||
np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
|
||||
np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar));
|
||||
if ((PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && np_rows != rows) ||
|
||||
(PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols))
|
||||
if ((PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && np_rows != rows)
|
||||
|| (PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return {np_rows, np_cols, np_rstride, np_cstride};
|
||||
}
|
||||
@ -168,8 +170,9 @@ template <typename Type_> struct EigenProps {
|
||||
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
|
||||
|
||||
if (vector) { // Eigen type is a compile-time vector
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(fixed) && size != n)
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(fixed) && size != n) {
|
||||
return false; // Vector size mismatch
|
||||
}
|
||||
return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
|
||||
}
|
||||
if (fixed) {
|
||||
@ -179,10 +182,14 @@ template <typename Type_> struct EigenProps {
|
||||
if (fixed_cols) {
|
||||
// Since this isn't a vector, cols must be != 1. We allow this only if it exactly
|
||||
// equals the number of elements (rows is Dynamic, and so 1 row is allowed).
|
||||
if (cols != n) return false;
|
||||
if (cols != n) {
|
||||
return false;
|
||||
}
|
||||
return {1, n, stride};
|
||||
} // Otherwise it's either fully dynamic, or column dynamic; both become a column vector
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && rows != n) return false;
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && rows != n) {
|
||||
return false;
|
||||
}
|
||||
return {n, 1, stride};
|
||||
}
|
||||
|
||||
@ -213,14 +220,18 @@ template <typename Type_> struct EigenProps {
|
||||
template <typename props> handle eigen_array_cast(typename props::Type const &src, handle base = handle(), bool writeable = true) {
|
||||
constexpr ssize_t elem_size = sizeof(typename props::Scalar);
|
||||
array a;
|
||||
if (props::vector)
|
||||
if (props::vector) {
|
||||
a = array({ src.size() }, { elem_size * src.innerStride() }, src.data(), base);
|
||||
else
|
||||
a = array({ src.rows(), src.cols() }, { elem_size * src.rowStride(), elem_size * src.colStride() },
|
||||
src.data(), base);
|
||||
} else {
|
||||
a = array({src.rows(), src.cols()},
|
||||
{elem_size * src.rowStride(), elem_size * src.colStride()},
|
||||
src.data(),
|
||||
base);
|
||||
}
|
||||
|
||||
if (!writeable)
|
||||
if (!writeable) {
|
||||
array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||
}
|
||||
|
||||
return a.release();
|
||||
}
|
||||
@ -255,28 +266,35 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
// If we're in no-convert mode, only load if given an array of the correct type
|
||||
if (!convert && !isinstance<array_t<Scalar>>(src))
|
||||
if (!convert && !isinstance<array_t<Scalar>>(src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Coerce into an array, but don't do type conversion yet; the copy below handles it.
|
||||
auto buf = array::ensure(src);
|
||||
|
||||
if (!buf)
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dims = buf.ndim();
|
||||
if (dims < 1 || dims > 2)
|
||||
if (dims < 1 || dims > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fits = props::conformable(buf);
|
||||
if (!fits)
|
||||
if (!fits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate the new type, then build a numpy reference into it
|
||||
value = Type(fits.rows, fits.cols);
|
||||
auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value));
|
||||
if (dims == 1) ref = ref.squeeze();
|
||||
else if (ref.ndim() == 1) buf = buf.squeeze();
|
||||
if (dims == 1) {
|
||||
ref = ref.squeeze();
|
||||
} else if (ref.ndim() == 1) {
|
||||
buf = buf.squeeze();
|
||||
}
|
||||
|
||||
int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr());
|
||||
|
||||
@ -323,14 +341,18 @@ public:
|
||||
}
|
||||
// lvalue reference return; default (automatic) becomes copy
|
||||
static handle cast(Type &src, return_value_policy policy, handle parent) {
|
||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||
if (policy == return_value_policy::automatic
|
||||
|| policy == return_value_policy::automatic_reference) {
|
||||
policy = return_value_policy::copy;
|
||||
}
|
||||
return cast_impl(&src, policy, parent);
|
||||
}
|
||||
// const lvalue reference return; default (automatic) becomes copy
|
||||
static handle cast(const Type &src, return_value_policy policy, handle parent) {
|
||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||
if (policy == return_value_policy::automatic
|
||||
|| policy == return_value_policy::automatic_reference) {
|
||||
policy = return_value_policy::copy;
|
||||
}
|
||||
return cast(&src, policy, parent);
|
||||
}
|
||||
// non-const pointer return
|
||||
@ -439,11 +461,14 @@ public:
|
||||
|
||||
if (aref && (!need_writeable || aref.writeable())) {
|
||||
fits = props::conformable(aref);
|
||||
if (!fits) return false; // Incompatible dimensions
|
||||
if (!fits.template stride_compatible<props>())
|
||||
if (!fits) {
|
||||
return false; // Incompatible dimensions
|
||||
}
|
||||
if (!fits.template stride_compatible<props>()) {
|
||||
need_copy = true;
|
||||
else
|
||||
} else {
|
||||
copy_or_ref = std::move(aref);
|
||||
}
|
||||
}
|
||||
else {
|
||||
need_copy = true;
|
||||
@ -454,13 +479,18 @@ public:
|
||||
// We need to copy: If we need a mutable reference, or we're not supposed to convert
|
||||
// (either because we're in the no-convert overload pass, or because we're explicitly
|
||||
// instructed not to copy (via `py::arg().noconvert()`) we have to fail loading.
|
||||
if (!convert || need_writeable) return false;
|
||||
if (!convert || need_writeable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Array copy = Array::ensure(src);
|
||||
if (!copy) return false;
|
||||
fits = props::conformable(copy);
|
||||
if (!fits || !fits.template stride_compatible<props>())
|
||||
if (!copy) {
|
||||
return false;
|
||||
}
|
||||
fits = props::conformable(copy);
|
||||
if (!fits || !fits.template stride_compatible<props>()) {
|
||||
return false;
|
||||
}
|
||||
copy_or_ref = std::move(copy);
|
||||
loader_life_support::add_patient(copy_or_ref);
|
||||
}
|
||||
@ -550,8 +580,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
static constexpr bool rowMajor = Type::IsRowMajor;
|
||||
|
||||
bool load(handle src, bool) {
|
||||
if (!src)
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto obj = reinterpret_borrow<object>(src);
|
||||
object sparse_module = module_::import("scipy.sparse");
|
||||
@ -572,8 +603,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
auto shape = pybind11::tuple((pybind11::object) obj.attr("shape"));
|
||||
auto nnz = obj.attr("nnz").cast<Index>();
|
||||
|
||||
if (!values || !innerIndices || !outerIndices)
|
||||
if (!values || !innerIndices || !outerIndices) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = EigenMapSparseMatrix<Scalar,
|
||||
Type::Flags & (Eigen::RowMajor | Eigen::ColMajor),
|
||||
|
@ -77,12 +77,14 @@ struct embedded_module {
|
||||
using init_t = void (*)();
|
||||
#endif
|
||||
embedded_module(const char *name, init_t init) {
|
||||
if (Py_IsInitialized() != 0)
|
||||
if (Py_IsInitialized() != 0) {
|
||||
pybind11_fail("Can't add new modules after the interpreter has been initialized");
|
||||
}
|
||||
|
||||
auto result = PyImport_AppendInittab(name, init);
|
||||
if (result == -1)
|
||||
if (result == -1) {
|
||||
pybind11_fail("Insufficient memory to add a new module");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -135,8 +137,9 @@ inline void set_interpreter_argv(int argc, const char *const *argv, bool add_pro
|
||||
|
||||
const char *const empty_argv[]{"\0"};
|
||||
const char *const *safe_argv = special_case ? empty_argv : argv;
|
||||
if (special_case)
|
||||
if (special_case) {
|
||||
argc = 1;
|
||||
}
|
||||
|
||||
auto argv_size = static_cast<size_t>(argc);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
@ -192,8 +195,9 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
|
||||
int argc = 0,
|
||||
const char *const *argv = nullptr,
|
||||
bool add_program_dir_to_path = true) {
|
||||
if (Py_IsInitialized() != 0)
|
||||
if (Py_IsInitialized() != 0) {
|
||||
pybind11_fail("The interpreter is already running");
|
||||
}
|
||||
|
||||
Py_InitializeEx(init_signal_handlers ? 1 : 0);
|
||||
|
||||
@ -244,8 +248,9 @@ inline void finalize_interpreter() {
|
||||
// during destruction), so we get the pointer-pointer here and check it after Py_Finalize().
|
||||
detail::internals **internals_ptr_ptr = detail::get_internals_pp();
|
||||
// It could also be stashed in builtins, so look there too:
|
||||
if (builtins.contains(id) && isinstance<capsule>(builtins[id]))
|
||||
if (builtins.contains(id) && isinstance<capsule>(builtins[id])) {
|
||||
internals_ptr_ptr = capsule(builtins[id]);
|
||||
}
|
||||
|
||||
Py_Finalize();
|
||||
|
||||
@ -285,8 +290,9 @@ public:
|
||||
scoped_interpreter &operator=(scoped_interpreter &&) = delete;
|
||||
|
||||
~scoped_interpreter() {
|
||||
if (is_valid)
|
||||
if (is_valid) {
|
||||
finalize_interpreter();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -46,8 +46,9 @@ enum eval_mode {
|
||||
|
||||
template <eval_mode mode = eval_expr>
|
||||
object eval(const str &expr, object global = globals(), object local = object()) {
|
||||
if (!local)
|
||||
if (!local) {
|
||||
local = global;
|
||||
}
|
||||
|
||||
detail::ensure_builtins_in_globals(global);
|
||||
|
||||
@ -64,8 +65,9 @@ object eval(const str &expr, object global = globals(), object local = object())
|
||||
}
|
||||
|
||||
PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
|
||||
if (!result)
|
||||
if (!result) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
@ -102,8 +104,9 @@ object eval_file(str) {
|
||||
#else
|
||||
template <eval_mode mode = eval_statements>
|
||||
object eval_file(str fname, object global = globals(), object local = object()) {
|
||||
if (!local)
|
||||
if (!local) {
|
||||
local = global;
|
||||
}
|
||||
|
||||
detail::ensure_builtins_in_globals(global);
|
||||
|
||||
@ -154,8 +157,9 @@ object eval_file(str fname, object global = globals(), object local = object())
|
||||
local.ptr(), closeFile);
|
||||
#endif
|
||||
|
||||
if (!result)
|
||||
if (!result) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
#endif
|
||||
|
@ -25,12 +25,15 @@ public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (src.is_none()) {
|
||||
// Defer accepting None to other overloads (if we aren't in convert mode):
|
||||
if (!convert) return false;
|
||||
if (!convert) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isinstance<function>(src))
|
||||
if (!isinstance<function>(src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto func = reinterpret_borrow<function>(src);
|
||||
|
||||
@ -104,12 +107,14 @@ public:
|
||||
|
||||
template <typename Func>
|
||||
static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
|
||||
if (!f_)
|
||||
if (!f_) {
|
||||
return none().inc_ref();
|
||||
}
|
||||
|
||||
auto result = f_.template target<function_type>();
|
||||
if (result)
|
||||
if (result) {
|
||||
return cpp_function(*result, policy).release();
|
||||
}
|
||||
return cpp_function(std::forward<Func>(f_), policy).release();
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,9 @@ public:
|
||||
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
|
||||
#endif
|
||||
PyThreadState_Clear(tstate);
|
||||
if (active)
|
||||
if (active) {
|
||||
PyThreadState_DeleteCurrent();
|
||||
}
|
||||
PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate);
|
||||
release = false;
|
||||
}
|
||||
@ -117,8 +118,9 @@ public:
|
||||
|
||||
PYBIND11_NOINLINE ~gil_scoped_acquire() {
|
||||
dec_ref();
|
||||
if (release)
|
||||
PyEval_SaveThread();
|
||||
if (release) {
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
}
|
||||
private:
|
||||
PyThreadState *tstate = nullptr;
|
||||
@ -150,11 +152,13 @@ public:
|
||||
}
|
||||
|
||||
~gil_scoped_release() {
|
||||
if (!tstate)
|
||||
if (!tstate) {
|
||||
return;
|
||||
}
|
||||
// `PyEval_RestoreThread()` should not be called if runtime is finalizing
|
||||
if (active)
|
||||
if (active) {
|
||||
PyEval_RestoreThread(tstate);
|
||||
}
|
||||
if (disassoc) {
|
||||
auto key = detail::get_internals().tstate;
|
||||
PYBIND11_TLS_REPLACE_VALUE(key, tstate);
|
||||
|
@ -71,23 +71,26 @@ private:
|
||||
return static_cast<unsigned char>(c) <= 0xEF;
|
||||
};
|
||||
// If the last character is ASCII, there are no incomplete code points
|
||||
if (is_ascii(*rpptr))
|
||||
if (is_ascii(*rpptr)) {
|
||||
return 0;
|
||||
}
|
||||
// Otherwise, work back from the end of the buffer and find the first
|
||||
// UTF-8 leading byte
|
||||
const auto rpend = rbase - rpptr >= 3 ? rpptr + 3 : rbase;
|
||||
const auto leading = std::find_if(rpptr, rpend, is_leading);
|
||||
if (leading == rbase)
|
||||
if (leading == rbase) {
|
||||
return 0;
|
||||
}
|
||||
const auto dist = static_cast<size_t>(leading - rpptr);
|
||||
size_t remainder = 0;
|
||||
|
||||
if (dist == 0)
|
||||
if (dist == 0) {
|
||||
remainder = 1; // 1-byte code point is impossible
|
||||
else if (dist == 1)
|
||||
} else if (dist == 1) {
|
||||
remainder = is_leading_2b(*leading) ? 0 : dist + 1;
|
||||
else if (dist == 2)
|
||||
} else if (dist == 2) {
|
||||
remainder = is_leading_3b(*leading) ? 0 : dist + 1;
|
||||
}
|
||||
// else if (dist >= 3), at least 4 bytes before encountering an UTF-8
|
||||
// leading byte, either no remainder or invalid UTF-8.
|
||||
// Invalid UTF-8 will cause an exception later when converting
|
||||
@ -110,8 +113,9 @@ private:
|
||||
}
|
||||
|
||||
// Copy the remainder at the end of the buffer to the beginning:
|
||||
if (remainder > 0)
|
||||
if (remainder > 0) {
|
||||
std::memmove(pbase(), pptr() - remainder, remainder);
|
||||
}
|
||||
setp(pbase(), epptr());
|
||||
pbump(static_cast<int>(remainder));
|
||||
}
|
||||
@ -223,10 +227,12 @@ public:
|
||||
: do_stdout_(do_stdout), do_stderr_(do_stderr) {}
|
||||
|
||||
void enter() {
|
||||
if (do_stdout_)
|
||||
if (do_stdout_) {
|
||||
redirect_stdout.reset(new scoped_ostream_redirect());
|
||||
if (do_stderr_)
|
||||
}
|
||||
if (do_stderr_) {
|
||||
redirect_stderr.reset(new scoped_estream_redirect());
|
||||
}
|
||||
}
|
||||
|
||||
void exit() {
|
||||
|
@ -87,10 +87,12 @@ struct numpy_internals {
|
||||
|
||||
numpy_type_info *get_type_info(const std::type_info& tinfo, bool throw_if_missing = true) {
|
||||
auto it = registered_dtypes.find(std::type_index(tinfo));
|
||||
if (it != registered_dtypes.end())
|
||||
if (it != registered_dtypes.end()) {
|
||||
return &(it->second);
|
||||
if (throw_if_missing)
|
||||
}
|
||||
if (throw_if_missing) {
|
||||
pybind11_fail(std::string("NumPy type info missing for ") + tinfo.name());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -105,8 +107,9 @@ PYBIND11_NOINLINE void load_numpy_internals(numpy_internals* &ptr) {
|
||||
|
||||
inline numpy_internals& get_numpy_internals() {
|
||||
static numpy_internals* ptr = nullptr;
|
||||
if (!ptr)
|
||||
if (!ptr) {
|
||||
load_numpy_internals(ptr);
|
||||
}
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
@ -235,8 +238,9 @@ private:
|
||||
npy_api api;
|
||||
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
|
||||
DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
|
||||
if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7)
|
||||
if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) {
|
||||
pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0");
|
||||
}
|
||||
DECL_NPY_API(PyArray_Type);
|
||||
DECL_NPY_API(PyVoidArrType_Type);
|
||||
DECL_NPY_API(PyArrayDescr_Type);
|
||||
@ -491,8 +495,9 @@ public:
|
||||
/// This is essentially the same as calling numpy.dtype(args) in Python.
|
||||
static dtype from_args(object args) {
|
||||
PyObject *ptr = nullptr;
|
||||
if ((detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) == 0) || !ptr)
|
||||
if ((detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) == 0) || !ptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<dtype>(ptr);
|
||||
}
|
||||
|
||||
@ -536,8 +541,9 @@ private:
|
||||
dtype strip_padding(ssize_t itemsize) {
|
||||
// Recursively strip all void fields with empty names that are generated for
|
||||
// padding fields (as of NumPy v1.11).
|
||||
if (!has_fields())
|
||||
if (!has_fields()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
struct field_descr { PYBIND11_STR_TYPE name; object format; pybind11::int_ offset; };
|
||||
std::vector<field_descr> field_descriptors;
|
||||
@ -547,8 +553,9 @@ private:
|
||||
auto name = spec[0].cast<pybind11::str>();
|
||||
auto format = spec[1].cast<tuple>()[0].cast<dtype>();
|
||||
auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>();
|
||||
if ((len(name) == 0u) && format.kind() == 'V')
|
||||
if ((len(name) == 0u) && format.kind() == 'V') {
|
||||
continue;
|
||||
}
|
||||
field_descriptors.push_back({(PYBIND11_STR_TYPE) name, format.strip_padding(format.itemsize()), offset});
|
||||
}
|
||||
|
||||
@ -586,22 +593,25 @@ public:
|
||||
array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides,
|
||||
const void *ptr = nullptr, handle base = handle()) {
|
||||
|
||||
if (strides->empty())
|
||||
if (strides->empty()) {
|
||||
*strides = detail::c_strides(*shape, dt.itemsize());
|
||||
}
|
||||
|
||||
auto ndim = shape->size();
|
||||
if (ndim != strides->size())
|
||||
if (ndim != strides->size()) {
|
||||
pybind11_fail("NumPy: shape ndim doesn't match strides ndim");
|
||||
}
|
||||
auto descr = dt;
|
||||
|
||||
int flags = 0;
|
||||
if (base && ptr) {
|
||||
if (isinstance<array>(base))
|
||||
if (isinstance<array>(base)) {
|
||||
/* Copy flags from base (except ownership bit) */
|
||||
flags = reinterpret_borrow<array>(base).flags() & ~detail::npy_api::NPY_ARRAY_OWNDATA_;
|
||||
else
|
||||
} else {
|
||||
/* Writable by default, easy to downgrade later on if needed */
|
||||
flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||
}
|
||||
}
|
||||
|
||||
auto &api = detail::npy_api::get();
|
||||
@ -611,8 +621,9 @@ public:
|
||||
reinterpret_cast<Py_intptr_t*>(shape->data()),
|
||||
reinterpret_cast<Py_intptr_t*>(strides->data()),
|
||||
const_cast<void *>(ptr), flags, nullptr));
|
||||
if (!tmp)
|
||||
if (!tmp) {
|
||||
throw error_already_set();
|
||||
}
|
||||
if (ptr) {
|
||||
if (base) {
|
||||
api.PyArray_SetBaseObject_(tmp.ptr(), base.inc_ref().ptr());
|
||||
@ -681,8 +692,9 @@ public:
|
||||
|
||||
/// Dimension along a given axis
|
||||
ssize_t shape(ssize_t dim) const {
|
||||
if (dim >= ndim())
|
||||
if (dim >= ndim()) {
|
||||
fail_dim_check(dim, "invalid axis");
|
||||
}
|
||||
return shape()[dim];
|
||||
}
|
||||
|
||||
@ -693,8 +705,9 @@ public:
|
||||
|
||||
/// Stride along a given axis
|
||||
ssize_t strides(ssize_t dim) const {
|
||||
if (dim >= ndim())
|
||||
if (dim >= ndim()) {
|
||||
fail_dim_check(dim, "invalid axis");
|
||||
}
|
||||
return strides()[dim];
|
||||
}
|
||||
|
||||
@ -730,8 +743,9 @@ public:
|
||||
/// Byte offset from beginning of the array to a given index (full or partial).
|
||||
/// May throw if the index would lead to out of bounds access.
|
||||
template<typename... Ix> ssize_t offset_at(Ix... index) const {
|
||||
if ((ssize_t) sizeof...(index) > ndim())
|
||||
if ((ssize_t) sizeof...(index) > ndim()) {
|
||||
fail_dim_check(sizeof...(index), "too many indices for an array");
|
||||
}
|
||||
return byte_offset(ssize_t(index)...);
|
||||
}
|
||||
|
||||
@ -750,9 +764,11 @@ public:
|
||||
* and the caller must take care not to access invalid dimensions or dimension indices.
|
||||
*/
|
||||
template <typename T, ssize_t Dims = -1> detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims)
|
||||
throw std::domain_error("array has incorrect number of dimensions: " + std::to_string(ndim()) +
|
||||
"; expected " + std::to_string(Dims));
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) {
|
||||
throw std::domain_error("array has incorrect number of dimensions: "
|
||||
+ std::to_string(ndim()) + "; expected "
|
||||
+ std::to_string(Dims));
|
||||
}
|
||||
return detail::unchecked_mutable_reference<T, Dims>(mutable_data(), shape(), strides(), ndim());
|
||||
}
|
||||
|
||||
@ -764,9 +780,11 @@ public:
|
||||
* invalid dimensions or dimension indices.
|
||||
*/
|
||||
template <typename T, ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const & {
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims)
|
||||
throw std::domain_error("array has incorrect number of dimensions: " + std::to_string(ndim()) +
|
||||
"; expected " + std::to_string(Dims));
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) {
|
||||
throw std::domain_error("array has incorrect number of dimensions: "
|
||||
+ std::to_string(ndim()) + "; expected "
|
||||
+ std::to_string(Dims));
|
||||
}
|
||||
return detail::unchecked_reference<T, Dims>(data(), shape(), strides(), ndim());
|
||||
}
|
||||
|
||||
@ -789,7 +807,9 @@ public:
|
||||
auto new_array = reinterpret_steal<object>(
|
||||
detail::npy_api::get().PyArray_Resize_(m_ptr, &d, int(refcheck), -1)
|
||||
);
|
||||
if (!new_array) throw error_already_set();
|
||||
if (!new_array) {
|
||||
throw error_already_set();
|
||||
}
|
||||
if (isinstance<array>(new_array)) { *this = std::move(new_array); }
|
||||
}
|
||||
|
||||
@ -824,8 +844,9 @@ public:
|
||||
/// In case of an error, nullptr is returned and the Python error is cleared.
|
||||
static array ensure(handle h, int ExtraFlags = 0) {
|
||||
auto result = reinterpret_steal<array>(raw_array(h.ptr(), ExtraFlags));
|
||||
if (!result)
|
||||
if (!result) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -843,8 +864,9 @@ protected:
|
||||
}
|
||||
|
||||
void check_writeable() const {
|
||||
if (!writeable())
|
||||
if (!writeable()) {
|
||||
throw std::domain_error("array is not writeable");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Ix> void check_dimensions(Ix... index) const {
|
||||
@ -890,13 +912,19 @@ public:
|
||||
|
||||
PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
|
||||
array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen_t{}) {
|
||||
if (!m_ptr) PyErr_Clear();
|
||||
if (!is_borrowed) Py_XDECREF(h.ptr());
|
||||
if (!m_ptr) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
if (!is_borrowed) {
|
||||
Py_XDECREF(h.ptr());
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
|
||||
if (!m_ptr) throw error_already_set();
|
||||
if (!m_ptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
explicit array_t(const buffer_info& info, handle base = handle()) : array(info, base) { }
|
||||
@ -933,15 +961,17 @@ public:
|
||||
|
||||
// Reference to element at a given index
|
||||
template<typename... Ix> const T& at(Ix... index) const {
|
||||
if ((ssize_t) sizeof...(index) != ndim())
|
||||
if ((ssize_t) sizeof...(index) != ndim()) {
|
||||
fail_dim_check(sizeof...(index), "index dimension mismatch");
|
||||
}
|
||||
return *(static_cast<const T*>(array::data()) + byte_offset(ssize_t(index)...) / itemsize());
|
||||
}
|
||||
|
||||
// Mutable reference to element at a given index
|
||||
template<typename... Ix> T& mutable_at(Ix... index) {
|
||||
if ((ssize_t) sizeof...(index) != ndim())
|
||||
if ((ssize_t) sizeof...(index) != ndim()) {
|
||||
fail_dim_check(sizeof...(index), "index dimension mismatch");
|
||||
}
|
||||
return *(static_cast<T*>(array::mutable_data()) + byte_offset(ssize_t(index)...) / itemsize());
|
||||
}
|
||||
|
||||
@ -970,8 +1000,9 @@ public:
|
||||
/// it). In case of an error, nullptr is returned and the Python error is cleared.
|
||||
static array_t ensure(handle h) {
|
||||
auto result = reinterpret_steal<array_t>(raw_array_t(h.ptr()));
|
||||
if (!result)
|
||||
if (!result) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1032,8 +1063,9 @@ struct pyobject_caster<array_t<T, ExtraFlags>> {
|
||||
using type = array_t<T, ExtraFlags>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!convert && !type::check_(src))
|
||||
if (!convert && !type::check_(src)) {
|
||||
return false;
|
||||
}
|
||||
value = type::ensure(src);
|
||||
return static_cast<bool>(value);
|
||||
}
|
||||
@ -1098,8 +1130,9 @@ public:
|
||||
static constexpr int value = values[detail::is_fmt_numeric<T>::index];
|
||||
|
||||
static pybind11::dtype dtype() {
|
||||
if (auto ptr = npy_api::get().PyArray_DescrFromType_(value))
|
||||
if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) {
|
||||
return reinterpret_steal<pybind11::dtype>(ptr);
|
||||
}
|
||||
pybind11_fail("Unsupported buffer format!");
|
||||
}
|
||||
};
|
||||
@ -1147,8 +1180,9 @@ PYBIND11_NOINLINE void register_structured_dtype(
|
||||
bool (*direct_converter)(PyObject *, void *&)) {
|
||||
|
||||
auto& numpy_internals = get_numpy_internals();
|
||||
if (numpy_internals.get_type_info(tinfo, false))
|
||||
if (numpy_internals.get_type_info(tinfo, false)) {
|
||||
pybind11_fail("NumPy: dtype is already registered");
|
||||
}
|
||||
|
||||
// Use ordered fields because order matters as of NumPy 1.14:
|
||||
// https://docs.scipy.org/doc/numpy/release.html#multiple-field-indexing-assignment-of-structured-arrays
|
||||
@ -1158,9 +1192,10 @@ PYBIND11_NOINLINE void register_structured_dtype(
|
||||
|
||||
list names, formats, offsets;
|
||||
for (auto& field : ordered_fields) {
|
||||
if (!field.descr)
|
||||
pybind11_fail(std::string("NumPy: unsupported field dtype: `") +
|
||||
field.name + "` @ " + tinfo.name());
|
||||
if (!field.descr) {
|
||||
pybind11_fail(std::string("NumPy: unsupported field dtype: `") + field.name + "` @ "
|
||||
+ tinfo.name());
|
||||
}
|
||||
names.append(PYBIND11_STR_TYPE(field.name));
|
||||
formats.append(field.descr);
|
||||
offsets.append(pybind11::int_(field.offset));
|
||||
@ -1186,21 +1221,24 @@ PYBIND11_NOINLINE void register_structured_dtype(
|
||||
// isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049
|
||||
oss << "^T{";
|
||||
for (auto& field : ordered_fields) {
|
||||
if (field.offset > offset)
|
||||
if (field.offset > offset) {
|
||||
oss << (field.offset - offset) << 'x';
|
||||
}
|
||||
oss << field.format << ':' << field.name << ':';
|
||||
offset = field.offset + field.size;
|
||||
}
|
||||
if (itemsize > offset)
|
||||
if (itemsize > offset) {
|
||||
oss << (itemsize - offset) << 'x';
|
||||
}
|
||||
oss << '}';
|
||||
auto format_str = oss.str();
|
||||
|
||||
// Sanity check: verify that NumPy properly parses our buffer format string
|
||||
auto& api = npy_api::get();
|
||||
auto arr = array(buffer_info(nullptr, itemsize, format_str, 1));
|
||||
if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr()))
|
||||
if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr())) {
|
||||
pybind11_fail("NumPy: invalid buffer descriptor!");
|
||||
}
|
||||
|
||||
auto tindex = std::type_index(tinfo);
|
||||
numpy_internals.registered_dtypes[tindex] = { dtype_ptr, format_str };
|
||||
@ -1234,8 +1272,9 @@ private:
|
||||
|
||||
static bool direct_converter(PyObject *obj, void*& value) {
|
||||
auto& api = npy_api::get();
|
||||
if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_))
|
||||
if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) {
|
||||
return false;
|
||||
}
|
||||
if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
|
||||
if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
|
||||
value = ((PyVoidScalarObject_Proxy *) obj)->obval;
|
||||
@ -1363,12 +1402,14 @@ public:
|
||||
m_common_iterator() {
|
||||
|
||||
// Manual copy to avoid conversion warning if using std::copy
|
||||
for (size_t i = 0; i < shape.size(); ++i)
|
||||
for (size_t i = 0; i < shape.size(); ++i) {
|
||||
m_shape[i] = shape[i];
|
||||
}
|
||||
|
||||
container_type strides(shape.size());
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
init_common_iterator(buffers[i], shape, m_common_iterator[i], strides);
|
||||
}
|
||||
}
|
||||
|
||||
multi_array_iterator& operator++() {
|
||||
@ -1401,10 +1442,11 @@ private:
|
||||
auto strides_iter = strides.rbegin();
|
||||
|
||||
while (buffer_shape_iter != buffer.shape.rend()) {
|
||||
if (*shape_iter == *buffer_shape_iter)
|
||||
if (*shape_iter == *buffer_shape_iter) {
|
||||
*strides_iter = *buffer_strides_iter;
|
||||
else
|
||||
} else {
|
||||
*strides_iter = 0;
|
||||
}
|
||||
|
||||
++buffer_shape_iter;
|
||||
++buffer_strides_iter;
|
||||
@ -1417,8 +1459,9 @@ private:
|
||||
}
|
||||
|
||||
void increment_common_iterator(size_t dim) {
|
||||
for (auto &iter : m_common_iterator)
|
||||
for (auto &iter : m_common_iterator) {
|
||||
iter.increment(dim);
|
||||
}
|
||||
}
|
||||
|
||||
container_type m_shape;
|
||||
@ -1451,26 +1494,30 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &
|
||||
auto &dim_size_out = *res_iter;
|
||||
|
||||
// Each input dimension can either be 1 or `n`, but `n` values must match across buffers
|
||||
if (dim_size_out == 1)
|
||||
if (dim_size_out == 1) {
|
||||
dim_size_out = dim_size_in;
|
||||
else if (dim_size_in != 1 && dim_size_in != dim_size_out)
|
||||
} else if (dim_size_in != 1 && dim_size_in != dim_size_out) {
|
||||
pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool trivial_broadcast_c = true;
|
||||
bool trivial_broadcast_f = true;
|
||||
for (size_t i = 0; i < N && (trivial_broadcast_c || trivial_broadcast_f); ++i) {
|
||||
if (buffers[i].size == 1)
|
||||
if (buffers[i].size == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Require the same number of dimensions:
|
||||
if (buffers[i].ndim != ndim)
|
||||
if (buffers[i].ndim != ndim) {
|
||||
return broadcast_trivial::non_trivial;
|
||||
}
|
||||
|
||||
// Require all dimensions be full-size:
|
||||
if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin()))
|
||||
if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin())) {
|
||||
return broadcast_trivial::non_trivial;
|
||||
}
|
||||
|
||||
// Check for C contiguity (but only if previous inputs were also C contiguous)
|
||||
if (trivial_broadcast_c) {
|
||||
@ -1478,10 +1525,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &
|
||||
auto end = buffers[i].shape.crend();
|
||||
for (auto shape_iter = buffers[i].shape.crbegin(), stride_iter = buffers[i].strides.crbegin();
|
||||
trivial_broadcast_c && shape_iter != end; ++shape_iter, ++stride_iter) {
|
||||
if (expect_stride == *stride_iter)
|
||||
if (expect_stride == *stride_iter) {
|
||||
expect_stride *= *shape_iter;
|
||||
else
|
||||
} else {
|
||||
trivial_broadcast_c = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1491,10 +1539,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &
|
||||
auto end = buffers[i].shape.cend();
|
||||
for (auto shape_iter = buffers[i].shape.cbegin(), stride_iter = buffers[i].strides.cbegin();
|
||||
trivial_broadcast_f && shape_iter != end; ++shape_iter, ++stride_iter) {
|
||||
if (expect_stride == *stride_iter)
|
||||
if (expect_stride == *stride_iter) {
|
||||
expect_stride *= *shape_iter;
|
||||
else
|
||||
} else {
|
||||
trivial_broadcast_f = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1527,8 +1576,9 @@ struct vectorize_returned_array {
|
||||
using Type = array_t<Return>;
|
||||
|
||||
static Type create(broadcast_trivial trivial, const std::vector<ssize_t> &shape) {
|
||||
if (trivial == broadcast_trivial::f_trivial)
|
||||
if (trivial == broadcast_trivial::f_trivial) {
|
||||
return array_t<Return, array::f_style>(shape);
|
||||
}
|
||||
return array_t<Return>(shape);
|
||||
}
|
||||
|
||||
@ -1644,14 +1694,17 @@ private:
|
||||
|
||||
auto result = returned_array::create(trivial, shape);
|
||||
|
||||
if (size == 0) return std::move(result);
|
||||
if (size == 0) {
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
auto mutable_data = returned_array::mutable_data(result);
|
||||
if (trivial == broadcast_trivial::non_trivial)
|
||||
if (trivial == broadcast_trivial::non_trivial) {
|
||||
apply_broadcast(buffers, params, mutable_data, size, shape, i_seq, vi_seq, bi_seq);
|
||||
else
|
||||
} else {
|
||||
apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq);
|
||||
}
|
||||
|
||||
return std::move(result);
|
||||
}
|
||||
@ -1675,7 +1728,9 @@ private:
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
returned_array::call(out, i, f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...);
|
||||
for (auto &x : vecparams) x.first += x.second;
|
||||
for (auto &x : vecparams) {
|
||||
x.first += x.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,8 +212,9 @@ protected:
|
||||
cast_in args_converter;
|
||||
|
||||
/* Try to cast the function arguments into the C++ domain */
|
||||
if (!args_converter.load_args(call))
|
||||
if (!args_converter.load_args(call)) {
|
||||
return PYBIND11_TRY_NEXT_OVERLOAD;
|
||||
}
|
||||
|
||||
/* Invoke call policy pre-call hook */
|
||||
process_attributes<Extra...>::precall(call);
|
||||
@ -286,8 +287,9 @@ protected:
|
||||
class strdup_guard {
|
||||
public:
|
||||
~strdup_guard() {
|
||||
for (auto s : strings)
|
||||
for (auto s : strings) {
|
||||
std::free(s);
|
||||
}
|
||||
}
|
||||
char *operator()(const char *s) {
|
||||
auto t = PYBIND11_COMPAT_STRDUP(s);
|
||||
@ -318,14 +320,18 @@ protected:
|
||||
|
||||
/* Create copies of all referenced C-style strings */
|
||||
rec->name = guarded_strdup(rec->name ? rec->name : "");
|
||||
if (rec->doc) rec->doc = guarded_strdup(rec->doc);
|
||||
if (rec->doc) {
|
||||
rec->doc = guarded_strdup(rec->doc);
|
||||
}
|
||||
for (auto &a: rec->args) {
|
||||
if (a.name)
|
||||
if (a.name) {
|
||||
a.name = guarded_strdup(a.name);
|
||||
if (a.descr)
|
||||
}
|
||||
if (a.descr) {
|
||||
a.descr = guarded_strdup(a.descr);
|
||||
else if (a.value)
|
||||
} else if (a.value) {
|
||||
a.descr = guarded_strdup(repr(a.value).cast<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
rec->is_constructor = (std::strcmp(rec->name, "__init__") == 0)
|
||||
@ -355,12 +361,14 @@ protected:
|
||||
if (c == '{') {
|
||||
// Write arg name for everything except *args and **kwargs.
|
||||
is_starred = *(pc + 1) == '*';
|
||||
if (is_starred)
|
||||
if (is_starred) {
|
||||
continue;
|
||||
}
|
||||
// Separator for keyword-only arguments, placed before the kw
|
||||
// arguments start (unless we are already putting an *args)
|
||||
if (!rec->has_args && arg_index == rec->nargs_pos)
|
||||
if (!rec->has_args && arg_index == rec->nargs_pos) {
|
||||
signature += "*, ";
|
||||
}
|
||||
if (arg_index < rec->args.size() && rec->args[arg_index].name) {
|
||||
signature += rec->args[arg_index].name;
|
||||
} else if (arg_index == 0 && rec->is_method) {
|
||||
@ -377,14 +385,17 @@ protected:
|
||||
}
|
||||
// Separator for positional-only arguments (placed after the
|
||||
// argument, rather than before like *
|
||||
if (rec->nargs_pos_only > 0 && (arg_index + 1) == rec->nargs_pos_only)
|
||||
if (rec->nargs_pos_only > 0 && (arg_index + 1) == rec->nargs_pos_only) {
|
||||
signature += ", /";
|
||||
if (!is_starred)
|
||||
}
|
||||
if (!is_starred) {
|
||||
arg_index++;
|
||||
}
|
||||
} else if (c == '%') {
|
||||
const std::type_info *t = types[type_index++];
|
||||
if (!t)
|
||||
if (!t) {
|
||||
pybind11_fail("Internal error while parsing type signature (1)");
|
||||
}
|
||||
if (auto tinfo = detail::get_type_info(*t)) {
|
||||
handle th((PyObject *) tinfo->type);
|
||||
signature +=
|
||||
@ -406,8 +417,9 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_index != args - rec->has_args - rec->has_kwargs || types[type_index] != nullptr)
|
||||
if (arg_index != args - rec->has_args - rec->has_kwargs || types[type_index] != nullptr) {
|
||||
pybind11_fail("Internal error while parsing type signature (2)");
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (std::strcmp(rec->name, "__next__") == 0) {
|
||||
@ -422,8 +434,9 @@ protected:
|
||||
rec->args.shrink_to_fit();
|
||||
rec->nargs = (std::uint16_t) args;
|
||||
|
||||
if (rec->sibling && PYBIND11_INSTANCE_METHOD_CHECK(rec->sibling.ptr()))
|
||||
if (rec->sibling && PYBIND11_INSTANCE_METHOD_CHECK(rec->sibling.ptr())) {
|
||||
rec->sibling = PYBIND11_INSTANCE_METHOD_GET_FUNCTION(rec->sibling.ptr());
|
||||
}
|
||||
|
||||
detail::function_record *chain = nullptr, *chain_start = rec;
|
||||
if (rec->sibling) {
|
||||
@ -433,13 +446,16 @@ protected:
|
||||
chain = (detail::function_record *) rec_capsule;
|
||||
/* Never append a method to an overload chain of a parent class;
|
||||
instead, hide the parent's overloads in this case */
|
||||
if (!chain->scope.is(rec->scope))
|
||||
if (!chain->scope.is(rec->scope)) {
|
||||
chain = nullptr;
|
||||
}
|
||||
}
|
||||
// Don't trigger for things like the default __init__, which are wrapper_descriptors
|
||||
// that we are intentionally replacing
|
||||
else if (!rec->sibling.is_none() && rec->name[0] != '_') {
|
||||
pybind11_fail("Cannot overload existing non-function object \""
|
||||
+ std::string(rec->name) + "\" with a function of the same name");
|
||||
}
|
||||
// Don't trigger for things like the default __init__, which are wrapper_descriptors that we are intentionally replacing
|
||||
else if (!rec->sibling.is_none() && rec->name[0] != '_')
|
||||
pybind11_fail("Cannot overload existing non-function object \"" + std::string(rec->name) +
|
||||
"\" with a function of the same name");
|
||||
}
|
||||
|
||||
if (!chain) {
|
||||
@ -466,21 +482,26 @@ protected:
|
||||
}
|
||||
|
||||
m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr());
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("cpp_function::cpp_function(): Could not allocate function object");
|
||||
}
|
||||
} else {
|
||||
/* Append at the beginning or end of the overload chain */
|
||||
m_ptr = rec->sibling.ptr();
|
||||
inc_ref();
|
||||
if (chain->is_method != rec->is_method)
|
||||
pybind11_fail("overloading a method with both static and instance methods is not supported; "
|
||||
#if defined(NDEBUG)
|
||||
"compile in debug mode for more details"
|
||||
if (chain->is_method != rec->is_method) {
|
||||
pybind11_fail(
|
||||
"overloading a method with both static and instance methods is not supported; "
|
||||
#if defined(NDEBUG)
|
||||
"compile in debug mode for more details"
|
||||
#else
|
||||
"error while attempting to bind " + std::string(rec->is_method ? "instance" : "static") + " method " +
|
||||
std::string(pybind11::str(rec->scope.attr("__name__"))) + "." + std::string(rec->name) + signature
|
||||
"error while attempting to bind "
|
||||
+ std::string(rec->is_method ? "instance" : "static") + " method "
|
||||
+ std::string(pybind11::str(rec->scope.attr("__name__"))) + "."
|
||||
+ std::string(rec->name) + signature
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
if (rec->prepend) {
|
||||
// Beginning of chain; we need to replace the capsule's current head-of-the-chain
|
||||
@ -494,8 +515,9 @@ protected:
|
||||
} else {
|
||||
// Or end of chain (normal behavior)
|
||||
chain_start = chain;
|
||||
while (chain->next)
|
||||
while (chain->next) {
|
||||
chain = chain->next;
|
||||
}
|
||||
chain->next = unique_rec.release();
|
||||
guarded_strdup.release();
|
||||
}
|
||||
@ -515,9 +537,12 @@ protected:
|
||||
bool first_user_def = true;
|
||||
for (auto it = chain_start; it != nullptr; it = it->next) {
|
||||
if (options::show_function_signatures()) {
|
||||
if (index > 0) signatures += "\n";
|
||||
if (chain)
|
||||
if (index > 0) {
|
||||
signatures += "\n";
|
||||
}
|
||||
if (chain) {
|
||||
signatures += std::to_string(++index) + ". ";
|
||||
}
|
||||
signatures += rec->name;
|
||||
signatures += it->signature;
|
||||
signatures += "\n";
|
||||
@ -526,12 +551,19 @@ protected:
|
||||
// If we're appending another docstring, and aren't printing function signatures, we
|
||||
// need to append a newline first:
|
||||
if (!options::show_function_signatures()) {
|
||||
if (first_user_def) first_user_def = false;
|
||||
else signatures += "\n";
|
||||
if (first_user_def) {
|
||||
first_user_def = false;
|
||||
} else {
|
||||
signatures += "\n";
|
||||
}
|
||||
}
|
||||
if (options::show_function_signatures()) {
|
||||
signatures += "\n";
|
||||
}
|
||||
if (options::show_function_signatures()) signatures += "\n";
|
||||
signatures += it->doc;
|
||||
if (options::show_function_signatures()) signatures += "\n";
|
||||
if (options::show_function_signatures()) {
|
||||
signatures += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -544,8 +576,10 @@ protected:
|
||||
|
||||
if (rec->is_method) {
|
||||
m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr());
|
||||
if (!m_ptr)
|
||||
pybind11_fail("cpp_function::cpp_function(): Could not allocate instance method object");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail(
|
||||
"cpp_function::cpp_function(): Could not allocate instance method object");
|
||||
}
|
||||
Py_DECREF(func);
|
||||
}
|
||||
}
|
||||
@ -560,8 +594,9 @@ protected:
|
||||
|
||||
while (rec) {
|
||||
detail::function_record *next = rec->next;
|
||||
if (rec->free_data)
|
||||
if (rec->free_data) {
|
||||
rec->free_data(rec);
|
||||
}
|
||||
// During initialization, these strings might not have been copied yet,
|
||||
// so they cannot be freed. Once the function has been created, they can.
|
||||
// Check `make_function_record` for more details.
|
||||
@ -574,17 +609,19 @@ protected:
|
||||
std::free(const_cast<char *>(arg.descr));
|
||||
}
|
||||
}
|
||||
for (auto &arg: rec->args)
|
||||
for (auto &arg : rec->args) {
|
||||
arg.value.dec_ref();
|
||||
}
|
||||
if (rec->def) {
|
||||
std::free(const_cast<char *>(rec->def->ml_doc));
|
||||
// Python 3.9.0 decref's these in the wrong order; rec->def
|
||||
// If loaded on 3.9.0, let these leak (use Python 3.9.1 at runtime to fix)
|
||||
// See https://github.com/python/cpython/pull/22670
|
||||
#if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
|
||||
if (!is_zero)
|
||||
delete rec->def;
|
||||
#else
|
||||
if (!is_zero) {
|
||||
delete rec->def;
|
||||
}
|
||||
#else
|
||||
delete rec->def;
|
||||
#endif
|
||||
}
|
||||
@ -621,8 +658,9 @@ protected:
|
||||
|
||||
// If this value is already registered it must mean __init__ is invoked multiple times;
|
||||
// we really can't support that in C++, so just ignore the second __init__.
|
||||
if (self_value_and_holder.instance_registered())
|
||||
if (self_value_and_holder.instance_registered()) {
|
||||
return none().release().ptr();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@ -658,15 +696,22 @@ protected:
|
||||
|
||||
const function_record &func = *it;
|
||||
size_t num_args = func.nargs; // Number of positional arguments that we need
|
||||
if (func.has_args) --num_args; // (but don't count py::args
|
||||
if (func.has_kwargs) --num_args; // or py::kwargs)
|
||||
if (func.has_args) {
|
||||
--num_args; // (but don't count py::args
|
||||
}
|
||||
if (func.has_kwargs) {
|
||||
--num_args; // or py::kwargs)
|
||||
}
|
||||
size_t pos_args = func.nargs_pos;
|
||||
|
||||
if (!func.has_args && n_args_in > pos_args)
|
||||
if (!func.has_args && n_args_in > pos_args) {
|
||||
continue; // Too many positional arguments for this overload
|
||||
}
|
||||
|
||||
if (n_args_in < pos_args && func.args.size() < pos_args)
|
||||
continue; // Not enough positional arguments given, and not enough defaults to fill in the blanks
|
||||
if (n_args_in < pos_args && func.args.size() < pos_args) {
|
||||
continue; // Not enough positional arguments given, and not enough defaults to
|
||||
// fill in the blanks
|
||||
}
|
||||
|
||||
function_call call(func, parent);
|
||||
|
||||
@ -677,8 +722,9 @@ protected:
|
||||
if (func.is_new_style_constructor) {
|
||||
// The `value` may have been preallocated by an old-style `__init__`
|
||||
// if it was a preceding candidate for overload resolution.
|
||||
if (self_value_and_holder)
|
||||
if (self_value_and_holder) {
|
||||
self_value_and_holder.type->dealloc(self_value_and_holder);
|
||||
}
|
||||
|
||||
call.init_self = PyTuple_GET_ITEM(args_in, 0);
|
||||
call.args.emplace_back(reinterpret_cast<PyObject *>(&self_value_and_holder));
|
||||
@ -703,8 +749,9 @@ protected:
|
||||
call.args.push_back(arg);
|
||||
call.args_convert.push_back(arg_rec ? arg_rec->convert : true);
|
||||
}
|
||||
if (bad_arg)
|
||||
if (bad_arg) {
|
||||
continue; // Maybe it was meant for another overload (issue #688)
|
||||
}
|
||||
|
||||
// Keep track of how many position args we copied out in case we need to come back
|
||||
// to copy the rest into a py::args argument.
|
||||
@ -725,12 +772,14 @@ protected:
|
||||
if (value) {
|
||||
call.args.push_back(value);
|
||||
call.args_convert.push_back(arg_rec.convert);
|
||||
} else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (args_copied < func.nargs_pos_only)
|
||||
if (args_copied < func.nargs_pos_only) {
|
||||
continue; // Not enough defaults to fill the positional arguments
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Check kwargs and, failing that, defaults that may help complete the list
|
||||
@ -741,8 +790,9 @@ protected:
|
||||
const auto &arg_rec = func.args[args_copied];
|
||||
|
||||
handle value;
|
||||
if (kwargs_in && arg_rec.name)
|
||||
if (kwargs_in && arg_rec.name) {
|
||||
value = dict_getitemstring(kwargs.ptr(), arg_rec.name);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
// Consume a kwargs value
|
||||
@ -763,23 +813,27 @@ protected:
|
||||
|
||||
if (value) {
|
||||
// If we're at the py::args index then first insert a stub for it to be replaced later
|
||||
if (func.has_args && call.args.size() == func.nargs_pos)
|
||||
if (func.has_args && call.args.size() == func.nargs_pos) {
|
||||
call.args.push_back(none());
|
||||
}
|
||||
|
||||
call.args.push_back(value);
|
||||
call.args_convert.push_back(arg_rec.convert);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (args_copied < num_args)
|
||||
continue; // Not enough arguments, defaults, or kwargs to fill the positional arguments
|
||||
if (args_copied < num_args) {
|
||||
continue; // Not enough arguments, defaults, or kwargs to fill the
|
||||
// positional arguments
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Check everything was consumed (unless we have a kwargs arg)
|
||||
if (kwargs && !kwargs.empty() && !func.has_kwargs)
|
||||
if (kwargs && !kwargs.empty() && !func.has_kwargs) {
|
||||
continue; // Unconsumed kwargs, but no py::kwargs argument to accept them
|
||||
}
|
||||
|
||||
// 4a. If we have a py::args argument, create a new tuple with leftovers
|
||||
if (func.has_args) {
|
||||
@ -797,18 +851,20 @@ protected:
|
||||
extra_args[i] = PyTuple_GET_ITEM(args_in, positional_args_copied + i);
|
||||
}
|
||||
}
|
||||
if (call.args.size() <= func.nargs_pos)
|
||||
if (call.args.size() <= func.nargs_pos) {
|
||||
call.args.push_back(extra_args);
|
||||
else
|
||||
} else {
|
||||
call.args[func.nargs_pos] = extra_args;
|
||||
}
|
||||
call.args_convert.push_back(false);
|
||||
call.args_ref = std::move(extra_args);
|
||||
}
|
||||
|
||||
// 4b. If we have a py::kwargs, pass on any remaining kwargs
|
||||
if (func.has_kwargs) {
|
||||
if (!kwargs.ptr())
|
||||
if (!kwargs.ptr()) {
|
||||
kwargs = dict(); // If we didn't get one, send an empty one
|
||||
}
|
||||
call.args.push_back(kwargs);
|
||||
call.args_convert.push_back(false);
|
||||
call.kwargs_ref = std::move(kwargs);
|
||||
@ -838,8 +894,9 @@ protected:
|
||||
result = PYBIND11_TRY_NEXT_OVERLOAD;
|
||||
}
|
||||
|
||||
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD)
|
||||
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (overloaded) {
|
||||
// The (overloaded) call failed; if the call has at least one argument that
|
||||
@ -870,8 +927,9 @@ protected:
|
||||
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD) {
|
||||
// The error reporting logic below expects 'it' to be valid, as it would be
|
||||
// if we'd encountered this failure in the first-pass loop.
|
||||
if (!result)
|
||||
if (!result) {
|
||||
it = &call.func;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -923,8 +981,9 @@ protected:
|
||||
};
|
||||
|
||||
if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) {
|
||||
if (overloads->is_operator)
|
||||
if (overloads->is_operator) {
|
||||
return handle(Py_NotImplemented).inc_ref().ptr();
|
||||
}
|
||||
|
||||
std::string msg = std::string(overloads->name) + "(): incompatible " +
|
||||
std::string(overloads->is_constructor ? "constructor" : "function") +
|
||||
@ -944,7 +1003,9 @@ protected:
|
||||
size_t end = sig.find(", "), next = end + 2;
|
||||
size_t ret = sig.rfind(" -> ");
|
||||
// Or the ), if there is no comma:
|
||||
if (end >= sig.size()) next = end = sig.find(')');
|
||||
if (end >= sig.size()) {
|
||||
next = end = sig.find(')');
|
||||
}
|
||||
if (start < end && next < sig.size()) {
|
||||
msg.append(sig, start, end - start);
|
||||
msg += '(';
|
||||
@ -953,7 +1014,9 @@ protected:
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wrote_sig) msg += it2->signature;
|
||||
if (!wrote_sig) {
|
||||
msg += it2->signature;
|
||||
}
|
||||
|
||||
msg += "\n";
|
||||
}
|
||||
@ -961,8 +1024,11 @@ protected:
|
||||
auto args_ = reinterpret_borrow<tuple>(args_in);
|
||||
bool some_args = false;
|
||||
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
|
||||
if (!some_args) some_args = true;
|
||||
else msg += ", ";
|
||||
if (!some_args) {
|
||||
some_args = true;
|
||||
} else {
|
||||
msg += ", ";
|
||||
}
|
||||
try {
|
||||
msg += pybind11::repr(args_[ti]);
|
||||
} catch (const error_already_set&) {
|
||||
@ -972,12 +1038,17 @@ protected:
|
||||
if (kwargs_in) {
|
||||
auto kwargs = reinterpret_borrow<dict>(kwargs_in);
|
||||
if (!kwargs.empty()) {
|
||||
if (some_args) msg += "; ";
|
||||
if (some_args) {
|
||||
msg += "; ";
|
||||
}
|
||||
msg += "kwargs: ";
|
||||
bool first = true;
|
||||
for (auto kwarg : kwargs) {
|
||||
if (first) first = false;
|
||||
else msg += ", ";
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
msg += ", ";
|
||||
}
|
||||
msg += pybind11::str("{}=").format(kwarg.first);
|
||||
try {
|
||||
msg += pybind11::repr(kwarg.second);
|
||||
@ -1068,8 +1139,9 @@ public:
|
||||
std::string full_name = std::string(PyModule_GetName(m_ptr))
|
||||
+ std::string(".") + std::string(name);
|
||||
auto result = reinterpret_borrow<module_>(PyImport_AddModule(full_name.c_str()));
|
||||
if (doc && options::show_user_defined_docstrings())
|
||||
if (doc && options::show_user_defined_docstrings()) {
|
||||
result.attr("__doc__") = pybind11::str(doc);
|
||||
}
|
||||
attr(name) = result;
|
||||
return result;
|
||||
}
|
||||
@ -1077,16 +1149,18 @@ public:
|
||||
/// Import and return a module or throws `error_already_set`.
|
||||
static module_ import(const char *name) {
|
||||
PyObject *obj = PyImport_ImportModule(name);
|
||||
if (!obj)
|
||||
if (!obj) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<module_>(obj);
|
||||
}
|
||||
|
||||
/// Reload the module or throws `error_already_set`.
|
||||
void reload() {
|
||||
PyObject *obj = PyImport_ReloadModule(ptr());
|
||||
if (!obj)
|
||||
if (!obj) {
|
||||
throw error_already_set();
|
||||
}
|
||||
*this = reinterpret_steal<module_>(obj);
|
||||
}
|
||||
|
||||
@ -1098,9 +1172,11 @@ public:
|
||||
established will, in most cases, break things.
|
||||
\endrst */
|
||||
PYBIND11_NOINLINE void add_object(const char *name, handle obj, bool overwrite = false) {
|
||||
if (!overwrite && hasattr(*this, name))
|
||||
pybind11_fail("Error during initialization: multiple incompatible definitions with name \"" +
|
||||
std::string(name) + "\"");
|
||||
if (!overwrite && hasattr(*this, name)) {
|
||||
pybind11_fail(
|
||||
"Error during initialization: multiple incompatible definitions with name \""
|
||||
+ std::string(name) + "\"");
|
||||
}
|
||||
|
||||
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
|
||||
}
|
||||
@ -1138,8 +1214,9 @@ public:
|
||||
auto m = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
|
||||
#endif
|
||||
if (m == nullptr) {
|
||||
if (PyErr_Occurred())
|
||||
if (PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
pybind11_fail("Internal error in module_::create_extension_module()");
|
||||
}
|
||||
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when returned from PyInit_...
|
||||
@ -1177,14 +1254,17 @@ public:
|
||||
PYBIND11_OBJECT_DEFAULT(generic_type, object, PyType_Check)
|
||||
protected:
|
||||
void initialize(const type_record &rec) {
|
||||
if (rec.scope && hasattr(rec.scope, "__dict__") && rec.scope.attr("__dict__").contains(rec.name))
|
||||
pybind11_fail("generic_type: cannot initialize type \"" + std::string(rec.name) +
|
||||
"\": an object with that name is already defined");
|
||||
if (rec.scope && hasattr(rec.scope, "__dict__")
|
||||
&& rec.scope.attr("__dict__").contains(rec.name)) {
|
||||
pybind11_fail("generic_type: cannot initialize type \"" + std::string(rec.name)
|
||||
+ "\": an object with that name is already defined");
|
||||
}
|
||||
|
||||
if ((rec.module_local ? get_local_type_info(*rec.type) : get_global_type_info(*rec.type))
|
||||
!= nullptr)
|
||||
pybind11_fail("generic_type: type \"" + std::string(rec.name) +
|
||||
"\" is already registered!");
|
||||
!= nullptr) {
|
||||
pybind11_fail("generic_type: type \"" + std::string(rec.name)
|
||||
+ "\" is already registered!");
|
||||
}
|
||||
|
||||
m_ptr = make_new_python_type(rec);
|
||||
|
||||
@ -1206,10 +1286,11 @@ protected:
|
||||
auto &internals = get_internals();
|
||||
auto tindex = std::type_index(*rec.type);
|
||||
tinfo->direct_conversions = &internals.direct_conversions[tindex];
|
||||
if (rec.module_local)
|
||||
if (rec.module_local) {
|
||||
get_local_internals().registered_types_cpp[tindex] = tinfo;
|
||||
else
|
||||
} else {
|
||||
internals.registered_types_cpp[tindex] = tinfo;
|
||||
}
|
||||
internals.registered_types_py[(PyTypeObject *) m_ptr] = { tinfo };
|
||||
|
||||
if (rec.bases.size() > 1 || rec.multiple_inheritance) {
|
||||
@ -1237,8 +1318,9 @@ protected:
|
||||
auto t = reinterpret_borrow<tuple>(value->tp_bases);
|
||||
for (handle h : t) {
|
||||
auto tinfo2 = get_type_info((PyTypeObject *) h.ptr());
|
||||
if (tinfo2)
|
||||
if (tinfo2) {
|
||||
tinfo2->simple_type = false;
|
||||
}
|
||||
mark_parents_nonsimple((PyTypeObject *) h.ptr());
|
||||
}
|
||||
}
|
||||
@ -1249,12 +1331,12 @@ protected:
|
||||
auto *type = (PyHeapTypeObject*) m_ptr;
|
||||
auto tinfo = detail::get_type_info(&type->ht_type);
|
||||
|
||||
if (!type->ht_type.tp_as_buffer)
|
||||
pybind11_fail(
|
||||
"To be able to register buffer protocol support for the type '" +
|
||||
get_fully_qualified_tp_name(tinfo->type) +
|
||||
"' the associated class<>(..) invocation must "
|
||||
"include the pybind11::buffer_protocol() annotation!");
|
||||
if (!type->ht_type.tp_as_buffer) {
|
||||
pybind11_fail("To be able to register buffer protocol support for the type '"
|
||||
+ get_fully_qualified_tp_name(tinfo->type)
|
||||
+ "' the associated class<>(..) invocation must "
|
||||
"include the pybind11::buffer_protocol() annotation!");
|
||||
}
|
||||
|
||||
tinfo->get_buffer = get_buffer;
|
||||
tinfo->get_buffer_data = get_buffer_data;
|
||||
@ -1475,8 +1557,9 @@ public:
|
||||
auto *ptr = new capture { std::forward<Func>(func) };
|
||||
install_buffer_funcs([](PyObject *obj, void *ptr) -> buffer_info* {
|
||||
detail::make_caster<type> caster;
|
||||
if (!caster.load(obj, false))
|
||||
if (!caster.load(obj, false)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new buffer_info(((capture *) ptr)->func(caster));
|
||||
}, ptr);
|
||||
weakref(m_ptr, cpp_function([ptr](handle wr) {
|
||||
@ -1598,7 +1681,9 @@ public:
|
||||
std::free(doc_prev);
|
||||
rec_fset->doc = PYBIND11_COMPAT_STRDUP(rec_fset->doc);
|
||||
}
|
||||
if (! rec_active) rec_active = rec_fset;
|
||||
if (!rec_active) {
|
||||
rec_active = rec_fset;
|
||||
}
|
||||
}
|
||||
def_property_static_impl(name, fget, fset, rec_active);
|
||||
return *this;
|
||||
@ -1716,8 +1801,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
inline str enum_name(handle arg) {
|
||||
dict entries = arg.get_type().attr("__entries");
|
||||
for (auto kv : entries) {
|
||||
if (handle(kv.second[int_(0)]).equal(arg))
|
||||
if (handle(kv.second[int_(0)]).equal(arg)) {
|
||||
return pybind11::str(kv.first);
|
||||
}
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
@ -1752,15 +1838,17 @@ struct enum_base {
|
||||
[](handle arg) -> std::string {
|
||||
std::string docstring;
|
||||
dict entries = arg.attr("__entries");
|
||||
if (((PyTypeObject *) arg.ptr())->tp_doc)
|
||||
if (((PyTypeObject *) arg.ptr())->tp_doc) {
|
||||
docstring += std::string(((PyTypeObject *) arg.ptr())->tp_doc) + "\n\n";
|
||||
}
|
||||
docstring += "Members:";
|
||||
for (auto kv : entries) {
|
||||
auto key = std::string(pybind11::str(kv.first));
|
||||
auto comment = kv.second[int_(1)];
|
||||
docstring += "\n\n " + key;
|
||||
if (!comment.is_none())
|
||||
if (!comment.is_none()) {
|
||||
docstring += " : " + (std::string) pybind11::str(comment);
|
||||
}
|
||||
}
|
||||
return docstring;
|
||||
}, name("__doc__")
|
||||
@ -1769,8 +1857,9 @@ struct enum_base {
|
||||
m_base.attr("__members__") = static_property(cpp_function(
|
||||
[](handle arg) -> dict {
|
||||
dict entries = arg.attr("__entries"), m;
|
||||
for (auto kv : entries)
|
||||
for (auto kv : entries) {
|
||||
m[kv.first] = kv.second[int_(0)];
|
||||
}
|
||||
return m;
|
||||
}, name("__members__")), none(), none(), ""
|
||||
);
|
||||
@ -1865,8 +1954,9 @@ struct enum_base {
|
||||
|
||||
PYBIND11_NOINLINE void export_values() {
|
||||
dict entries = m_base.attr("__entries");
|
||||
for (auto kv : entries)
|
||||
for (auto kv : entries) {
|
||||
m_parent.attr(kv.first) = kv.second[int_(0)];
|
||||
}
|
||||
}
|
||||
|
||||
handle m_base;
|
||||
@ -1944,11 +2034,13 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
|
||||
PYBIND11_NOINLINE void keep_alive_impl(handle nurse, handle patient) {
|
||||
if (!nurse || !patient)
|
||||
if (!nurse || !patient) {
|
||||
pybind11_fail("Could not activate keep_alive!");
|
||||
}
|
||||
|
||||
if (patient.is_none() || nurse.is_none())
|
||||
if (patient.is_none() || nurse.is_none()) {
|
||||
return; /* Nothing to keep alive or nothing to be kept alive by */
|
||||
}
|
||||
|
||||
auto tinfo = all_type_info(Py_TYPE(nurse.ptr()));
|
||||
if (!tinfo.empty()) {
|
||||
@ -1972,12 +2064,15 @@ PYBIND11_NOINLINE void keep_alive_impl(handle nurse, handle patient) {
|
||||
|
||||
PYBIND11_NOINLINE void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret) {
|
||||
auto get_arg = [&](size_t n) {
|
||||
if (n == 0)
|
||||
if (n == 0) {
|
||||
return ret;
|
||||
if (n == 1 && call.init_self)
|
||||
}
|
||||
if (n == 1 && call.init_self) {
|
||||
return call.init_self;
|
||||
if (n <= call.args.size())
|
||||
}
|
||||
if (n <= call.args.size()) {
|
||||
return call.args[n - 1];
|
||||
}
|
||||
return handle();
|
||||
};
|
||||
|
||||
@ -2000,10 +2095,11 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
|
||||
// TODO consolidate the erasure code in pybind11_meta_dealloc() in class.h
|
||||
auto &cache = get_internals().inactive_override_cache;
|
||||
for (auto it = cache.begin(), last = cache.end(); it != last; ) {
|
||||
if (it->first == reinterpret_cast<PyObject *>(type))
|
||||
if (it->first == reinterpret_cast<PyObject *>(type)) {
|
||||
it = cache.erase(it);
|
||||
else
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
wr.dec_ref();
|
||||
@ -2089,19 +2185,24 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&... extra) {
|
||||
|
||||
if (!detail::get_type_info(typeid(state), false)) {
|
||||
class_<state>(handle(), "iterator", pybind11::module_local())
|
||||
.def("__iter__", [](state &s) -> state& { return s; })
|
||||
.def("__next__", [](state &s) -> ValueType {
|
||||
if (!s.first_or_done)
|
||||
++s.it;
|
||||
else
|
||||
s.first_or_done = false;
|
||||
if (s.it == s.end) {
|
||||
s.first_or_done = true;
|
||||
throw stop_iteration();
|
||||
}
|
||||
return Access()(s.it);
|
||||
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
|
||||
}, std::forward<Extra>(extra)..., Policy);
|
||||
.def("__iter__", [](state &s) -> state & { return s; })
|
||||
.def(
|
||||
"__next__",
|
||||
[](state &s) -> ValueType {
|
||||
if (!s.first_or_done) {
|
||||
++s.it;
|
||||
} else {
|
||||
s.first_or_done = false;
|
||||
}
|
||||
if (s.it == s.end) {
|
||||
s.first_or_done = true;
|
||||
throw stop_iteration();
|
||||
}
|
||||
return Access()(s.it);
|
||||
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
|
||||
},
|
||||
std::forward<Extra>(extra)...,
|
||||
Policy);
|
||||
}
|
||||
|
||||
return cast(state{first, last, true});
|
||||
@ -2187,23 +2288,27 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
|
||||
};
|
||||
auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * {
|
||||
static bool currently_used = false;
|
||||
if (currently_used) // implicit conversions are non-reentrant
|
||||
if (currently_used) { // implicit conversions are non-reentrant
|
||||
return nullptr;
|
||||
}
|
||||
set_flag flag_helper(currently_used);
|
||||
if (!detail::make_caster<InputType>().load(obj, false))
|
||||
if (!detail::make_caster<InputType>().load(obj, false)) {
|
||||
return nullptr;
|
||||
}
|
||||
tuple args(1);
|
||||
args[0] = obj;
|
||||
PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr);
|
||||
if (result == nullptr)
|
||||
if (result == nullptr) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
if (auto tinfo = detail::get_type_info(typeid(OutputType)))
|
||||
if (auto tinfo = detail::get_type_info(typeid(OutputType))) {
|
||||
tinfo->implicit_conversions.push_back(implicit_caster);
|
||||
else
|
||||
} else {
|
||||
pybind11_fail("implicitly_convertible: Unable to find type " + type_id<OutputType>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2239,9 +2344,11 @@ public:
|
||||
std::string full_name = scope.attr("__name__").cast<std::string>() +
|
||||
std::string(".") + name;
|
||||
m_ptr = PyErr_NewException(const_cast<char *>(full_name.c_str()), base.ptr(), NULL);
|
||||
if (hasattr(scope, "__dict__") && scope.attr("__dict__").contains(name))
|
||||
if (hasattr(scope, "__dict__") && scope.attr("__dict__").contains(name)) {
|
||||
pybind11_fail("Error during initialization: multiple incompatible "
|
||||
"definitions with name \"" + std::string(name) + "\"");
|
||||
"definitions with name \""
|
||||
+ std::string(name) + "\"");
|
||||
}
|
||||
scope.attr(name) = *this;
|
||||
}
|
||||
|
||||
@ -2265,13 +2372,17 @@ exception<CppException> ®ister_exception_impl(handle scope,
|
||||
handle base,
|
||||
bool isLocal) {
|
||||
auto &ex = detail::get_exception_object<CppException>();
|
||||
if (!ex) ex = exception<CppException>(scope, name, base);
|
||||
if (!ex) {
|
||||
ex = exception<CppException>(scope, name, base);
|
||||
}
|
||||
|
||||
auto register_func = isLocal ? ®ister_local_exception_translator
|
||||
: ®ister_exception_translator;
|
||||
|
||||
register_func([](std::exception_ptr p) {
|
||||
if (!p) return;
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
std::rethrow_exception(p);
|
||||
} catch (const CppException &e) {
|
||||
@ -2339,8 +2450,9 @@ PYBIND11_NOINLINE void print(const tuple &args, const dict &kwargs) {
|
||||
write(line);
|
||||
write(kwargs.contains("end") ? kwargs["end"] : cast("\n"));
|
||||
|
||||
if (kwargs.contains("flush") && kwargs["flush"].cast<bool>())
|
||||
if (kwargs.contains("flush") && kwargs["flush"].cast<bool>()) {
|
||||
file.attr("flush")();
|
||||
}
|
||||
}
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
@ -2363,16 +2475,18 @@ error_already_set::~error_already_set() {
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
inline function get_type_override(const void *this_ptr, const type_info *this_type, const char *name) {
|
||||
handle self = get_object_handle(this_ptr, this_type);
|
||||
if (!self)
|
||||
if (!self) {
|
||||
return function();
|
||||
}
|
||||
handle type = type::handle_of(self);
|
||||
auto key = std::make_pair(type.ptr(), name);
|
||||
|
||||
/* Cache functions that aren't overridden in Python to avoid
|
||||
many costly Python dictionary lookups below */
|
||||
auto &cache = get_internals().inactive_override_cache;
|
||||
if (cache.find(key) != cache.end())
|
||||
if (cache.find(key) != cache.end()) {
|
||||
return function();
|
||||
}
|
||||
|
||||
function override = getattr(self, name, function());
|
||||
if (override.is_cpp_function()) {
|
||||
|
@ -242,7 +242,11 @@ class object : public handle {
|
||||
public:
|
||||
object() = default;
|
||||
PYBIND11_DEPRECATED("Use reinterpret_borrow<object>() or reinterpret_steal<object>()")
|
||||
object(handle h, bool is_borrowed) : handle(h) { if (is_borrowed) inc_ref(); }
|
||||
object(handle h, bool is_borrowed) : handle(h) {
|
||||
if (is_borrowed) {
|
||||
inc_ref();
|
||||
}
|
||||
}
|
||||
/// Copy constructor; always increases the reference count
|
||||
object(const object &o) : handle(o) { inc_ref(); }
|
||||
/// Move constructor; steals the object from ``other`` and preserves its reference count
|
||||
@ -458,8 +462,9 @@ template <> inline bool isinstance<object>(handle obj) { return obj.ptr() != nul
|
||||
/// Return true if ``obj`` is an instance of the ``type``.
|
||||
inline bool isinstance(handle obj, handle type) {
|
||||
const auto result = PyObject_IsInstance(obj.ptr(), type.ptr());
|
||||
if (result == -1)
|
||||
if (result == -1) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
@ -529,12 +534,13 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
inline handle get_function(handle value) {
|
||||
if (value) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
if (PyInstanceMethod_Check(value.ptr()))
|
||||
if (PyInstanceMethod_Check(value.ptr())) {
|
||||
value = PyInstanceMethod_GET_FUNCTION(value.ptr());
|
||||
else
|
||||
} else
|
||||
#endif
|
||||
if (PyMethod_Check(value.ptr()))
|
||||
if (PyMethod_Check(value.ptr())) {
|
||||
value = PyMethod_GET_FUNCTION(value.ptr());
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -1076,14 +1082,18 @@ public:
|
||||
template <typename SzType, detail::enable_if_t<std::is_integral<SzType>::value, int> = 0>
|
||||
str(const char *c, const SzType &n)
|
||||
: object(PyUnicode_FromStringAndSize(c, ssize_t_cast(n)), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate string object!");
|
||||
}
|
||||
}
|
||||
|
||||
// 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
str(const char *c = "")
|
||||
: object(PyUnicode_FromString(c), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate string object!");
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
@ -1109,20 +1119,26 @@ public:
|
||||
Return a string representation of the object. This is analogous to
|
||||
the ``str()`` function in Python.
|
||||
\endrst */
|
||||
explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); }
|
||||
explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) {
|
||||
if (!m_ptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator std::string() const {
|
||||
object temp = *this;
|
||||
if (PyUnicode_Check(m_ptr)) {
|
||||
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(m_ptr));
|
||||
if (!temp)
|
||||
if (!temp) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length))
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract string contents! (invalid type)");
|
||||
}
|
||||
return std::string(buffer, (size_t) length);
|
||||
}
|
||||
|
||||
@ -1162,13 +1178,17 @@ public:
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
bytes(const char *c = "")
|
||||
: object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate bytes object!");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SzType, detail::enable_if_t<std::is_integral<SzType>::value, int> = 0>
|
||||
bytes(const char *c, const SzType &n)
|
||||
: object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, ssize_t_cast(n)), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate bytes object!");
|
||||
}
|
||||
}
|
||||
|
||||
// Allow implicit conversion:
|
||||
@ -1181,8 +1201,9 @@ public:
|
||||
operator std::string() const {
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length))
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
}
|
||||
return std::string(buffer, (size_t) length);
|
||||
}
|
||||
|
||||
@ -1199,8 +1220,9 @@ public:
|
||||
operator std::string_view() const {
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length))
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
}
|
||||
return {buffer, static_cast<size_t>(length)};
|
||||
}
|
||||
#endif
|
||||
@ -1214,27 +1236,32 @@ inline bytes::bytes(const pybind11::str &s) {
|
||||
object temp = s;
|
||||
if (PyUnicode_Check(s.ptr())) {
|
||||
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(s.ptr()));
|
||||
if (!temp)
|
||||
if (!temp) {
|
||||
pybind11_fail("Unable to extract string contents! (encoding issue)");
|
||||
}
|
||||
}
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length))
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract string contents! (invalid type)");
|
||||
}
|
||||
auto obj = reinterpret_steal<object>(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length));
|
||||
if (!obj)
|
||||
if (!obj) {
|
||||
pybind11_fail("Could not allocate bytes object!");
|
||||
}
|
||||
m_ptr = obj.release().ptr();
|
||||
}
|
||||
|
||||
inline str::str(const bytes& b) {
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length))
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
}
|
||||
auto obj = reinterpret_steal<object>(PyUnicode_FromStringAndSize(buffer, length));
|
||||
if (!obj)
|
||||
if (!obj) {
|
||||
pybind11_fail("Could not allocate string object!");
|
||||
}
|
||||
m_ptr = obj.release().ptr();
|
||||
}
|
||||
|
||||
@ -1247,7 +1274,9 @@ public:
|
||||
template <typename SzType, detail::enable_if_t<std::is_integral<SzType>::value, int> = 0>
|
||||
bytearray(const char *c, const SzType &n)
|
||||
: object(PyByteArray_FromStringAndSize(c, ssize_t_cast(n)), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate bytearray object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate bytearray object!");
|
||||
}
|
||||
}
|
||||
|
||||
bytearray()
|
||||
@ -1295,7 +1324,9 @@ private:
|
||||
/// Return the truth value of an object -- always returns a new reference
|
||||
static PyObject *raw_bool(PyObject *op) {
|
||||
const auto value = PyObject_IsTrue(op);
|
||||
if (value == -1) return nullptr;
|
||||
if (value == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
return handle(value != 0 ? Py_True : Py_False).inc_ref().ptr();
|
||||
}
|
||||
};
|
||||
@ -1330,17 +1361,21 @@ public:
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
int_(T value) {
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(T) <= sizeof(long))) {
|
||||
if (std::is_signed<T>::value)
|
||||
if (std::is_signed<T>::value) {
|
||||
m_ptr = PyLong_FromLong((long) value);
|
||||
else
|
||||
} else {
|
||||
m_ptr = PyLong_FromUnsignedLong((unsigned long) value);
|
||||
}
|
||||
} else {
|
||||
if (std::is_signed<T>::value)
|
||||
if (std::is_signed<T>::value) {
|
||||
m_ptr = PyLong_FromLongLong((long long) value);
|
||||
else
|
||||
} else {
|
||||
m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);
|
||||
}
|
||||
}
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate int object!");
|
||||
}
|
||||
if (!m_ptr) pybind11_fail("Could not allocate int object!");
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
@ -1361,11 +1396,15 @@ public:
|
||||
// Allow implicit conversion from float/double:
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate float object!");
|
||||
}
|
||||
}
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate float object!");
|
||||
}
|
||||
}
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator float() const { return (float) PyFloat_AsDouble(m_ptr); }
|
||||
@ -1378,7 +1417,9 @@ public:
|
||||
PYBIND11_OBJECT_CVT_DEFAULT(weakref, object, PyWeakref_Check, raw_weakref)
|
||||
explicit weakref(handle obj, handle callback = {})
|
||||
: object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate weak reference!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate weak reference!");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1392,8 +1433,9 @@ public:
|
||||
PYBIND11_OBJECT_DEFAULT(slice, object, PySlice_Check)
|
||||
slice(handle start, handle stop, handle step) {
|
||||
m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr());
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate slice object!");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PYBIND11_HAS_OPTIONAL
|
||||
@ -1434,15 +1476,17 @@ public:
|
||||
|
||||
explicit capsule(const void *value, const char *name = nullptr, void (*destructor)(PyObject *) = nullptr)
|
||||
: object(PyCapsule_New(const_cast<void *>(value), name, destructor), stolen_t{}) {
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
}
|
||||
}
|
||||
|
||||
PYBIND11_DEPRECATED("Please pass a destructor that takes a void pointer as input")
|
||||
capsule(const void *value, void (*destruct)(PyObject *))
|
||||
: object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen_t{}) {
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
}
|
||||
}
|
||||
|
||||
capsule(const void *value, void (*destructor)(void *)) {
|
||||
@ -1452,11 +1496,13 @@ public:
|
||||
destructor(ptr);
|
||||
});
|
||||
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
}
|
||||
|
||||
if (PyCapsule_SetContext(m_ptr, (void *) destructor) != 0)
|
||||
if (PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
|
||||
pybind11_fail("Could not set capsule context!");
|
||||
}
|
||||
}
|
||||
|
||||
explicit capsule(void (*destructor)()) {
|
||||
@ -1465,8 +1511,9 @@ public:
|
||||
destructor();
|
||||
});
|
||||
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
@ -1504,7 +1551,9 @@ public:
|
||||
detail::enable_if_t<std::is_integral<SzType>::value, int> = 0>
|
||||
// Some compilers generate link errors when using `const SzType &` here:
|
||||
explicit tuple(SzType size = 0) : object(PyTuple_New(ssize_t_cast(size)), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate tuple object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate tuple object!");
|
||||
}
|
||||
}
|
||||
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
|
||||
bool empty() const { return size() == 0; }
|
||||
@ -1527,7 +1576,9 @@ class dict : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict)
|
||||
dict() : object(PyDict_New(), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate dict object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate dict object!");
|
||||
}
|
||||
}
|
||||
template <typename... Args,
|
||||
typename = detail::enable_if_t<args_are_all_keyword_or_ds<Args...>()>,
|
||||
@ -1547,8 +1598,9 @@ public:
|
||||
private:
|
||||
/// Call the `dict` Python type -- always returns a new reference
|
||||
static PyObject *raw_dict(PyObject *op) {
|
||||
if (PyDict_Check(op))
|
||||
if (PyDict_Check(op)) {
|
||||
return handle(op).inc_ref().ptr();
|
||||
}
|
||||
return PyObject_CallFunctionObjArgs((PyObject *) &PyDict_Type, op, nullptr);
|
||||
}
|
||||
};
|
||||
@ -1558,8 +1610,9 @@ public:
|
||||
PYBIND11_OBJECT_DEFAULT(sequence, object, PySequence_Check)
|
||||
size_t size() const {
|
||||
ssize_t result = PySequence_Size(m_ptr);
|
||||
if (result == -1)
|
||||
if (result == -1) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return (size_t) result;
|
||||
}
|
||||
bool empty() const { return size() == 0; }
|
||||
@ -1576,7 +1629,9 @@ public:
|
||||
detail::enable_if_t<std::is_integral<SzType>::value, int> = 0>
|
||||
// Some compilers generate link errors when using `const SzType &` here:
|
||||
explicit list(SzType size = 0) : object(PyList_New(ssize_t_cast(size)), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate list object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate list object!");
|
||||
}
|
||||
}
|
||||
size_t size() const { return (size_t) PyList_Size(m_ptr); }
|
||||
bool empty() const { return size() == 0; }
|
||||
@ -1603,7 +1658,9 @@ class set : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(set, object, PySet_Check, PySet_New)
|
||||
set() : object(PySet_New(nullptr), stolen_t{}) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate set object!");
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate set object!");
|
||||
}
|
||||
}
|
||||
size_t size() const { return (size_t) PySet_Size(m_ptr); }
|
||||
bool empty() const { return size() == 0; }
|
||||
@ -1621,8 +1678,9 @@ public:
|
||||
PYBIND11_OBJECT_DEFAULT(function, object, PyCallable_Check)
|
||||
handle cpp_function() const {
|
||||
handle fun = detail::get_function(m_ptr);
|
||||
if (fun && PyCFunction_Check(fun.ptr()))
|
||||
if (fun && PyCFunction_Check(fun.ptr())) {
|
||||
return fun;
|
||||
}
|
||||
return handle();
|
||||
}
|
||||
bool is_cpp_function() const { return (bool) cpp_function(); }
|
||||
@ -1639,7 +1697,9 @@ public:
|
||||
|
||||
buffer_info request(bool writable = false) const {
|
||||
int flags = PyBUF_STRIDES | PyBUF_FORMAT;
|
||||
if (writable) flags |= PyBUF_WRITABLE;
|
||||
if (writable) {
|
||||
flags |= PyBUF_WRITABLE;
|
||||
}
|
||||
auto *view = new Py_buffer();
|
||||
if (PyObject_GetBuffer(m_ptr, view, flags) != 0) {
|
||||
delete view;
|
||||
@ -1663,14 +1723,16 @@ public:
|
||||
use ``memoryview(const object& obj)`` instead of this constructor.
|
||||
\endrst */
|
||||
explicit memoryview(const buffer_info& info) {
|
||||
if (!info.view())
|
||||
if (!info.view()) {
|
||||
pybind11_fail("Prohibited to create memoryview without Py_buffer");
|
||||
}
|
||||
// Note: PyMemoryView_FromBuffer never increments obj reference.
|
||||
m_ptr = (info.view()->obj) ?
|
||||
PyMemoryView_FromObject(info.view()->obj) :
|
||||
PyMemoryView_FromBuffer(info.view());
|
||||
if (!m_ptr)
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Unable to create memoryview from buffer descriptor");
|
||||
}
|
||||
}
|
||||
|
||||
/** \rst
|
||||
@ -1744,8 +1806,9 @@ public:
|
||||
PyObject* ptr = PyMemoryView_FromMemory(
|
||||
reinterpret_cast<char*>(mem), size,
|
||||
(readonly) ? PyBUF_READ : PyBUF_WRITE);
|
||||
if (!ptr)
|
||||
if (!ptr) {
|
||||
pybind11_fail("Could not allocate memoryview object!");
|
||||
}
|
||||
return memoryview(object(ptr, stolen_t{}));
|
||||
}
|
||||
|
||||
@ -1768,11 +1831,13 @@ inline memoryview memoryview::from_buffer(
|
||||
detail::any_container<ssize_t> shape,
|
||||
detail::any_container<ssize_t> strides, bool readonly) {
|
||||
size_t ndim = shape->size();
|
||||
if (ndim != strides->size())
|
||||
if (ndim != strides->size()) {
|
||||
pybind11_fail("memoryview: shape length doesn't match strides length");
|
||||
}
|
||||
ssize_t size = ndim != 0u ? 1 : 0;
|
||||
for (size_t i = 0; i < ndim; ++i)
|
||||
for (size_t i = 0; i < ndim; ++i) {
|
||||
size *= (*shape)[i];
|
||||
}
|
||||
Py_buffer view;
|
||||
view.buf = ptr;
|
||||
view.obj = nullptr;
|
||||
@ -1786,8 +1851,9 @@ inline memoryview memoryview::from_buffer(
|
||||
view.suboffsets = nullptr;
|
||||
view.internal = nullptr;
|
||||
PyObject* obj = PyMemoryView_FromBuffer(&view);
|
||||
if (!obj)
|
||||
if (!obj) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return memoryview(object(obj, stolen_t{}));
|
||||
}
|
||||
/// @endcond
|
||||
@ -1799,8 +1865,9 @@ inline memoryview memoryview::from_buffer(
|
||||
/// Get the length of a Python object.
|
||||
inline size_t len(handle h) {
|
||||
ssize_t result = PyObject_Length(h.ptr());
|
||||
if (result < 0)
|
||||
if (result < 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return (size_t) result;
|
||||
}
|
||||
|
||||
@ -1823,7 +1890,9 @@ inline size_t len_hint(handle h) {
|
||||
|
||||
inline str repr(handle h) {
|
||||
PyObject *str_value = PyObject_Repr(h.ptr());
|
||||
if (!str_value) throw error_already_set();
|
||||
if (!str_value) {
|
||||
throw error_already_set();
|
||||
}
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
|
||||
Py_XDECREF(str_value); str_value = unicode;
|
||||
@ -1873,8 +1942,9 @@ handle object_api<D>::get_type() const { return type::handle_of(derived()); }
|
||||
template <typename D>
|
||||
bool object_api<D>::rich_compare(object_api const &other, int value) const {
|
||||
int rv = PyObject_RichCompareBool(derived().ptr(), other.derived().ptr(), value);
|
||||
if (rv == -1)
|
||||
if (rv == -1) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return rv == 1;
|
||||
}
|
||||
|
||||
|
@ -52,14 +52,16 @@ template <typename Type, typename Key> struct set_caster {
|
||||
using key_conv = make_caster<Key>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<pybind11::set>(src))
|
||||
if (!isinstance<pybind11::set>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto s = reinterpret_borrow<pybind11::set>(src);
|
||||
value.clear();
|
||||
for (auto entry : s) {
|
||||
key_conv conv;
|
||||
if (!conv.load(entry, convert))
|
||||
if (!conv.load(entry, convert)) {
|
||||
return false;
|
||||
}
|
||||
value.insert(cast_op<Key &&>(std::move(conv)));
|
||||
}
|
||||
return true;
|
||||
@ -67,13 +69,15 @@ template <typename Type, typename Key> struct set_caster {
|
||||
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!std::is_lvalue_reference<T>::value)
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Key>::policy(policy);
|
||||
}
|
||||
pybind11::set s;
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_ || !s.add(value_))
|
||||
if (!value_ || !s.add(value_)) {
|
||||
return handle();
|
||||
}
|
||||
}
|
||||
return s.release();
|
||||
}
|
||||
@ -86,16 +90,17 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<dict>(src))
|
||||
if (!isinstance<dict>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto d = reinterpret_borrow<dict>(src);
|
||||
value.clear();
|
||||
for (auto it : d) {
|
||||
key_conv kconv;
|
||||
value_conv vconv;
|
||||
if (!kconv.load(it.first.ptr(), convert) ||
|
||||
!vconv.load(it.second.ptr(), convert))
|
||||
if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
|
||||
return false;
|
||||
}
|
||||
value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
|
||||
}
|
||||
return true;
|
||||
@ -113,8 +118,9 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
for (auto &&kv : src) {
|
||||
auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent));
|
||||
auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
|
||||
if (!key || !value)
|
||||
if (!key || !value) {
|
||||
return handle();
|
||||
}
|
||||
d[key] = value;
|
||||
}
|
||||
return d.release();
|
||||
@ -127,15 +133,17 @@ template <typename Type, typename Value> struct list_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src))
|
||||
if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto s = reinterpret_borrow<sequence>(src);
|
||||
value.clear();
|
||||
reserve_maybe(s, &value);
|
||||
for (auto it : s) {
|
||||
value_conv conv;
|
||||
if (!conv.load(it, convert))
|
||||
if (!conv.load(it, convert)) {
|
||||
return false;
|
||||
}
|
||||
value.push_back(cast_op<Value &&>(std::move(conv)));
|
||||
}
|
||||
return true;
|
||||
@ -153,14 +161,16 @@ private:
|
||||
public:
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!std::is_lvalue_reference<T>::value)
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
list l(src.size());
|
||||
ssize_t index = 0;
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_)
|
||||
if (!value_) {
|
||||
return handle();
|
||||
}
|
||||
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||
}
|
||||
return l.release();
|
||||
@ -184,8 +194,9 @@ template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> s
|
||||
private:
|
||||
template <bool R = Resizable>
|
||||
bool require_size(enable_if_t<R, size_t> size) {
|
||||
if (value.size() != size)
|
||||
if (value.size() != size) {
|
||||
value.resize(size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <bool R = Resizable>
|
||||
@ -195,16 +206,19 @@ private:
|
||||
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<sequence>(src))
|
||||
if (!isinstance<sequence>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto l = reinterpret_borrow<sequence>(src);
|
||||
if (!require_size(l.size()))
|
||||
if (!require_size(l.size())) {
|
||||
return false;
|
||||
}
|
||||
size_t ctr = 0;
|
||||
for (auto it : l) {
|
||||
value_conv conv;
|
||||
if (!conv.load(it, convert))
|
||||
if (!conv.load(it, convert)) {
|
||||
return false;
|
||||
}
|
||||
value[ctr++] = cast_op<Value &&>(std::move(conv));
|
||||
}
|
||||
return true;
|
||||
@ -216,8 +230,9 @@ public:
|
||||
ssize_t index = 0;
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_)
|
||||
if (!value_) {
|
||||
return handle();
|
||||
}
|
||||
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||
}
|
||||
return l.release();
|
||||
@ -250,8 +265,9 @@ template<typename Type, typename Value = typename Type::value_type> struct optio
|
||||
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!src)
|
||||
if (!src) {
|
||||
return none().inc_ref();
|
||||
}
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
@ -266,8 +282,9 @@ template<typename Type, typename Value = typename Type::value_type> struct optio
|
||||
return true; // default-constructed value is already empty
|
||||
}
|
||||
value_conv inner_caster;
|
||||
if (!inner_caster.load(src, convert))
|
||||
if (!inner_caster.load(src, convert)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value.emplace(cast_op<Value &&>(std::move(inner_caster)));
|
||||
return true;
|
||||
@ -341,8 +358,9 @@ struct variant_caster<V<Ts...>> {
|
||||
// E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
|
||||
// slot of the variant. Without two-pass loading `double` would be filled
|
||||
// because it appears first and a conversion is possible.
|
||||
if (convert && load_alternative(src, false, type_list<Ts...>{}))
|
||||
if (convert && load_alternative(src, false, type_list<Ts...>{})) {
|
||||
return true;
|
||||
}
|
||||
return load_alternative(src, convert, type_list<Ts...>{});
|
||||
}
|
||||
|
||||
|
@ -87,10 +87,11 @@ void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_>
|
||||
|
||||
cl.def("remove", [](Vector &v, const T &x) {
|
||||
auto p = std::find(v.begin(), v.end(), x);
|
||||
if (p != v.end())
|
||||
if (p != v.end()) {
|
||||
v.erase(p);
|
||||
else
|
||||
} else {
|
||||
throw value_error();
|
||||
}
|
||||
},
|
||||
arg("x"),
|
||||
"Remove the first item from the list whose value is x. "
|
||||
@ -116,10 +117,12 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
using DiffType = typename Vector::difference_type;
|
||||
|
||||
auto wrap_i = [](DiffType i, SizeType n) {
|
||||
if (i < 0)
|
||||
if (i < 0) {
|
||||
i += n;
|
||||
if (i < 0 || (SizeType)i >= n)
|
||||
}
|
||||
if (i < 0 || (SizeType) i >= n) {
|
||||
throw index_error();
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
@ -131,8 +134,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
cl.def(init([](const iterable &it) {
|
||||
auto v = std::unique_ptr<Vector>(new Vector());
|
||||
v->reserve(len_hint(it));
|
||||
for (handle h : it)
|
||||
for (handle h : it) {
|
||||
v->push_back(h.cast<T>());
|
||||
}
|
||||
return v.release();
|
||||
}));
|
||||
|
||||
@ -177,26 +181,29 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
cl.def("insert",
|
||||
[](Vector &v, DiffType i, const T &x) {
|
||||
// Can't use wrap_i; i == v.size() is OK
|
||||
if (i < 0)
|
||||
if (i < 0) {
|
||||
i += v.size();
|
||||
if (i < 0 || (SizeType)i > v.size())
|
||||
}
|
||||
if (i < 0 || (SizeType) i > v.size()) {
|
||||
throw index_error();
|
||||
}
|
||||
v.insert(v.begin() + i, x);
|
||||
},
|
||||
arg("i") , arg("x"),
|
||||
"Insert an item at a given position."
|
||||
);
|
||||
|
||||
cl.def("pop",
|
||||
cl.def(
|
||||
"pop",
|
||||
[](Vector &v) {
|
||||
if (v.empty())
|
||||
if (v.empty()) {
|
||||
throw index_error();
|
||||
}
|
||||
T t = std::move(v.back());
|
||||
v.pop_back();
|
||||
return t;
|
||||
},
|
||||
"Remove and return the last item"
|
||||
);
|
||||
"Remove and return the last item");
|
||||
|
||||
cl.def("pop",
|
||||
[wrap_i](Vector &v, DiffType i) {
|
||||
@ -222,8 +229,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
[](const Vector &v, slice slice) -> Vector * {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
auto *seq = new Vector();
|
||||
seq->reserve((size_t) slicelength);
|
||||
@ -241,11 +249,14 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
"__setitem__",
|
||||
[](Vector &v, slice slice, const Vector &value) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
if (slicelength != value.size())
|
||||
throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
|
||||
if (slicelength != value.size()) {
|
||||
throw std::runtime_error(
|
||||
"Left and right hand size of slice assignment have different sizes!");
|
||||
}
|
||||
|
||||
for (size_t i=0; i<slicelength; ++i) {
|
||||
v[start] = value[i];
|
||||
@ -267,8 +278,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
[](Vector &v, slice slice) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
if (step == 1 && false) {
|
||||
v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
|
||||
@ -296,10 +308,12 @@ void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl)
|
||||
using ItType = typename Vector::iterator;
|
||||
|
||||
auto wrap_i = [](DiffType i, SizeType n) {
|
||||
if (i < 0)
|
||||
if (i < 0) {
|
||||
i += n;
|
||||
if (i < 0 || (SizeType)i >= n)
|
||||
}
|
||||
if (i < 0 || (SizeType) i >= n) {
|
||||
throw index_error();
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
@ -328,15 +342,15 @@ void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl)
|
||||
using SizeType = typename Vector::size_type;
|
||||
using DiffType = typename Vector::difference_type;
|
||||
using ItType = typename Vector::iterator;
|
||||
cl.def("__getitem__",
|
||||
[](const Vector &v, DiffType i) -> T {
|
||||
if (i < 0 && (i += v.size()) < 0)
|
||||
throw index_error();
|
||||
if ((SizeType)i >= v.size())
|
||||
throw index_error();
|
||||
return v[(SizeType)i];
|
||||
cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
|
||||
if (i < 0 && (i += v.size()) < 0) {
|
||||
throw index_error();
|
||||
}
|
||||
);
|
||||
if ((SizeType) i >= v.size()) {
|
||||
throw index_error();
|
||||
}
|
||||
return v[(SizeType) i];
|
||||
});
|
||||
|
||||
cl.def("__iter__",
|
||||
[](Vector &v) {
|
||||
@ -358,8 +372,9 @@ template <typename Vector, typename Class_> auto vector_if_insertion_operator(Cl
|
||||
s << name << '[';
|
||||
for (size_type i=0; i < v.size(); ++i) {
|
||||
s << v[i];
|
||||
if (i != v.size() - 1)
|
||||
if (i != v.size() - 1) {
|
||||
s << ", ";
|
||||
}
|
||||
}
|
||||
s << ']';
|
||||
return s.str();
|
||||
@ -402,10 +417,14 @@ void vector_buffer_impl(Class_& cl, std::true_type) {
|
||||
|
||||
cl.def(init([](const buffer &buf) {
|
||||
auto info = buf.request();
|
||||
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
|
||||
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) {
|
||||
throw type_error("Only valid 1D buffers can be copied to a vector");
|
||||
if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize)
|
||||
throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")");
|
||||
}
|
||||
if (!detail::compare_buffer_info<T>::compare(info)
|
||||
|| (ssize_t) sizeof(T) != info.itemsize) {
|
||||
throw type_error("Format mismatch (Python: " + info.format
|
||||
+ " C++: " + format_descriptor<T>::format() + ")");
|
||||
}
|
||||
|
||||
T *p = static_cast<T*>(info.ptr);
|
||||
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
|
||||
@ -415,8 +434,9 @@ void vector_buffer_impl(Class_& cl, std::true_type) {
|
||||
}
|
||||
Vector vec;
|
||||
vec.reserve((size_t) info.shape[0]);
|
||||
for (; p != end; p += step)
|
||||
for (; p != end; p += step) {
|
||||
vec.push_back(*p);
|
||||
}
|
||||
return vec;
|
||||
|
||||
}));
|
||||
@ -545,8 +565,11 @@ void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::v
|
||||
cl.def("__setitem__",
|
||||
[](Map &m, const KeyType &k, const MappedType &v) {
|
||||
auto it = m.find(k);
|
||||
if (it != m.end()) it->second = v;
|
||||
else m.emplace(k, v);
|
||||
if (it != m.end()) {
|
||||
it->second = v;
|
||||
} else {
|
||||
m.emplace(k, v);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -583,8 +606,9 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &
|
||||
s << name << '{';
|
||||
bool f = false;
|
||||
for (auto const &kv : m) {
|
||||
if (f)
|
||||
if (f) {
|
||||
s << ", ";
|
||||
}
|
||||
s << kv.first << ": " << kv.second;
|
||||
f = true;
|
||||
}
|
||||
@ -675,8 +699,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
|
||||
cl.def("__getitem__",
|
||||
[](Map &m, const KeyType &k) -> MappedType & {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end())
|
||||
throw key_error();
|
||||
if (it == m.end()) {
|
||||
throw key_error();
|
||||
}
|
||||
return it->second;
|
||||
},
|
||||
return_value_policy::reference_internal // ref + keepalive
|
||||
@ -685,8 +710,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
|
||||
cl.def("__contains__",
|
||||
[](Map &m, const KeyType &k) -> bool {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end())
|
||||
return false;
|
||||
if (it == m.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@ -699,8 +725,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
|
||||
cl.def("__delitem__",
|
||||
[](Map &m, const KeyType &k) {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end())
|
||||
if (it == m.end()) {
|
||||
throw key_error();
|
||||
}
|
||||
m.erase(it);
|
||||
}
|
||||
);
|
||||
@ -717,8 +744,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
|
||||
keys_view.def("__contains__",
|
||||
[](KeysView &view, const KeyType &k) -> bool {
|
||||
auto it = view.map.find(k);
|
||||
if (it == view.map.end())
|
||||
if (it == view.map.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
@ -101,10 +101,11 @@ public:
|
||||
}
|
||||
|
||||
void destroyed(void *inst) {
|
||||
if (--_instances[inst] < 0)
|
||||
if (--_instances[inst] < 0) {
|
||||
throw std::runtime_error("cstats.destroyed() called with unknown "
|
||||
"instance; potential double-destruction "
|
||||
"or a missing cstats.created()");
|
||||
}
|
||||
}
|
||||
|
||||
static void gc() {
|
||||
@ -127,9 +128,11 @@ public:
|
||||
int alive() {
|
||||
gc();
|
||||
int total = 0;
|
||||
for (const auto &p : _instances)
|
||||
if (p.second > 0)
|
||||
for (const auto &p : _instances) {
|
||||
if (p.second > 0) {
|
||||
total += p.second;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
@ -145,7 +148,9 @@ public:
|
||||
// Move out stored values
|
||||
py::list values() {
|
||||
py::list l;
|
||||
for (const auto &v : _values) l.append(py::cast(v));
|
||||
for (const auto &v : _values) {
|
||||
l.append(py::cast(v));
|
||||
}
|
||||
_values.clear();
|
||||
return l;
|
||||
}
|
||||
@ -181,7 +186,9 @@ public:
|
||||
}
|
||||
}
|
||||
catch (const std::out_of_range&) {}
|
||||
if (!t1) throw std::runtime_error("Unknown class passed to ConstructorStats::get()");
|
||||
if (!t1) {
|
||||
throw std::runtime_error("Unknown class passed to ConstructorStats::get()");
|
||||
}
|
||||
auto &cs1 = get(*t1);
|
||||
// If we have both a t1 and t2 match, one is probably the trampoline class; return whichever
|
||||
// has more constructions (typically one or the other will be 0)
|
||||
@ -189,7 +196,9 @@ public:
|
||||
auto &cs2 = get(*t2);
|
||||
int cs1_total = cs1.default_constructions + cs1.copy_constructions + cs1.move_constructions + (int) cs1._values.size();
|
||||
int cs2_total = cs2.default_constructions + cs2.copy_constructions + cs2.move_constructions + (int) cs2._values.size();
|
||||
if (cs2_total > cs1_total) return cs2;
|
||||
if (cs2_total > cs1_total) {
|
||||
return cs2;
|
||||
}
|
||||
}
|
||||
return cs1;
|
||||
}
|
||||
|
@ -27,10 +27,11 @@ public:
|
||||
*/
|
||||
void decRef(bool dealloc = true) const {
|
||||
--m_refCount;
|
||||
if (m_refCount == 0 && dealloc)
|
||||
if (m_refCount == 0 && dealloc) {
|
||||
delete this;
|
||||
else if (m_refCount < 0)
|
||||
} else if (m_refCount < 0) {
|
||||
throw std::runtime_error("Internal error: reference count < 0!");
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
@ -66,7 +67,9 @@ public:
|
||||
|
||||
/// Construct a reference from a pointer
|
||||
explicit ref(T *ptr) : m_ptr(ptr) {
|
||||
if (m_ptr) ((Object *) m_ptr)->incRef();
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
|
||||
print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer");
|
||||
|
||||
@ -74,8 +77,9 @@ public:
|
||||
|
||||
/// Copy constructor
|
||||
ref(const ref &r) : m_ptr(r.m_ptr) {
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
|
||||
print_copy_created(this, "with pointer", m_ptr); track_copy_created((ref_tag*) this);
|
||||
}
|
||||
@ -89,8 +93,9 @@ public:
|
||||
|
||||
/// Destroy this reference
|
||||
~ref() {
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
|
||||
print_destroyed(this); track_destroyed((ref_tag*) this);
|
||||
}
|
||||
@ -99,10 +104,12 @@ public:
|
||||
ref &operator=(ref &&r) noexcept {
|
||||
print_move_assigned(this, "pointer", r.m_ptr); track_move_assigned((ref_tag*) this);
|
||||
|
||||
if (*this == r)
|
||||
if (*this == r) {
|
||||
return *this;
|
||||
if (m_ptr)
|
||||
}
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
m_ptr = r.m_ptr;
|
||||
r.m_ptr = nullptr;
|
||||
return *this;
|
||||
@ -116,13 +123,16 @@ public:
|
||||
print_copy_assigned(this, "pointer", r.m_ptr);
|
||||
track_copy_assigned((ref_tag *) this);
|
||||
|
||||
if (m_ptr == r.m_ptr)
|
||||
if (m_ptr == r.m_ptr) {
|
||||
return *this;
|
||||
if (m_ptr)
|
||||
}
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
m_ptr = r.m_ptr;
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -130,13 +140,16 @@ public:
|
||||
ref& operator=(T *ptr) {
|
||||
print_values(this, "assigned pointer"); track_values((ref_tag*) this, "assigned pointer");
|
||||
|
||||
if (m_ptr == ptr)
|
||||
if (m_ptr == ptr) {
|
||||
return *this;
|
||||
if (m_ptr)
|
||||
}
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
m_ptr = ptr;
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,9 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); });
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const shared_exception &e) {
|
||||
PyErr_SetString(PyExc_KeyError, e.what());
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ PYBIND11_MODULE(pybind11_tests, m) {
|
||||
.def(py::init<int>())
|
||||
.def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); });
|
||||
|
||||
for (const auto &initializer : initializers())
|
||||
for (const auto &initializer : initializers()) {
|
||||
initializer(m);
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +85,9 @@ TEST_SUBMODULE(buffers, m) {
|
||||
/// Construct from a buffer
|
||||
.def(py::init([](const py::buffer &b) {
|
||||
py::buffer_info info = b.request();
|
||||
if (info.format != py::format_descriptor<float>::format() || info.ndim != 2)
|
||||
if (info.format != py::format_descriptor<float>::format() || info.ndim != 2) {
|
||||
throw std::runtime_error("Incompatible buffer format!");
|
||||
}
|
||||
|
||||
auto v = new Matrix(info.shape[0], info.shape[1]);
|
||||
memcpy(v->data(), info.ptr, sizeof(float) * (size_t) (v->rows() * v->cols()));
|
||||
@ -99,14 +100,16 @@ TEST_SUBMODULE(buffers, m) {
|
||||
/// Bare bones interface
|
||||
.def("__getitem__",
|
||||
[](const Matrix &m, std::pair<py::ssize_t, py::ssize_t> i) {
|
||||
if (i.first >= m.rows() || i.second >= m.cols())
|
||||
if (i.first >= m.rows() || i.second >= m.cols()) {
|
||||
throw py::index_error();
|
||||
}
|
||||
return m(i.first, i.second);
|
||||
})
|
||||
.def("__setitem__",
|
||||
[](Matrix &m, std::pair<py::ssize_t, py::ssize_t> i, float v) {
|
||||
if (i.first >= m.rows() || i.second >= m.cols())
|
||||
if (i.first >= m.rows() || i.second >= m.cols()) {
|
||||
throw py::index_error();
|
||||
}
|
||||
m(i.first, i.second) = v;
|
||||
})
|
||||
/// Provide buffer access
|
||||
|
@ -93,8 +93,11 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
// Under Python 2.7, invalid unicode UTF-32 characters don't appear to trigger UnicodeDecodeError
|
||||
m.def("bad_utf32_string", [=]() { return std::u32string({ a32, char32_t(0xd800), z32 }); });
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2))
|
||||
m.def("bad_wchar_string", [=]() { return std::wstring({ wchar_t(0x61), wchar_t(0xd800) }); });
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) {
|
||||
m.def("bad_wchar_string", [=]() {
|
||||
return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
|
||||
});
|
||||
}
|
||||
#endif
|
||||
m.def("u8_Z", []() -> char { return 'Z'; });
|
||||
m.def("u8_eacute", []() -> char { return '\xe9'; });
|
||||
@ -133,9 +136,21 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
m.def("string_view_print", [](std::string_view s) { py::print(s, s.size()); });
|
||||
m.def("string_view16_print", [](std::u16string_view s) { py::print(s, s.size()); });
|
||||
m.def("string_view32_print", [](std::u32string_view s) { py::print(s, s.size()); });
|
||||
m.def("string_view_chars", [](std::string_view s) { py::list l; for (auto c : s) l.append((std::uint8_t) c); return l; });
|
||||
m.def("string_view16_chars", [](std::u16string_view s) { py::list l; for (auto c : s) l.append((int) c); return l; });
|
||||
m.def("string_view32_chars", [](std::u32string_view s) { py::list l; for (auto c : s) l.append((int) c); return l; });
|
||||
m.def("string_view_chars", [](std::string_view s) { py::list l;
|
||||
for (auto c : s) {
|
||||
l.append((std::uint8_t) c);
|
||||
}
|
||||
return l; });
|
||||
m.def("string_view16_chars", [](std::u16string_view s) { py::list l;
|
||||
for (auto c : s) {
|
||||
l.append((int) c);
|
||||
}
|
||||
return l; });
|
||||
m.def("string_view32_chars", [](std::u32string_view s) { py::list l;
|
||||
for (auto c : s) {
|
||||
l.append((int) c);
|
||||
}
|
||||
return l; });
|
||||
m.def("string_view_return", []() { return std::string_view((const char*)u8"utf8 secret \U0001f382"); });
|
||||
m.def("string_view16_return", []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
|
||||
m.def("string_view32_return", []() { return std::u32string_view(U"utf32 secret \U0001f382"); });
|
||||
|
@ -95,8 +95,9 @@ TEST_SUBMODULE(call_policies, m) {
|
||||
// but it's unclear how to test it without `PyGILState_GetThisThreadState`.
|
||||
auto report_gil_status = []() {
|
||||
auto is_gil_held = false;
|
||||
if (auto tstate = py::detail::get_thread_state_unchecked())
|
||||
if (auto tstate = py::detail::get_thread_state_unchecked()) {
|
||||
is_gil_held = (tstate == PyGILState_GetThisThreadState());
|
||||
}
|
||||
|
||||
return is_gil_held ? "GIL held" : "GIL released";
|
||||
};
|
||||
|
@ -136,11 +136,16 @@ TEST_SUBMODULE(callbacks, m) {
|
||||
m.def("dummy_function_overloaded", [](int i, int j) { return i + j; });
|
||||
m.def("dummy_function_overloaded", &dummy_function);
|
||||
m.def("dummy_function2", [](int i, int j) { return i + j; });
|
||||
m.def("roundtrip", [](std::function<int(int)> f, bool expect_none = false) {
|
||||
if (expect_none && f)
|
||||
throw std::runtime_error("Expected None to be converted to empty std::function");
|
||||
return f;
|
||||
}, py::arg("f"), py::arg("expect_none")=false);
|
||||
m.def(
|
||||
"roundtrip",
|
||||
[](std::function<int(int)> f, bool expect_none = false) {
|
||||
if (expect_none && f) {
|
||||
throw std::runtime_error("Expected None to be converted to empty std::function");
|
||||
}
|
||||
return f;
|
||||
},
|
||||
py::arg("f"),
|
||||
py::arg("expect_none") = false);
|
||||
m.def("test_dummy_function", [](const std::function<int(int)> &f) -> std::string {
|
||||
using fn_type = int (*)(int);
|
||||
auto result = f.target<fn_type>();
|
||||
@ -215,8 +220,9 @@ TEST_SUBMODULE(callbacks, m) {
|
||||
};
|
||||
|
||||
// spawn worker threads
|
||||
for (auto i : work)
|
||||
for (auto i : work) {
|
||||
start_f(py::cast<int>(i));
|
||||
}
|
||||
});
|
||||
|
||||
m.def("callback_num_times", [](const py::function &f, std::size_t num) {
|
||||
|
@ -139,9 +139,13 @@ TEST_SUBMODULE(class_, m) {
|
||||
|
||||
m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
|
||||
m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
|
||||
m.def("return_class_n", [](int n) -> BaseClass* {
|
||||
if (n == 1) return new DerivedClass1();
|
||||
if (n == 2) return new DerivedClass2();
|
||||
m.def("return_class_n", [](int n) -> BaseClass * {
|
||||
if (n == 1) {
|
||||
return new DerivedClass1();
|
||||
}
|
||||
if (n == 2) {
|
||||
return new DerivedClass2();
|
||||
}
|
||||
return new BaseClass();
|
||||
});
|
||||
m.def("return_none", []() -> BaseClass* { return nullptr; });
|
||||
@ -167,8 +171,9 @@ TEST_SUBMODULE(class_, m) {
|
||||
// See https://github.com/pybind/pybind11/issues/2486
|
||||
// if (category == 2)
|
||||
// return py::type::of<int>();
|
||||
if (category == 1)
|
||||
if (category == 1) {
|
||||
return py::type::of<DerivedClass1>();
|
||||
}
|
||||
return py::type::of<Invalid>();
|
||||
});
|
||||
|
||||
|
@ -104,7 +104,9 @@ public:
|
||||
bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; }
|
||||
static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
||||
static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {
|
||||
if (!src) return none().release();
|
||||
if (!src) {
|
||||
return none().release();
|
||||
}
|
||||
return cast(*src, policy, parent);
|
||||
}
|
||||
explicit operator CopyOnlyInt *() { return &value; }
|
||||
@ -203,8 +205,9 @@ TEST_SUBMODULE(copy_move_policies, m) {
|
||||
private:
|
||||
void *operator new(size_t bytes) {
|
||||
void *ptr = std::malloc(bytes);
|
||||
if (ptr)
|
||||
if (ptr) {
|
||||
return ptr;
|
||||
}
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
};
|
||||
|
@ -28,8 +28,11 @@ using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::R
|
||||
// Sets/resets a testing reference matrix to have values of 10*r + c, where r and c are the
|
||||
// (1-based) row/column number.
|
||||
template <typename M> void reset_ref(M &x) {
|
||||
for (int i = 0; i < x.rows(); i++) for (int j = 0; j < x.cols(); j++)
|
||||
x(i, j) = 11 + 10*i + j;
|
||||
for (int i = 0; i < x.rows(); i++) {
|
||||
for (int j = 0; j < x.cols(); j++) {
|
||||
x(i, j) = 11 + 10 * i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a static, column-major matrix
|
||||
@ -63,9 +66,11 @@ double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); };
|
||||
// reference is referencing rows/columns correctly).
|
||||
template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m) {
|
||||
Eigen::MatrixXd ret(m);
|
||||
for (int c = 0; c < m.cols(); c++)
|
||||
for (int r = 0; r < m.rows(); r++)
|
||||
ret(r, c) += 10*r + 100*c; // NOLINT(clang-analyzer-core.uninitialized.Assign)
|
||||
for (int c = 0; c < m.cols(); c++) {
|
||||
for (int r = 0; r < m.rows(); r++) {
|
||||
ret(r, c) += 10 * r + 100 * c; // NOLINT(clang-analyzer-core.uninitialized.Assign)
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -225,7 +230,9 @@ TEST_SUBMODULE(eigen, m) {
|
||||
// Returns a DiagonalMatrix with diagonal (1,2,3,...)
|
||||
m.def("incr_diag", [](int k) {
|
||||
Eigen::DiagonalMatrix<int, Eigen::Dynamic> m(k);
|
||||
for (int i = 0; i < k; i++) m.diagonal()[i] = i+1;
|
||||
for (int i = 0; i < k; i++) {
|
||||
m.diagonal()[i] = i + 1;
|
||||
}
|
||||
return m;
|
||||
});
|
||||
|
||||
@ -320,8 +327,9 @@ TEST_SUBMODULE(eigen, m) {
|
||||
"matrix_multiply",
|
||||
[](const py::EigenDRef<const Eigen::MatrixXd> &A,
|
||||
const py::EigenDRef<const Eigen::MatrixXd> &B) -> Eigen::MatrixXd {
|
||||
if (A.cols() != B.rows())
|
||||
if (A.cols() != B.rows()) {
|
||||
throw std::domain_error("Nonconformable matrices!");
|
||||
}
|
||||
return A * B;
|
||||
},
|
||||
py::arg("A"),
|
||||
|
@ -307,7 +307,11 @@ TEST_CASE("Threads") {
|
||||
struct scope_exit {
|
||||
std::function<void()> f_;
|
||||
explicit scope_exit(std::function<void()> f) noexcept : f_(std::move(f)) {}
|
||||
~scope_exit() { if (f_) f_(); }
|
||||
~scope_exit() {
|
||||
if (f_) {
|
||||
f_();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Reload module from file") {
|
||||
|
@ -93,8 +93,9 @@ TEST_SUBMODULE(eval_, m) {
|
||||
|
||||
// test_eval_empty_globals
|
||||
m.def("eval_empty_globals", [](py::object global) {
|
||||
if (global.is_none())
|
||||
if (global.is_none()) {
|
||||
global = py::dict();
|
||||
}
|
||||
auto int_class = py::eval("isinstance(42, int)", global);
|
||||
return global;
|
||||
});
|
||||
|
@ -116,7 +116,9 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
static py::exception<MyException> ex(m, "MyException");
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const MyException &e) {
|
||||
// Set MyException as the active python error
|
||||
ex(e.what());
|
||||
@ -128,7 +130,9 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
// never by visible from Python
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const MyException2 &e) {
|
||||
// Translate this exception to a standard RuntimeError
|
||||
PyErr_SetString(PyExc_RuntimeError, e.what());
|
||||
@ -140,7 +144,9 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
// translator for MyException by throwing a new exception
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const MyException4 &e) {
|
||||
throw MyException(e.what());
|
||||
}
|
||||
@ -181,7 +187,9 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
py::object o = foo["bar"];
|
||||
}
|
||||
catch (py::error_already_set& ex) {
|
||||
if (!ex.matches(PyExc_KeyError)) throw;
|
||||
if (!ex.matches(PyExc_KeyError)) {
|
||||
throw;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -193,7 +201,9 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
py::object o = foo["bar"];
|
||||
}
|
||||
catch (py::error_already_set &ex) {
|
||||
if (!ex.matches(PyExc_Exception)) throw;
|
||||
if (!ex.matches(PyExc_Exception)) {
|
||||
throw;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -204,15 +214,18 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
py::module_::import("nonexistent");
|
||||
}
|
||||
catch (py::error_already_set &ex) {
|
||||
if (!ex.matches(PyExc_ImportError)) throw;
|
||||
if (!ex.matches(PyExc_ImportError)) {
|
||||
throw;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
m.def("throw_already_set", [](bool err) {
|
||||
if (err)
|
||||
if (err) {
|
||||
PyErr_SetString(PyExc_ValueError, "foo");
|
||||
}
|
||||
try {
|
||||
throw py::error_already_set();
|
||||
} catch (const std::runtime_error& e) {
|
||||
@ -224,8 +237,9 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
if (err)
|
||||
if (err) {
|
||||
PyErr_SetString(PyExc_ValueError, "foo");
|
||||
}
|
||||
throw py::error_already_set();
|
||||
});
|
||||
|
||||
@ -252,10 +266,11 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
try {
|
||||
f(*args);
|
||||
} catch (py::error_already_set &ex) {
|
||||
if (ex.matches(exc_type))
|
||||
if (ex.matches(exc_type)) {
|
||||
py::print(ex.what());
|
||||
else
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -22,8 +22,9 @@
|
||||
void noisy_function(const std::string &msg, bool flush) {
|
||||
|
||||
std::cout << msg;
|
||||
if (flush)
|
||||
if (flush) {
|
||||
std::cout << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
void noisy_funct_dual(const std::string &msg, const std::string &emsg) {
|
||||
|
@ -26,8 +26,9 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
std::vector<int> list{{13, 17}};
|
||||
m.def("kw_func4", [](const std::vector<int> &entries) {
|
||||
std::string ret = "{";
|
||||
for (int i : entries)
|
||||
for (int i : entries) {
|
||||
ret += std::to_string(i) + " ";
|
||||
}
|
||||
ret.back() = '}';
|
||||
return ret;
|
||||
}, py::arg("myList") = list);
|
||||
@ -89,18 +90,20 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
m.def("args_refcount", [](py::args a) {
|
||||
GC_IF_NEEDED;
|
||||
py::tuple t(a.size());
|
||||
for (size_t i = 0; i < a.size(); i++)
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
// Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
|
||||
t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
|
||||
}
|
||||
return t;
|
||||
});
|
||||
m.def("mixed_args_refcount", [](const py::object &o, py::args a) {
|
||||
GC_IF_NEEDED;
|
||||
py::tuple t(a.size() + 1);
|
||||
t[0] = o.ref_count();
|
||||
for (size_t i = 0; i < a.size(); i++)
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
// Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
|
||||
t[i + 1] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
|
||||
}
|
||||
return t;
|
||||
});
|
||||
|
||||
|
@ -47,8 +47,9 @@ TEST_SUBMODULE(local_bindings, m) {
|
||||
auto main = py::module_::import("pybind11_tests");
|
||||
if (py::hasattr(main, "class_")) {
|
||||
bind_local<LocalExternal, 7>(m, "LocalExternal", py::module_local());
|
||||
} else {
|
||||
throw std::runtime_error("test_class not enabled");
|
||||
}
|
||||
else throw std::runtime_error("test_class not enabled");
|
||||
});
|
||||
|
||||
// test_stl_bind_local
|
||||
|
@ -90,15 +90,17 @@ template<typename... Ix> arr data_t(const arr_t& a, Ix... index) {
|
||||
|
||||
template<typename... Ix> arr& mutate_data(arr& a, Ix... index) {
|
||||
auto ptr = (uint8_t *) a.mutable_data(index...);
|
||||
for (py::ssize_t i = 0; i < a.nbytes() - a.offset_at(index...); i++)
|
||||
for (py::ssize_t i = 0; i < a.nbytes() - a.offset_at(index...); i++) {
|
||||
ptr[i] = (uint8_t) (ptr[i] * 2);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename... Ix> arr_t& mutate_data_t(arr_t& a, Ix... index) {
|
||||
auto ptr = a.mutable_data(index...);
|
||||
for (py::ssize_t i = 0; i < a.size() - a.index_at(index...); i++)
|
||||
for (py::ssize_t i = 0; i < a.size() - a.index_at(index...); i++) {
|
||||
ptr[i]++;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
@ -116,7 +118,9 @@ template<typename... Ix> arr_t& mutate_at_t(arr_t& a, Ix... idx) { a.mutable_at(
|
||||
sm.def(#name, [](type a, int i, int j, int k) { return name(a, i, j, k); });
|
||||
|
||||
template <typename T, typename T2> py::handle auxiliaries(T &&r, T2 &&r2) {
|
||||
if (r.ndim() != 2) throw std::domain_error("error: ndim != 2");
|
||||
if (r.ndim() != 2) {
|
||||
throw std::domain_error("error: ndim != 2");
|
||||
}
|
||||
py::list l;
|
||||
l.append(*r.data(0, 0));
|
||||
l.append(*r2.mutable_data(0, 0));
|
||||
@ -292,34 +296,43 @@ TEST_SUBMODULE(numpy_array, sm) {
|
||||
// test_array_unchecked_fixed_dims
|
||||
sm.def("proxy_add2", [](py::array_t<double> a, double v) {
|
||||
auto r = a.mutable_unchecked<2>();
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++) {
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++) {
|
||||
r(i, j) += v;
|
||||
}
|
||||
}
|
||||
}, py::arg{}.noconvert(), py::arg());
|
||||
|
||||
sm.def("proxy_init3", [](double start) {
|
||||
py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
|
||||
auto r = a.mutable_unchecked<3>();
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||
for (py::ssize_t k = 0; k < r.shape(2); k++)
|
||||
r(i, j, k) = start++;
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++) {
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++) {
|
||||
for (py::ssize_t k = 0; k < r.shape(2); k++) {
|
||||
r(i, j, k) = start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
});
|
||||
sm.def("proxy_init3F", [](double start) {
|
||||
py::array_t<double, py::array::f_style> a({ 3, 3, 3 });
|
||||
auto r = a.mutable_unchecked<3>();
|
||||
for (py::ssize_t k = 0; k < r.shape(2); k++)
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||
r(i, j, k) = start++;
|
||||
for (py::ssize_t k = 0; k < r.shape(2); k++) {
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++) {
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++) {
|
||||
r(i, j, k) = start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
});
|
||||
sm.def("proxy_squared_L2_norm", [](const py::array_t<double> &a) {
|
||||
auto r = a.unchecked<1>();
|
||||
double sumsq = 0;
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++) {
|
||||
sumsq += r[i] * r(i); // Either notation works for a 1D array
|
||||
}
|
||||
return sumsq;
|
||||
});
|
||||
|
||||
@ -345,19 +358,28 @@ TEST_SUBMODULE(numpy_array, sm) {
|
||||
// Same as the above, but without a compile-time dimensions specification:
|
||||
sm.def("proxy_add2_dyn", [](py::array_t<double> a, double v) {
|
||||
auto r = a.mutable_unchecked();
|
||||
if (r.ndim() != 2) throw std::domain_error("error: ndim != 2");
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||
if (r.ndim() != 2) {
|
||||
throw std::domain_error("error: ndim != 2");
|
||||
}
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++) {
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++) {
|
||||
r(i, j) += v;
|
||||
}
|
||||
}
|
||||
}, py::arg{}.noconvert(), py::arg());
|
||||
sm.def("proxy_init3_dyn", [](double start) {
|
||||
py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
|
||||
auto r = a.mutable_unchecked();
|
||||
if (r.ndim() != 3) throw std::domain_error("error: ndim != 3");
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||
for (py::ssize_t k = 0; k < r.shape(2); k++)
|
||||
r(i, j, k) = start++;
|
||||
if (r.ndim() != 3) {
|
||||
throw std::domain_error("error: ndim != 3");
|
||||
}
|
||||
for (py::ssize_t i = 0; i < r.shape(0); i++) {
|
||||
for (py::ssize_t j = 0; j < r.shape(1); j++) {
|
||||
for (py::ssize_t k = 0; k < r.shape(2); k++) {
|
||||
r(i, j, k) = start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
});
|
||||
sm.def("proxy_auxiliaries2_dyn", [](py::array_t<double> a) {
|
||||
@ -386,8 +408,10 @@ TEST_SUBMODULE(numpy_array, sm) {
|
||||
// reshape array to 2D without changing size
|
||||
sm.def("array_reshape2", [](py::array_t<double> a) {
|
||||
const auto dim_sz = (py::ssize_t)std::sqrt(a.size());
|
||||
if (dim_sz * dim_sz != a.size())
|
||||
throw std::domain_error("array_reshape2: input array total size is not a squared integer");
|
||||
if (dim_sz * dim_sz != a.size()) {
|
||||
throw std::domain_error(
|
||||
"array_reshape2: input array total size is not a squared integer");
|
||||
}
|
||||
a.resize({dim_sz, dim_sz});
|
||||
});
|
||||
|
||||
|
@ -108,30 +108,35 @@ PYBIND11_PACKED(struct EnumStruct {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const StringStruct& v) {
|
||||
os << "a='";
|
||||
for (size_t i = 0; i < 3 && (v.a[i] != 0); i++)
|
||||
for (size_t i = 0; i < 3 && (v.a[i] != 0); i++) {
|
||||
os << v.a[i];
|
||||
}
|
||||
os << "',b='";
|
||||
for (size_t i = 0; i < 3 && (v.b[i] != 0); i++)
|
||||
for (size_t i = 0; i < 3 && (v.b[i] != 0); i++) {
|
||||
os << v.b[i];
|
||||
}
|
||||
return os << "'";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ArrayStruct& v) {
|
||||
os << "a={";
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (i > 0)
|
||||
if (i > 0) {
|
||||
os << ',';
|
||||
}
|
||||
os << '{';
|
||||
for (int j = 0; j < 3; j++)
|
||||
for (int j = 0; j < 3; j++) {
|
||||
os << v.a[i][j] << ',';
|
||||
}
|
||||
os << v.a[i][3] << '}';
|
||||
}
|
||||
os << "},b={" << v.b[0] << ',' << v.b[1];
|
||||
os << "},c={" << int(v.c[0]) << ',' << int(v.c[1]) << ',' << int(v.c[2]);
|
||||
os << "},d={";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (i > 0)
|
||||
if (i > 0) {
|
||||
os << ',';
|
||||
}
|
||||
os << '{' << v.d[i][0] << ',' << v.d[i][1] << '}';
|
||||
}
|
||||
return os << '}';
|
||||
@ -198,7 +203,9 @@ py::array_t<int32_t, 0> test_array_ctors(int i) {
|
||||
|
||||
auto fill = [](py::array arr) {
|
||||
auto req = arr.request();
|
||||
for (int i = 0; i < 6; i++) ((int32_t *) req.ptr)[i] = i + 1;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
((int32_t *) req.ptr)[i] = i + 1;
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
@ -373,32 +380,33 @@ TEST_SUBMODULE(numpy_dtypes, m) {
|
||||
|
||||
m.def("print_dtypes", []() {
|
||||
py::list l;
|
||||
for (const py::handle &d : {
|
||||
py::dtype::of<SimpleStruct>(),
|
||||
py::dtype::of<PackedStruct>(),
|
||||
py::dtype::of<NestedStruct>(),
|
||||
py::dtype::of<PartialStruct>(),
|
||||
py::dtype::of<PartialNestedStruct>(),
|
||||
py::dtype::of<StringStruct>(),
|
||||
py::dtype::of<ArrayStruct>(),
|
||||
py::dtype::of<EnumStruct>(),
|
||||
py::dtype::of<StructWithUglyNames>(),
|
||||
py::dtype::of<ComplexStruct>()
|
||||
})
|
||||
for (const py::handle &d : {py::dtype::of<SimpleStruct>(),
|
||||
py::dtype::of<PackedStruct>(),
|
||||
py::dtype::of<NestedStruct>(),
|
||||
py::dtype::of<PartialStruct>(),
|
||||
py::dtype::of<PartialNestedStruct>(),
|
||||
py::dtype::of<StringStruct>(),
|
||||
py::dtype::of<ArrayStruct>(),
|
||||
py::dtype::of<EnumStruct>(),
|
||||
py::dtype::of<StructWithUglyNames>(),
|
||||
py::dtype::of<ComplexStruct>()}) {
|
||||
l.append(py::str(d));
|
||||
}
|
||||
return l;
|
||||
});
|
||||
m.def("test_dtype_ctors", &test_dtype_ctors);
|
||||
m.def("test_dtype_kind", [dtype_names]() {
|
||||
py::list list;
|
||||
for (auto& dt_name : dtype_names)
|
||||
for (auto &dt_name : dtype_names) {
|
||||
list.append(py::dtype(dt_name).kind());
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_char_", [dtype_names]() {
|
||||
py::list list;
|
||||
for (auto& dt_name : dtype_names)
|
||||
for (auto &dt_name : dtype_names) {
|
||||
list.append(py::dtype(dt_name).char_());
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_methods", []() {
|
||||
@ -423,8 +431,9 @@ TEST_SUBMODULE(numpy_dtypes, m) {
|
||||
if (non_empty) {
|
||||
auto req = arr.request();
|
||||
auto ptr = static_cast<StringStruct*>(req.ptr);
|
||||
for (py::ssize_t i = 0; i < req.size * req.itemsize; i++)
|
||||
static_cast<char*>(req.ptr)[i] = 0;
|
||||
for (py::ssize_t i = 0; i < req.size * req.itemsize; i++) {
|
||||
static_cast<char *>(req.ptr)[i] = 0;
|
||||
}
|
||||
ptr[1].a[0] = 'a'; ptr[1].b[0] = 'a';
|
||||
ptr[2].a[0] = 'a'; ptr[2].b[0] = 'a';
|
||||
ptr[3].a[0] = 'a'; ptr[3].b[0] = 'a';
|
||||
@ -443,16 +452,22 @@ TEST_SUBMODULE(numpy_dtypes, m) {
|
||||
py::array_t<ArrayStruct, 0> arr = mkarray_via_buffer<ArrayStruct>(n);
|
||||
auto ptr = (ArrayStruct *) arr.mutable_data();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < 3; j++)
|
||||
for (size_t k = 0; k < 4; k++)
|
||||
for (size_t j = 0; j < 3; j++) {
|
||||
for (size_t k = 0; k < 4; k++) {
|
||||
ptr[i].a[j][k] = char('A' + (i * 100 + j * 10 + k) % 26);
|
||||
for (size_t j = 0; j < 2; j++)
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < 2; j++) {
|
||||
ptr[i].b[j] = int32_t(i * 1000 + j);
|
||||
for (size_t j = 0; j < 3; j++)
|
||||
}
|
||||
for (size_t j = 0; j < 3; j++) {
|
||||
ptr[i].c[j] = uint8_t(i * 10 + j);
|
||||
for (size_t j = 0; j < 4; j++)
|
||||
for (size_t k = 0; k < 2; k++)
|
||||
}
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
for (size_t k = 0; k < 2; k++) {
|
||||
ptr[i].d[j][k] = float(i) * 100.0f + float(j) * 10.0f + float(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
});
|
||||
|
@ -45,8 +45,9 @@ TEST_SUBMODULE(opaque_types, m) {
|
||||
std::string ret = "Opaque list: [";
|
||||
bool first = true;
|
||||
for (const auto &entry : l) {
|
||||
if (!first)
|
||||
if (!first) {
|
||||
ret += ", ";
|
||||
}
|
||||
ret += entry;
|
||||
first = false;
|
||||
}
|
||||
|
@ -39,13 +39,15 @@ void wrap(py::module m) {
|
||||
.def(py::pickle(
|
||||
[](const py::object &self) {
|
||||
py::dict d;
|
||||
if (py::hasattr(self, "__dict__"))
|
||||
if (py::hasattr(self, "__dict__")) {
|
||||
d = self.attr("__dict__");
|
||||
}
|
||||
return py::make_tuple(self.attr("num"), d);
|
||||
},
|
||||
[](const py::tuple &t) {
|
||||
if (t.size() != 2)
|
||||
if (t.size() != 2) {
|
||||
throw std::runtime_error("Invalid state!");
|
||||
}
|
||||
auto cpp_state = std::unique_ptr<SimpleBase>(new SimpleBaseTrampoline);
|
||||
cpp_state->num = t[0].cast<int>();
|
||||
auto py_state = t[1].cast<py::dict>();
|
||||
@ -101,8 +103,9 @@ TEST_SUBMODULE(pickling, m) {
|
||||
});
|
||||
ignoreOldStyleInitWarnings([&pyPickleable]() {
|
||||
pyPickleable.def("__setstate__", [](Pickleable &p, const py::tuple &t) {
|
||||
if (t.size() != 3)
|
||||
if (t.size() != 3) {
|
||||
throw std::runtime_error("Invalid state!");
|
||||
}
|
||||
/* Invoke the constructor (need to use in-place version) */
|
||||
new (&p) Pickleable(t[0].cast<std::string>());
|
||||
|
||||
@ -119,8 +122,9 @@ TEST_SUBMODULE(pickling, m) {
|
||||
return py::make_tuple(p.value(), p.extra1(), p.extra2());
|
||||
},
|
||||
[](const py::tuple &t) {
|
||||
if (t.size() != 3)
|
||||
if (t.size() != 3) {
|
||||
throw std::runtime_error("Invalid state!");
|
||||
}
|
||||
auto p = PickleableNew(t[0].cast<std::string>());
|
||||
|
||||
p.setExtra1(t[1].cast<int>());
|
||||
@ -153,8 +157,9 @@ TEST_SUBMODULE(pickling, m) {
|
||||
});
|
||||
ignoreOldStyleInitWarnings([&pyPickleableWithDict]() {
|
||||
pyPickleableWithDict.def("__setstate__", [](const py::object &self, const py::tuple &t) {
|
||||
if (t.size() != 3)
|
||||
if (t.size() != 3) {
|
||||
throw std::runtime_error("Invalid state!");
|
||||
}
|
||||
/* Cast and construct */
|
||||
auto &p = self.cast<PickleableWithDict &>();
|
||||
new (&p) PickleableWithDict(t[0].cast<std::string>());
|
||||
@ -174,8 +179,9 @@ TEST_SUBMODULE(pickling, m) {
|
||||
return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
|
||||
},
|
||||
[](const py::tuple &t) {
|
||||
if (t.size() != 3)
|
||||
if (t.size() != 3) {
|
||||
throw std::runtime_error("Invalid state!");
|
||||
}
|
||||
|
||||
auto cpp_state = PickleableWithDictNew(t[0].cast<std::string>());
|
||||
cpp_state.extra = t[1].cast<int>();
|
||||
|
@ -40,8 +40,9 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
});
|
||||
m.def("print_list", [](const py::list &list) {
|
||||
int index = 0;
|
||||
for (auto item : list)
|
||||
for (auto item : list) {
|
||||
py::print("list item {}: {}"_s.format(index++, item));
|
||||
}
|
||||
});
|
||||
// test_none
|
||||
m.def("get_none", []{return py::none();});
|
||||
@ -56,8 +57,9 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
return set;
|
||||
});
|
||||
m.def("print_set", [](const py::set &set) {
|
||||
for (auto item : set)
|
||||
for (auto item : set) {
|
||||
py::print("key:", item);
|
||||
}
|
||||
});
|
||||
m.def("set_contains",
|
||||
[](const py::set &set, const py::object &key) { return set.contains(key); });
|
||||
@ -66,8 +68,9 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
// test_dict
|
||||
m.def("get_dict", []() { return py::dict("key"_a="value"); });
|
||||
m.def("print_dict", [](const py::dict &dict) {
|
||||
for (auto item : dict)
|
||||
for (auto item : dict) {
|
||||
py::print("key: {}, value={}"_s.format(item.first, item.second));
|
||||
}
|
||||
});
|
||||
m.def("dict_keyword_constructor", []() {
|
||||
auto d1 = py::dict("x"_a=1, "y"_a=2);
|
||||
@ -405,9 +408,9 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
m.def("test_memoryview_from_buffer", [](bool is_unsigned) {
|
||||
static const int16_t si16[] = { 3, 1, 4, 1, 5 };
|
||||
static const uint16_t ui16[] = { 2, 7, 1, 8 };
|
||||
if (is_unsigned)
|
||||
return py::memoryview::from_buffer(
|
||||
ui16, { 4 }, { sizeof(uint16_t) });
|
||||
if (is_unsigned) {
|
||||
return py::memoryview::from_buffer(ui16, {4}, {sizeof(uint16_t)});
|
||||
}
|
||||
return py::memoryview::from_buffer(si16, {5}, {sizeof(int16_t)});
|
||||
});
|
||||
|
||||
|
@ -74,8 +74,9 @@ PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>);
|
||||
|
||||
template <typename PythonType>
|
||||
py::list test_random_access_iterator(PythonType x) {
|
||||
if (x.size() < 5)
|
||||
if (x.size() < 5) {
|
||||
throw py::value_error("Please provide at least 5 elements for testing.");
|
||||
}
|
||||
|
||||
auto checks = py::list();
|
||||
auto assert_equal = [&checks](py::handle a, py::handle b) {
|
||||
@ -125,8 +126,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
||||
.def(py::init<int>())
|
||||
.def("__getitem__", [](const Sliceable &s, const py::slice &slice) {
|
||||
py::ssize_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
if (!slice.compute(s.size, &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(s.size, &start, &stop, &step, &slicelength)) {
|
||||
throw py::error_already_set();
|
||||
}
|
||||
int istart = static_cast<int>(start);
|
||||
int istop = static_cast<int>(stop);
|
||||
int istep = static_cast<int>(step);
|
||||
@ -195,10 +197,14 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
||||
}
|
||||
|
||||
bool operator==(const Sequence &s) const {
|
||||
if (m_size != s.size()) return false;
|
||||
for (size_t i = 0; i < m_size; ++i)
|
||||
if (m_data[i] != s[i])
|
||||
if (m_size != s.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
if (m_data[i] != s[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator!=(const Sequence &s) const { return !operator==(s); }
|
||||
@ -207,16 +213,19 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
||||
float &operator[](size_t index) { return m_data[index]; }
|
||||
|
||||
bool contains(float v) const {
|
||||
for (size_t i = 0; i < m_size; ++i)
|
||||
if (v == m_data[i])
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
if (v == m_data[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Sequence reversed() const {
|
||||
Sequence result(m_size);
|
||||
for (size_t i = 0; i < m_size; ++i)
|
||||
for (size_t i = 0; i < m_size; ++i) {
|
||||
result[m_size - i - 1] = m_data[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -235,14 +244,16 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
||||
/// Bare bones interface
|
||||
.def("__getitem__",
|
||||
[](const Sequence &s, size_t i) {
|
||||
if (i >= s.size())
|
||||
if (i >= s.size()) {
|
||||
throw py::index_error();
|
||||
}
|
||||
return s[i];
|
||||
})
|
||||
.def("__setitem__",
|
||||
[](Sequence &s, size_t i, float v) {
|
||||
if (i >= s.size())
|
||||
if (i >= s.size()) {
|
||||
throw py::index_error();
|
||||
}
|
||||
s[i] = v;
|
||||
})
|
||||
.def("__len__", &Sequence::size)
|
||||
@ -257,8 +268,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
||||
.def("__getitem__",
|
||||
[](const Sequence &s, const py::slice &slice) -> Sequence * {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw py::error_already_set();
|
||||
}
|
||||
auto *seq = new Sequence(slicelength);
|
||||
for (size_t i = 0; i < slicelength; ++i) {
|
||||
(*seq)[i] = s[start];
|
||||
@ -269,11 +281,13 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
||||
.def("__setitem__",
|
||||
[](Sequence &s, const py::slice &slice, const Sequence &value) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw py::error_already_set();
|
||||
if (slicelength != value.size())
|
||||
}
|
||||
if (slicelength != value.size()) {
|
||||
throw std::runtime_error(
|
||||
"Left and right hand size of slice assignment have different sizes!");
|
||||
}
|
||||
for (size_t i = 0; i < slicelength; ++i) {
|
||||
s[start] = value[i];
|
||||
start += step;
|
||||
|
@ -113,8 +113,9 @@ public:
|
||||
static void cleanupAllInstances() {
|
||||
auto tmp = std::move(myobject4_instances);
|
||||
myobject4_instances.clear();
|
||||
for (auto o : tmp)
|
||||
for (auto o : tmp) {
|
||||
delete o;
|
||||
}
|
||||
}
|
||||
private:
|
||||
~MyObject4() {
|
||||
@ -140,8 +141,9 @@ public:
|
||||
static void cleanupAllInstances() {
|
||||
auto tmp = std::move(myobject4a_instances);
|
||||
myobject4a_instances.clear();
|
||||
for (auto o : tmp)
|
||||
for (auto o : tmp) {
|
||||
delete o;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual ~MyObject4a() {
|
||||
@ -445,8 +447,9 @@ TEST_SUBMODULE(smart_ptr, m) {
|
||||
.def("add", &ElementList::add)
|
||||
.def("get", [](ElementList &el) {
|
||||
py::list list;
|
||||
for (auto &e : el.l)
|
||||
for (auto &e : el.l) {
|
||||
list.append(py::cast(e));
|
||||
}
|
||||
return list;
|
||||
});
|
||||
}
|
||||
|
@ -42,23 +42,27 @@ public:
|
||||
|
||||
template <class Container> Container *one_to_n(int n) {
|
||||
auto v = new Container();
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int i = 1; i <= n; i++) {
|
||||
v->emplace_back(i);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class Map> Map *times_ten(int n) {
|
||||
auto m = new Map();
|
||||
for (int i = 1; i <= n; i++)
|
||||
m->emplace(int(i), E_nc(10*i));
|
||||
for (int i = 1; i <= n; i++) {
|
||||
m->emplace(int(i), E_nc(10 * i));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
template <class NestMap> NestMap *times_hundred(int n) {
|
||||
auto m = new NestMap();
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = 1; j <= n; j++)
|
||||
(*m)[i].emplace(int(j*10), E_nc(100*j));
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
(*m)[i].emplace(int(j * 10), E_nc(100 * j));
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -98,9 +102,11 @@ TEST_SUBMODULE(stl_binders, m) {
|
||||
m.def("get_nvnc", [](int n)
|
||||
{
|
||||
auto m = new std::map<int, std::vector<E_nc>>();
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = 1; j <= n; j++)
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
(*m)[i].emplace_back(j);
|
||||
}
|
||||
}
|
||||
return m;
|
||||
});
|
||||
py::bind_map<std::map<int, std::map<int, E_nc>>>(m, "MapMapENC");
|
||||
|
@ -100,8 +100,12 @@ const std::type_info* Animal::type_of_kind(Kind kind)
|
||||
case Kind::LastCat: break;
|
||||
}
|
||||
|
||||
if (kind >= Kind::Dog && kind <= Kind::LastDog) return &typeid(Dog);
|
||||
if (kind >= Kind::Cat && kind <= Kind::LastCat) return &typeid(Cat);
|
||||
if (kind >= Kind::Dog && kind <= Kind::LastDog) {
|
||||
return &typeid(Dog);
|
||||
}
|
||||
if (kind >= Kind::Cat && kind <= Kind::LastCat) {
|
||||
return &typeid(Cat);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,9 @@ public:
|
||||
void operator=(const NonCopyable &) = delete;
|
||||
void operator=(NonCopyable &&) = delete;
|
||||
std::string get_value() const {
|
||||
if (value)
|
||||
if (value) {
|
||||
return std::to_string(*value);
|
||||
}
|
||||
return "(null)";
|
||||
}
|
||||
~NonCopyable() { print_destroyed(this); }
|
||||
|
Loading…
Reference in New Issue
Block a user