Commit ddbc74c6 by Ralf W. Grosse-Kunstleve Committed by Ralf W. Grosse-Kunstleve

Adding .clang-tidy readability-braces-around-statements option.

clang-tidy automatic changes. NO manual changes.
parent 8581584e
...@@ -31,6 +31,7 @@ modernize-use-override, ...@@ -31,6 +31,7 @@ modernize-use-override,
modernize-use-using, modernize-use-using,
*performance*, *performance*,
readability-avoid-const-params-in-decls, readability-avoid-const-params-in-decls,
readability-braces-around-statements,
readability-const-return-type, readability-const-return-type,
readability-container-size-empty, readability-container-size-empty,
readability-delete-null-pointer, readability-delete-null-pointer,
......
...@@ -330,11 +330,13 @@ struct type_record { ...@@ -330,11 +330,13 @@ struct type_record {
bases.append((PyObject *) base_info->type); bases.append((PyObject *) base_info->type);
if (base_info->type->tp_dictoffset != 0) if (base_info->type->tp_dictoffset != 0) {
dynamic_attr = true; dynamic_attr = true;
}
if (caster) if (caster) {
base_info->implicit_casts.emplace_back(type, caster); base_info->implicit_casts.emplace_back(type, caster);
}
} }
}; };
...@@ -410,13 +412,16 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu ...@@ -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) { 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')) 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"); 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) { inline void append_self_arg_if_needed(function_record *r) {
if (r->is_method && r->args.empty()) if (r->is_method && r->args.empty()) {
r->args.emplace_back("self", nullptr, handle(), /*convert=*/ true, /*none=*/ false); r->args.emplace_back("self", nullptr, handle(), /*convert=*/true, /*none=*/false);
}
} }
/// Process a keyword argument attribute (*without* a default value) /// Process a keyword argument attribute (*without* a default value)
...@@ -432,8 +437,10 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> { ...@@ -432,8 +437,10 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
/// Process a keyword argument attribute (*with* a default value) /// Process a keyword argument attribute (*with* a default value)
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
static void init(const arg_v &a, function_record *r) { static void init(const arg_v &a, function_record *r) {
if (r->is_method && r->args.empty()) if (r->is_method && r->args.empty()) {
r->args.emplace_back("self", /*descr=*/ nullptr, /*parent=*/ handle(), /*convert=*/ true, /*none=*/ false); r->args.emplace_back(
"self", /*descr=*/nullptr, /*parent=*/handle(), /*convert=*/true, /*none=*/false);
}
if (!a.value) { if (!a.value) {
#if !defined(NDEBUG) #if !defined(NDEBUG)
...@@ -466,8 +473,10 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { ...@@ -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> { template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
static void init(const kw_only &, function_record *r) { static void init(const kw_only &, function_record *r) {
append_self_arg_if_needed(r); append_self_arg_if_needed(r);
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size())) 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)"); 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()); 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 ...@@ -477,8 +486,9 @@ template <> struct process_attribute<pos_only> : process_attribute_default<pos_o
static void init(const pos_only &, function_record *r) { static void init(const pos_only &, function_record *r) {
append_self_arg_if_needed(r); append_self_arg_if_needed(r);
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size()); 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"); 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 // 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) ...@@ -19,9 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) { inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
auto ndim = shape.size(); auto ndim = shape.size();
std::vector<ssize_t> strides(ndim, itemsize); std::vector<ssize_t> strides(ndim, itemsize);
if (ndim > 0) if (ndim > 0) {
for (size_t i = ndim - 1; i > 0; --i) for (size_t i = ndim - 1; i > 0; --i) {
strides[i - 1] = strides[i] * shape[i]; strides[i - 1] = strides[i] * shape[i];
}
}
return strides; return strides;
} }
...@@ -29,8 +31,9 @@ inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t ...@@ -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) { inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
auto ndim = shape.size(); auto ndim = shape.size();
std::vector<ssize_t> strides(ndim, itemsize); 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]; strides[i] = strides[i - 1] * shape[i - 1];
}
return strides; return strides;
} }
...@@ -53,10 +56,12 @@ struct buffer_info { ...@@ -53,10 +56,12 @@ struct buffer_info {
detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false) 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), : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) { 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"); 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]; size *= shape[i];
}
} }
template <typename T> template <typename T>
......
...@@ -46,7 +46,9 @@ public: ...@@ -46,7 +46,9 @@ public:
// Lazy initialise the PyDateTime import // Lazy initialise the PyDateTime import
if (!PyDateTimeAPI) { PyDateTime_IMPORT; } if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
if (!src) return false; if (!src) {
return false;
}
// If invoked with datetime.delta object // If invoked with datetime.delta object
if (PyDelta_Check(src.ptr())) { if (PyDelta_Check(src.ptr())) {
value = type(duration_cast<duration<rep, period>>( value = type(duration_cast<duration<rep, period>>(
...@@ -124,7 +126,9 @@ public: ...@@ -124,7 +126,9 @@ public:
// Lazy initialise the PyDateTime import // Lazy initialise the PyDateTime import
if (!PyDateTimeAPI) { PyDateTime_IMPORT; } if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
if (!src) return false; if (!src) {
return false;
}
std::tm cal; std::tm cal;
microseconds msecs; microseconds msecs;
...@@ -156,8 +160,9 @@ public: ...@@ -156,8 +160,9 @@ public:
cal.tm_year = 70; // earliest available date for Python's datetime cal.tm_year = 70; // earliest available date for Python's datetime
cal.tm_isdst = -1; cal.tm_isdst = -1;
msecs = microseconds(PyDateTime_TIME_GET_MICROSECOND(src.ptr())); 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); value = time_point_cast<Duration>(system_clock::from_time_t(std::mktime(&cal)) + msecs);
return true; return true;
...@@ -173,8 +178,9 @@ public: ...@@ -173,8 +178,9 @@ public:
// (cfr. https://github.com/pybind/pybind11/issues/2417) // (cfr. https://github.com/pybind/pybind11/issues/2417)
using us_t = duration<int, std::micro>; using us_t = duration<int, std::micro>;
auto us = duration_cast<us_t>(src.time_since_epoch() % seconds(1)); auto us = duration_cast<us_t>(src.time_since_epoch() % seconds(1));
if (us.count() < 0) if (us.count() < 0) {
us += seconds(1); us += seconds(1);
}
// Subtract microseconds BEFORE `system_clock::to_time_t`, because: // 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. // > If std::time_t has lower precision, it is implementation-defined whether the value is rounded or truncated.
...@@ -183,8 +189,9 @@ public: ...@@ -183,8 +189,9 @@ public:
std::tm localtime; std::tm localtime;
std::tm *localtime_ptr = localtime_thread_safe(&tt, &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"); throw cast_error("Unable to represent system_clock in local time");
}
return PyDateTime_FromDateAndTime(localtime.tm_year + 1900, return PyDateTime_FromDateAndTime(localtime.tm_year + 1900,
localtime.tm_mon + 1, localtime.tm_mon + 1,
localtime.tm_mday, localtime.tm_mday,
......
...@@ -42,10 +42,12 @@ template <typename T> struct is_fmt_numeric<std::complex<T>, detail::enable_if_t ...@@ -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>> { template <typename T> class type_caster<std::complex<T>> {
public: public:
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!src) if (!src) {
return false; return false;
if (!convert && !PyComplex_Check(src.ptr())) }
if (!convert && !PyComplex_Check(src.ptr())) {
return false; return false;
}
Py_complex result = PyComplex_AsCComplex(src.ptr()); Py_complex result = PyComplex_AsCComplex(src.ptr());
if (result.real == -1.0 && PyErr_Occurred()) { if (result.real == -1.0 && PyErr_Occurred()) {
PyErr_Clear(); PyErr_Clear();
......
...@@ -33,7 +33,9 @@ private: ...@@ -33,7 +33,9 @@ private:
PYBIND11_NAMESPACE_BEGIN(initimpl) PYBIND11_NAMESPACE_BEGIN(initimpl)
inline void no_nullptr(void *ptr) { 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(...) // 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) { ...@@ -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); auto *ptr = holder_helper<Holder<Class>>::get(holder);
no_nullptr(ptr); no_nullptr(ptr);
// If we need an alias, check that the held pointer is actually an alias instance // 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 " throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
"is not an alias instance"); "is not an alias instance");
}
v_h.value_ptr() = ptr; v_h.value_ptr() = ptr;
v_h.type->init_instance(v_h.inst, &holder); 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) { ...@@ -153,10 +156,11 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias); PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
static_assert(std::is_move_constructible<Cpp<Class>>::value, static_assert(std::is_move_constructible<Cpp<Class>>::value,
"pybind11::init() return-by-value factory function requires a movable class"); "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)); 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)); 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 // return-by-value version 2: returning a value of the alias type itself. We move-construct an
...@@ -183,12 +187,19 @@ struct constructor { ...@@ -183,12 +187,19 @@ struct constructor {
enable_if_t<Class::has_alias && enable_if_t<Class::has_alias &&
std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> std::is_constructible<Cpp<Class>, Args...>::value, int> = 0>
static void execute(Class &cl, const Extra&... extra) { static void execute(Class &cl, const Extra&... extra) {
cl.def("__init__", [](value_and_holder &v_h, Args... args) { cl.def(
if (Py_TYPE(v_h.inst) == v_h.type->type) "__init__",
v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...); [](value_and_holder &v_h, Args... args) {
else if (Py_TYPE(v_h.inst) == v_h.type->type) {
v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); v_h.value_ptr()
}, is_new_style_constructor(), extra...); = 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, template <typename Class, typename... Extra,
......
...@@ -398,8 +398,9 @@ inline void translate_local_exception(std::exception_ptr p) { ...@@ -398,8 +398,9 @@ inline void translate_local_exception(std::exception_ptr p) {
/// Return a reference to the current `internals` data /// Return a reference to the current `internals` data
PYBIND11_NOINLINE internals &get_internals() { PYBIND11_NOINLINE internals &get_internals() {
auto **&internals_pp = get_internals_pp(); auto **&internals_pp = get_internals_pp();
if (internals_pp && *internals_pp) if (internals_pp && *internals_pp) {
return **internals_pp; return **internals_pp;
}
// Ensure that the GIL is held since we will need to make Python calls. // 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. // Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
...@@ -425,7 +426,9 @@ PYBIND11_NOINLINE internals &get_internals() { ...@@ -425,7 +426,9 @@ PYBIND11_NOINLINE internals &get_internals() {
(*internals_pp)->registered_exception_translators.push_front(&translate_local_exception); (*internals_pp)->registered_exception_translators.push_front(&translate_local_exception);
#endif #endif
} else { } else {
if (!internals_pp) internals_pp = new internals*(); if (!internals_pp) {
internals_pp = new internals *();
}
auto *&internals_ptr = *internals_pp; auto *&internals_ptr = *internals_pp;
internals_ptr = new internals(); internals_ptr = new internals();
#if defined(WITH_THREAD) #if defined(WITH_THREAD)
......
...@@ -24,7 +24,9 @@ PYBIND11_NAMESPACE_BEGIN(detail) ...@@ -24,7 +24,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline void erase_all(std::string &string, const std::string &search) { inline void erase_all(std::string &string, const std::string &search) {
for (size_t pos = 0;;) { for (size_t pos = 0;;) {
pos = string.find(search, pos); pos = string.find(search, pos);
if (pos == std::string::npos) break; if (pos == std::string::npos) {
break;
}
string.erase(pos, search.length()); string.erase(pos, search.length());
} }
} }
...@@ -34,8 +36,9 @@ PYBIND11_NOINLINE void clean_type_id(std::string &name) { ...@@ -34,8 +36,9 @@ PYBIND11_NOINLINE void clean_type_id(std::string &name) {
int status = 0; int status = 0;
std::unique_ptr<char, void (*)(void *)> res { std::unique_ptr<char, void (*)(void *)> res {
abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free }; abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free };
if (status == 0) if (status == 0) {
name = res.get(); name = res.get();
}
#else #else
detail::erase_all(name, "class "); detail::erase_all(name, "class ");
detail::erase_all(name, "struct "); detail::erase_all(name, "struct ");
......
...@@ -145,8 +145,9 @@ template <typename Type_> struct EigenProps { ...@@ -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). // (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) { static EigenConformable<row_major> conformable(const array &a) {
const auto dims = a.ndim(); const auto dims = a.ndim();
if (dims < 1 || dims > 2) if (dims < 1 || dims > 2) {
return false; return false;
}
if (dims == 2) { // Matrix type: require exact match (or dynamic) if (dims == 2) { // Matrix type: require exact match (or dynamic)
...@@ -155,9 +156,10 @@ template <typename Type_> struct EigenProps { ...@@ -155,9 +156,10 @@ template <typename Type_> struct EigenProps {
np_cols = a.shape(1), np_cols = a.shape(1),
np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)), np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
np_cstride = a.strides(1) / 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) || if ((PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && np_rows != rows)
(PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) || (PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) {
return false; return false;
}
return {np_rows, np_cols, np_rstride, np_cstride}; return {np_rows, np_cols, np_rstride, np_cstride};
} }
...@@ -168,8 +170,9 @@ template <typename Type_> struct EigenProps { ...@@ -168,8 +170,9 @@ template <typename Type_> struct EigenProps {
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)); stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
if (vector) { // Eigen type is a compile-time vector 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 false; // Vector size mismatch
}
return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride}; return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
} }
if (fixed) { if (fixed) {
...@@ -179,10 +182,14 @@ template <typename Type_> struct EigenProps { ...@@ -179,10 +182,14 @@ template <typename Type_> struct EigenProps {
if (fixed_cols) { if (fixed_cols) {
// Since this isn't a vector, cols must be != 1. We allow this only if it exactly // 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). // 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}; return {1, n, stride};
} // Otherwise it's either fully dynamic, or column dynamic; both become a column vector } // 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}; return {n, 1, stride};
} }
...@@ -213,14 +220,18 @@ template <typename Type_> struct EigenProps { ...@@ -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) { 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); constexpr ssize_t elem_size = sizeof(typename props::Scalar);
array a; array a;
if (props::vector) if (props::vector) {
a = array({ src.size() }, { elem_size * src.innerStride() }, src.data(), base); a = array({ src.size() }, { elem_size * src.innerStride() }, src.data(), base);
else } else {
a = array({ src.rows(), src.cols() }, { elem_size * src.rowStride(), elem_size * src.colStride() }, a = array({src.rows(), src.cols()},
src.data(), base); {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_; array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
}
return a.release(); return a.release();
} }
...@@ -255,28 +266,35 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> { ...@@ -255,28 +266,35 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
// If we're in no-convert mode, only load if given an array of the correct type // 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; return false;
}
// Coerce into an array, but don't do type conversion yet; the copy below handles it. // Coerce into an array, but don't do type conversion yet; the copy below handles it.
auto buf = array::ensure(src); auto buf = array::ensure(src);
if (!buf) if (!buf) {
return false; return false;
}
auto dims = buf.ndim(); auto dims = buf.ndim();
if (dims < 1 || dims > 2) if (dims < 1 || dims > 2) {
return false; return false;
}
auto fits = props::conformable(buf); auto fits = props::conformable(buf);
if (!fits) if (!fits) {
return false; return false;
}
// Allocate the new type, then build a numpy reference into it // Allocate the new type, then build a numpy reference into it
value = Type(fits.rows, fits.cols); value = Type(fits.rows, fits.cols);
auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value)); auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value));
if (dims == 1) ref = ref.squeeze(); if (dims == 1) {
else if (ref.ndim() == 1) buf = buf.squeeze(); ref = ref.squeeze();
} else if (ref.ndim() == 1) {
buf = buf.squeeze();
}
int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr()); int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr());
...@@ -323,14 +341,18 @@ public: ...@@ -323,14 +341,18 @@ public:
} }
// lvalue reference return; default (automatic) becomes copy // lvalue reference return; default (automatic) becomes copy
static handle cast(Type &src, return_value_policy policy, handle parent) { 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; policy = return_value_policy::copy;
}
return cast_impl(&src, policy, parent); return cast_impl(&src, policy, parent);
} }
// const lvalue reference return; default (automatic) becomes copy // const lvalue reference return; default (automatic) becomes copy
static handle cast(const Type &src, return_value_policy policy, handle parent) { 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; policy = return_value_policy::copy;
}
return cast(&src, policy, parent); return cast(&src, policy, parent);
} }
// non-const pointer return // non-const pointer return
...@@ -439,11 +461,14 @@ public: ...@@ -439,11 +461,14 @@ public:
if (aref && (!need_writeable || aref.writeable())) { if (aref && (!need_writeable || aref.writeable())) {
fits = props::conformable(aref); fits = props::conformable(aref);
if (!fits) return false; // Incompatible dimensions if (!fits) {
if (!fits.template stride_compatible<props>()) return false; // Incompatible dimensions
}
if (!fits.template stride_compatible<props>()) {
need_copy = true; need_copy = true;
else } else {
copy_or_ref = std::move(aref); copy_or_ref = std::move(aref);
}
} }
else { else {
need_copy = true; need_copy = true;
...@@ -454,13 +479,18 @@ public: ...@@ -454,13 +479,18 @@ public:
// We need to copy: If we need a mutable reference, or we're not supposed to convert // 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 // (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. // 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); Array copy = Array::ensure(src);
if (!copy) return false; if (!copy) {
return false;
}
fits = props::conformable(copy); fits = props::conformable(copy);
if (!fits || !fits.template stride_compatible<props>()) if (!fits || !fits.template stride_compatible<props>()) {
return false; return false;
}
copy_or_ref = std::move(copy); copy_or_ref = std::move(copy);
loader_life_support::add_patient(copy_or_ref); loader_life_support::add_patient(copy_or_ref);
} }
...@@ -550,8 +580,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { ...@@ -550,8 +580,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
static constexpr bool rowMajor = Type::IsRowMajor; static constexpr bool rowMajor = Type::IsRowMajor;
bool load(handle src, bool) { bool load(handle src, bool) {
if (!src) if (!src) {
return false; return false;
}
auto obj = reinterpret_borrow<object>(src); auto obj = reinterpret_borrow<object>(src);
object sparse_module = module_::import("scipy.sparse"); object sparse_module = module_::import("scipy.sparse");
...@@ -572,8 +603,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { ...@@ -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 shape = pybind11::tuple((pybind11::object) obj.attr("shape"));
auto nnz = obj.attr("nnz").cast<Index>(); auto nnz = obj.attr("nnz").cast<Index>();
if (!values || !innerIndices || !outerIndices) if (!values || !innerIndices || !outerIndices) {
return false; return false;
}
value = EigenMapSparseMatrix<Scalar, value = EigenMapSparseMatrix<Scalar,
Type::Flags & (Eigen::RowMajor | Eigen::ColMajor), Type::Flags & (Eigen::RowMajor | Eigen::ColMajor),
......
...@@ -77,12 +77,14 @@ struct embedded_module { ...@@ -77,12 +77,14 @@ struct embedded_module {
using init_t = void (*)(); using init_t = void (*)();
#endif #endif
embedded_module(const char *name, init_t init) { 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"); pybind11_fail("Can't add new modules after the interpreter has been initialized");
}
auto result = PyImport_AppendInittab(name, init); auto result = PyImport_AppendInittab(name, init);
if (result == -1) if (result == -1) {
pybind11_fail("Insufficient memory to add a new module"); 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 ...@@ -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 empty_argv[]{"\0"};
const char *const *safe_argv = special_case ? empty_argv : argv; const char *const *safe_argv = special_case ? empty_argv : argv;
if (special_case) if (special_case) {
argc = 1; argc = 1;
}
auto argv_size = static_cast<size_t>(argc); auto argv_size = static_cast<size_t>(argc);
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
...@@ -192,8 +195,9 @@ inline void initialize_interpreter(bool init_signal_handlers = true, ...@@ -192,8 +195,9 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
int argc = 0, int argc = 0,
const char *const *argv = nullptr, const char *const *argv = nullptr,
bool add_program_dir_to_path = true) { bool add_program_dir_to_path = true) {
if (Py_IsInitialized() != 0) if (Py_IsInitialized() != 0) {
pybind11_fail("The interpreter is already running"); pybind11_fail("The interpreter is already running");
}
Py_InitializeEx(init_signal_handlers ? 1 : 0); Py_InitializeEx(init_signal_handlers ? 1 : 0);
...@@ -244,8 +248,9 @@ inline void finalize_interpreter() { ...@@ -244,8 +248,9 @@ inline void finalize_interpreter() {
// during destruction), so we get the pointer-pointer here and check it after Py_Finalize(). // during destruction), so we get the pointer-pointer here and check it after Py_Finalize().
detail::internals **internals_ptr_ptr = detail::get_internals_pp(); detail::internals **internals_ptr_ptr = detail::get_internals_pp();
// It could also be stashed in builtins, so look there too: // 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]); internals_ptr_ptr = capsule(builtins[id]);
}
Py_Finalize(); Py_Finalize();
...@@ -285,8 +290,9 @@ public: ...@@ -285,8 +290,9 @@ public:
scoped_interpreter &operator=(scoped_interpreter &&) = delete; scoped_interpreter &operator=(scoped_interpreter &&) = delete;
~scoped_interpreter() { ~scoped_interpreter() {
if (is_valid) if (is_valid) {
finalize_interpreter(); finalize_interpreter();
}
} }
private: private:
......
...@@ -46,8 +46,9 @@ enum eval_mode { ...@@ -46,8 +46,9 @@ enum eval_mode {
template <eval_mode mode = eval_expr> template <eval_mode mode = eval_expr>
object eval(const str &expr, object global = globals(), object local = object()) { object eval(const str &expr, object global = globals(), object local = object()) {
if (!local) if (!local) {
local = global; local = global;
}
detail::ensure_builtins_in_globals(global); detail::ensure_builtins_in_globals(global);
...@@ -64,8 +65,9 @@ object eval(const str &expr, object global = globals(), object local = object()) ...@@ -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()); PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
if (!result) if (!result) {
throw error_already_set(); throw error_already_set();
}
return reinterpret_steal<object>(result); return reinterpret_steal<object>(result);
} }
...@@ -102,8 +104,9 @@ object eval_file(str) { ...@@ -102,8 +104,9 @@ object eval_file(str) {
#else #else
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str fname, object global = globals(), object local = object()) { object eval_file(str fname, object global = globals(), object local = object()) {
if (!local) if (!local) {
local = global; local = global;
}
detail::ensure_builtins_in_globals(global); detail::ensure_builtins_in_globals(global);
...@@ -154,8 +157,9 @@ object eval_file(str fname, object global = globals(), object local = object()) ...@@ -154,8 +157,9 @@ object eval_file(str fname, object global = globals(), object local = object())
local.ptr(), closeFile); local.ptr(), closeFile);
#endif #endif
if (!result) if (!result) {
throw error_already_set(); throw error_already_set();
}
return reinterpret_steal<object>(result); return reinterpret_steal<object>(result);
} }
#endif #endif
......
...@@ -25,12 +25,15 @@ public: ...@@ -25,12 +25,15 @@ public:
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (src.is_none()) { if (src.is_none()) {
// Defer accepting None to other overloads (if we aren't in convert mode): // Defer accepting None to other overloads (if we aren't in convert mode):
if (!convert) return false; if (!convert) {
return false;
}
return true; return true;
} }
if (!isinstance<function>(src)) if (!isinstance<function>(src)) {
return false; return false;
}
auto func = reinterpret_borrow<function>(src); auto func = reinterpret_borrow<function>(src);
...@@ -104,12 +107,14 @@ public: ...@@ -104,12 +107,14 @@ public:
template <typename Func> template <typename Func>
static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) { static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
if (!f_) if (!f_) {
return none().inc_ref(); return none().inc_ref();
}
auto result = f_.template target<function_type>(); auto result = f_.template target<function_type>();
if (result) if (result) {
return cpp_function(*result, policy).release(); return cpp_function(*result, policy).release();
}
return cpp_function(std::forward<Func>(f_), policy).release(); return cpp_function(std::forward<Func>(f_), policy).release();
} }
......
...@@ -99,8 +99,9 @@ public: ...@@ -99,8 +99,9 @@ public:
pybind11_fail("scoped_acquire::dec_ref(): internal error!"); pybind11_fail("scoped_acquire::dec_ref(): internal error!");
#endif #endif
PyThreadState_Clear(tstate); PyThreadState_Clear(tstate);
if (active) if (active) {
PyThreadState_DeleteCurrent(); PyThreadState_DeleteCurrent();
}
PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate); PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate);
release = false; release = false;
} }
...@@ -117,8 +118,9 @@ public: ...@@ -117,8 +118,9 @@ public:
PYBIND11_NOINLINE ~gil_scoped_acquire() { PYBIND11_NOINLINE ~gil_scoped_acquire() {
dec_ref(); dec_ref();
if (release) if (release) {
PyEval_SaveThread(); PyEval_SaveThread();
}
} }
private: private:
PyThreadState *tstate = nullptr; PyThreadState *tstate = nullptr;
...@@ -150,11 +152,13 @@ public: ...@@ -150,11 +152,13 @@ public:
} }
~gil_scoped_release() { ~gil_scoped_release() {
if (!tstate) if (!tstate) {
return; return;
}
// `PyEval_RestoreThread()` should not be called if runtime is finalizing // `PyEval_RestoreThread()` should not be called if runtime is finalizing
if (active) if (active) {
PyEval_RestoreThread(tstate); PyEval_RestoreThread(tstate);
}
if (disassoc) { if (disassoc) {
auto key = detail::get_internals().tstate; auto key = detail::get_internals().tstate;
PYBIND11_TLS_REPLACE_VALUE(key, tstate); PYBIND11_TLS_REPLACE_VALUE(key, tstate);
......
...@@ -71,23 +71,26 @@ private: ...@@ -71,23 +71,26 @@ private:
return static_cast<unsigned char>(c) <= 0xEF; return static_cast<unsigned char>(c) <= 0xEF;
}; };
// If the last character is ASCII, there are no incomplete code points // If the last character is ASCII, there are no incomplete code points
if (is_ascii(*rpptr)) if (is_ascii(*rpptr)) {
return 0; return 0;
}
// Otherwise, work back from the end of the buffer and find the first // Otherwise, work back from the end of the buffer and find the first
// UTF-8 leading byte // UTF-8 leading byte
const auto rpend = rbase - rpptr >= 3 ? rpptr + 3 : rbase; const auto rpend = rbase - rpptr >= 3 ? rpptr + 3 : rbase;
const auto leading = std::find_if(rpptr, rpend, is_leading); const auto leading = std::find_if(rpptr, rpend, is_leading);
if (leading == rbase) if (leading == rbase) {
return 0; return 0;
}
const auto dist = static_cast<size_t>(leading - rpptr); const auto dist = static_cast<size_t>(leading - rpptr);
size_t remainder = 0; size_t remainder = 0;
if (dist == 0) if (dist == 0) {
remainder = 1; // 1-byte code point is impossible remainder = 1; // 1-byte code point is impossible
else if (dist == 1) } else if (dist == 1) {
remainder = is_leading_2b(*leading) ? 0 : 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; remainder = is_leading_3b(*leading) ? 0 : dist + 1;
}
// else if (dist >= 3), at least 4 bytes before encountering an UTF-8 // else if (dist >= 3), at least 4 bytes before encountering an UTF-8
// leading byte, either no remainder or invalid UTF-8. // leading byte, either no remainder or invalid UTF-8.
// Invalid UTF-8 will cause an exception later when converting // Invalid UTF-8 will cause an exception later when converting
...@@ -110,8 +113,9 @@ private: ...@@ -110,8 +113,9 @@ private:
} }
// Copy the remainder at the end of the buffer to the beginning: // Copy the remainder at the end of the buffer to the beginning:
if (remainder > 0) if (remainder > 0) {
std::memmove(pbase(), pptr() - remainder, remainder); std::memmove(pbase(), pptr() - remainder, remainder);
}
setp(pbase(), epptr()); setp(pbase(), epptr());
pbump(static_cast<int>(remainder)); pbump(static_cast<int>(remainder));
} }
...@@ -223,10 +227,12 @@ public: ...@@ -223,10 +227,12 @@ public:
: do_stdout_(do_stdout), do_stderr_(do_stderr) {} : do_stdout_(do_stdout), do_stderr_(do_stderr) {}
void enter() { void enter() {
if (do_stdout_) if (do_stdout_) {
redirect_stdout.reset(new scoped_ostream_redirect()); redirect_stdout.reset(new scoped_ostream_redirect());
if (do_stderr_) }
if (do_stderr_) {
redirect_stderr.reset(new scoped_estream_redirect()); redirect_stderr.reset(new scoped_estream_redirect());
}
} }
void exit() { void exit() {
......
...@@ -52,14 +52,16 @@ template <typename Type, typename Key> struct set_caster { ...@@ -52,14 +52,16 @@ template <typename Type, typename Key> struct set_caster {
using key_conv = make_caster<Key>; using key_conv = make_caster<Key>;
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<pybind11::set>(src)) if (!isinstance<pybind11::set>(src)) {
return false; return false;
}
auto s = reinterpret_borrow<pybind11::set>(src); auto s = reinterpret_borrow<pybind11::set>(src);
value.clear(); value.clear();
for (auto entry : s) { for (auto entry : s) {
key_conv conv; key_conv conv;
if (!conv.load(entry, convert)) if (!conv.load(entry, convert)) {
return false; return false;
}
value.insert(cast_op<Key &&>(std::move(conv))); value.insert(cast_op<Key &&>(std::move(conv)));
} }
return true; return true;
...@@ -67,13 +69,15 @@ template <typename Type, typename Key> struct set_caster { ...@@ -67,13 +69,15 @@ template <typename Type, typename Key> struct set_caster {
template <typename T> template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) { 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); policy = return_value_policy_override<Key>::policy(policy);
}
pybind11::set s; pybind11::set s;
for (auto &&value : src) { for (auto &&value : src) {
auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent)); 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 handle();
}
} }
return s.release(); return s.release();
} }
...@@ -86,16 +90,17 @@ template <typename Type, typename Key, typename Value> struct map_caster { ...@@ -86,16 +90,17 @@ template <typename Type, typename Key, typename Value> struct map_caster {
using value_conv = make_caster<Value>; using value_conv = make_caster<Value>;
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<dict>(src)) if (!isinstance<dict>(src)) {
return false; return false;
}
auto d = reinterpret_borrow<dict>(src); auto d = reinterpret_borrow<dict>(src);
value.clear(); value.clear();
for (auto it : d) { for (auto it : d) {
key_conv kconv; key_conv kconv;
value_conv vconv; value_conv vconv;
if (!kconv.load(it.first.ptr(), convert) || if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
!vconv.load(it.second.ptr(), convert))
return false; return false;
}
value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv))); value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
} }
return true; return true;
...@@ -113,8 +118,9 @@ template <typename Type, typename Key, typename Value> struct map_caster { ...@@ -113,8 +118,9 @@ template <typename Type, typename Key, typename Value> struct map_caster {
for (auto &&kv : src) { for (auto &&kv : src) {
auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent)); 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)); auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
if (!key || !value) if (!key || !value) {
return handle(); return handle();
}
d[key] = value; d[key] = value;
} }
return d.release(); return d.release();
...@@ -127,15 +133,17 @@ template <typename Type, typename Value> struct list_caster { ...@@ -127,15 +133,17 @@ template <typename Type, typename Value> struct list_caster {
using value_conv = make_caster<Value>; using value_conv = make_caster<Value>;
bool load(handle src, bool convert) { 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; return false;
}
auto s = reinterpret_borrow<sequence>(src); auto s = reinterpret_borrow<sequence>(src);
value.clear(); value.clear();
reserve_maybe(s, &value); reserve_maybe(s, &value);
for (auto it : s) { for (auto it : s) {
value_conv conv; value_conv conv;
if (!conv.load(it, convert)) if (!conv.load(it, convert)) {
return false; return false;
}
value.push_back(cast_op<Value &&>(std::move(conv))); value.push_back(cast_op<Value &&>(std::move(conv)));
} }
return true; return true;
...@@ -153,14 +161,16 @@ private: ...@@ -153,14 +161,16 @@ private:
public: public:
template <typename T> template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) { 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); policy = return_value_policy_override<Value>::policy(policy);
}
list l(src.size()); list l(src.size());
ssize_t index = 0; ssize_t index = 0;
for (auto &&value : src) { for (auto &&value : src) {
auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
if (!value_) if (!value_) {
return handle(); return handle();
}
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
} }
return l.release(); return l.release();
...@@ -184,8 +194,9 @@ template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> s ...@@ -184,8 +194,9 @@ template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> s
private: private:
template <bool R = Resizable> template <bool R = Resizable>
bool require_size(enable_if_t<R, size_t> size) { bool require_size(enable_if_t<R, size_t> size) {
if (value.size() != size) if (value.size() != size) {
value.resize(size); value.resize(size);
}
return true; return true;
} }
template <bool R = Resizable> template <bool R = Resizable>
...@@ -195,16 +206,19 @@ private: ...@@ -195,16 +206,19 @@ private:
public: public:
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<sequence>(src)) if (!isinstance<sequence>(src)) {
return false; return false;
}
auto l = reinterpret_borrow<sequence>(src); auto l = reinterpret_borrow<sequence>(src);
if (!require_size(l.size())) if (!require_size(l.size())) {
return false; return false;
}
size_t ctr = 0; size_t ctr = 0;
for (auto it : l) { for (auto it : l) {
value_conv conv; value_conv conv;
if (!conv.load(it, convert)) if (!conv.load(it, convert)) {
return false; return false;
}
value[ctr++] = cast_op<Value &&>(std::move(conv)); value[ctr++] = cast_op<Value &&>(std::move(conv));
} }
return true; return true;
...@@ -216,8 +230,9 @@ public: ...@@ -216,8 +230,9 @@ public:
ssize_t index = 0; ssize_t index = 0;
for (auto &&value : src) { for (auto &&value : src) {
auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
if (!value_) if (!value_) {
return handle(); return handle();
}
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
} }
return l.release(); return l.release();
...@@ -250,8 +265,9 @@ template<typename Type, typename Value = typename Type::value_type> struct optio ...@@ -250,8 +265,9 @@ template<typename Type, typename Value = typename Type::value_type> struct optio
template <typename T> template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) { static handle cast(T &&src, return_value_policy policy, handle parent) {
if (!src) if (!src) {
return none().inc_ref(); return none().inc_ref();
}
if (!std::is_lvalue_reference<T>::value) { if (!std::is_lvalue_reference<T>::value) {
policy = return_value_policy_override<Value>::policy(policy); policy = return_value_policy_override<Value>::policy(policy);
} }
...@@ -266,8 +282,9 @@ template<typename Type, typename Value = typename Type::value_type> struct optio ...@@ -266,8 +282,9 @@ template<typename Type, typename Value = typename Type::value_type> struct optio
return true; // default-constructed value is already empty return true; // default-constructed value is already empty
} }
value_conv inner_caster; value_conv inner_caster;
if (!inner_caster.load(src, convert)) if (!inner_caster.load(src, convert)) {
return false; return false;
}
value.emplace(cast_op<Value &&>(std::move(inner_caster))); value.emplace(cast_op<Value &&>(std::move(inner_caster)));
return true; return true;
...@@ -341,8 +358,9 @@ struct variant_caster<V<Ts...>> { ...@@ -341,8 +358,9 @@ struct variant_caster<V<Ts...>> {
// E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int` // 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 // slot of the variant. Without two-pass loading `double` would be filled
// because it appears first and a conversion is possible. // 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 true;
}
return load_alternative(src, convert, type_list<Ts...>{}); 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_> ...@@ -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) { cl.def("remove", [](Vector &v, const T &x) {
auto p = std::find(v.begin(), v.end(), x); auto p = std::find(v.begin(), v.end(), x);
if (p != v.end()) if (p != v.end()) {
v.erase(p); v.erase(p);
else } else {
throw value_error(); throw value_error();
}
}, },
arg("x"), arg("x"),
"Remove the first item from the list whose value is 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 ...@@ -116,10 +117,12 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
using DiffType = typename Vector::difference_type; using DiffType = typename Vector::difference_type;
auto wrap_i = [](DiffType i, SizeType n) { auto wrap_i = [](DiffType i, SizeType n) {
if (i < 0) if (i < 0) {
i += n; i += n;
if (i < 0 || (SizeType)i >= n) }
if (i < 0 || (SizeType) i >= n) {
throw index_error(); throw index_error();
}
return i; return i;
}; };
...@@ -131,8 +134,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t ...@@ -131,8 +134,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
cl.def(init([](const iterable &it) { cl.def(init([](const iterable &it) {
auto v = std::unique_ptr<Vector>(new Vector()); auto v = std::unique_ptr<Vector>(new Vector());
v->reserve(len_hint(it)); v->reserve(len_hint(it));
for (handle h : it) for (handle h : it) {
v->push_back(h.cast<T>()); v->push_back(h.cast<T>());
}
return v.release(); return v.release();
})); }));
...@@ -177,26 +181,29 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t ...@@ -177,26 +181,29 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
cl.def("insert", cl.def("insert",
[](Vector &v, DiffType i, const T &x) { [](Vector &v, DiffType i, const T &x) {
// Can't use wrap_i; i == v.size() is OK // Can't use wrap_i; i == v.size() is OK
if (i < 0) if (i < 0) {
i += v.size(); i += v.size();
if (i < 0 || (SizeType)i > v.size()) }
if (i < 0 || (SizeType) i > v.size()) {
throw index_error(); throw index_error();
}
v.insert(v.begin() + i, x); v.insert(v.begin() + i, x);
}, },
arg("i") , arg("x"), arg("i") , arg("x"),
"Insert an item at a given position." "Insert an item at a given position."
); );
cl.def("pop", cl.def(
"pop",
[](Vector &v) { [](Vector &v) {
if (v.empty()) if (v.empty()) {
throw index_error(); throw index_error();
}
T t = std::move(v.back()); T t = std::move(v.back());
v.pop_back(); v.pop_back();
return t; return t;
}, },
"Remove and return the last item" "Remove and return the last item");
);
cl.def("pop", cl.def("pop",
[wrap_i](Vector &v, DiffType i) { [wrap_i](Vector &v, DiffType i) {
...@@ -222,8 +229,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t ...@@ -222,8 +229,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
[](const Vector &v, slice slice) -> Vector * { [](const Vector &v, slice slice) -> Vector * {
size_t start = 0, stop = 0, step = 0, slicelength = 0; 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(); throw error_already_set();
}
auto *seq = new Vector(); auto *seq = new Vector();
seq->reserve((size_t) slicelength); seq->reserve((size_t) slicelength);
...@@ -241,11 +249,14 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t ...@@ -241,11 +249,14 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
"__setitem__", "__setitem__",
[](Vector &v, slice slice, const Vector &value) { [](Vector &v, slice slice, const Vector &value) {
size_t start = 0, stop = 0, step = 0, slicelength = 0; 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(); throw 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!"); throw std::runtime_error(
"Left and right hand size of slice assignment have different sizes!");
}
for (size_t i=0; i<slicelength; ++i) { for (size_t i=0; i<slicelength; ++i) {
v[start] = value[i]; v[start] = value[i];
...@@ -267,8 +278,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t ...@@ -267,8 +278,9 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
[](Vector &v, slice slice) { [](Vector &v, slice slice) {
size_t start = 0, stop = 0, step = 0, slicelength = 0; 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(); throw error_already_set();
}
if (step == 1 && false) { if (step == 1 && false) {
v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength)); 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) ...@@ -296,10 +308,12 @@ void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl)
using ItType = typename Vector::iterator; using ItType = typename Vector::iterator;
auto wrap_i = [](DiffType i, SizeType n) { auto wrap_i = [](DiffType i, SizeType n) {
if (i < 0) if (i < 0) {
i += n; i += n;
if (i < 0 || (SizeType)i >= n) }
if (i < 0 || (SizeType) i >= n) {
throw index_error(); throw index_error();
}
return i; return i;
}; };
...@@ -328,15 +342,15 @@ void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) ...@@ -328,15 +342,15 @@ void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl)
using SizeType = typename Vector::size_type; using SizeType = typename Vector::size_type;
using DiffType = typename Vector::difference_type; using DiffType = typename Vector::difference_type;
using ItType = typename Vector::iterator; using ItType = typename Vector::iterator;
cl.def("__getitem__", cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
[](const Vector &v, DiffType i) -> T { if (i < 0 && (i += v.size()) < 0) {
if (i < 0 && (i += v.size()) < 0) throw index_error();
throw index_error();
if ((SizeType)i >= v.size())
throw index_error();
return v[(SizeType)i];
} }
); if ((SizeType) i >= v.size()) {
throw index_error();
}
return v[(SizeType) i];
});
cl.def("__iter__", cl.def("__iter__",
[](Vector &v) { [](Vector &v) {
...@@ -358,8 +372,9 @@ template <typename Vector, typename Class_> auto vector_if_insertion_operator(Cl ...@@ -358,8 +372,9 @@ template <typename Vector, typename Class_> auto vector_if_insertion_operator(Cl
s << name << '['; s << name << '[';
for (size_type i=0; i < v.size(); ++i) { for (size_type i=0; i < v.size(); ++i) {
s << v[i]; s << v[i];
if (i != v.size() - 1) if (i != v.size() - 1) {
s << ", "; s << ", ";
}
} }
s << ']'; s << ']';
return s.str(); return s.str();
...@@ -402,10 +417,14 @@ void vector_buffer_impl(Class_& cl, std::true_type) { ...@@ -402,10 +417,14 @@ void vector_buffer_impl(Class_& cl, std::true_type) {
cl.def(init([](const buffer &buf) { cl.def(init([](const buffer &buf) {
auto info = buf.request(); 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"); 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); T *p = static_cast<T*>(info.ptr);
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T)); 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) { ...@@ -415,8 +434,9 @@ void vector_buffer_impl(Class_& cl, std::true_type) {
} }
Vector vec; Vector vec;
vec.reserve((size_t) info.shape[0]); vec.reserve((size_t) info.shape[0]);
for (; p != end; p += step) for (; p != end; p += step) {
vec.push_back(*p); vec.push_back(*p);
}
return vec; return vec;
})); }));
...@@ -545,8 +565,11 @@ void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::v ...@@ -545,8 +565,11 @@ void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::v
cl.def("__setitem__", cl.def("__setitem__",
[](Map &m, const KeyType &k, const MappedType &v) { [](Map &m, const KeyType &k, const MappedType &v) {
auto it = m.find(k); auto it = m.find(k);
if (it != m.end()) it->second = v; if (it != m.end()) {
else m.emplace(k, v); it->second = v;
} else {
m.emplace(k, v);
}
} }
); );
} }
...@@ -583,8 +606,9 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ & ...@@ -583,8 +606,9 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &
s << name << '{'; s << name << '{';
bool f = false; bool f = false;
for (auto const &kv : m) { for (auto const &kv : m) {
if (f) if (f) {
s << ", "; s << ", ";
}
s << kv.first << ": " << kv.second; s << kv.first << ": " << kv.second;
f = true; f = true;
} }
...@@ -675,8 +699,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&. ...@@ -675,8 +699,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
cl.def("__getitem__", cl.def("__getitem__",
[](Map &m, const KeyType &k) -> MappedType & { [](Map &m, const KeyType &k) -> MappedType & {
auto it = m.find(k); auto it = m.find(k);
if (it == m.end()) if (it == m.end()) {
throw key_error(); throw key_error();
}
return it->second; return it->second;
}, },
return_value_policy::reference_internal // ref + keepalive return_value_policy::reference_internal // ref + keepalive
...@@ -685,8 +710,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&. ...@@ -685,8 +710,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
cl.def("__contains__", cl.def("__contains__",
[](Map &m, const KeyType &k) -> bool { [](Map &m, const KeyType &k) -> bool {
auto it = m.find(k); auto it = m.find(k);
if (it == m.end()) if (it == m.end()) {
return false; return false;
}
return true; return true;
} }
); );
...@@ -699,8 +725,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&. ...@@ -699,8 +725,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
cl.def("__delitem__", cl.def("__delitem__",
[](Map &m, const KeyType &k) { [](Map &m, const KeyType &k) {
auto it = m.find(k); auto it = m.find(k);
if (it == m.end()) if (it == m.end()) {
throw key_error(); throw key_error();
}
m.erase(it); m.erase(it);
} }
); );
...@@ -717,8 +744,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&. ...@@ -717,8 +744,9 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
keys_view.def("__contains__", keys_view.def("__contains__",
[](KeysView &view, const KeyType &k) -> bool { [](KeysView &view, const KeyType &k) -> bool {
auto it = view.map.find(k); auto it = view.map.find(k);
if (it == view.map.end()) if (it == view.map.end()) {
return false; return false;
}
return true; return true;
} }
); );
......
...@@ -101,10 +101,11 @@ public: ...@@ -101,10 +101,11 @@ public:
} }
void destroyed(void *inst) { void destroyed(void *inst) {
if (--_instances[inst] < 0) if (--_instances[inst] < 0) {
throw std::runtime_error("cstats.destroyed() called with unknown " throw std::runtime_error("cstats.destroyed() called with unknown "
"instance; potential double-destruction " "instance; potential double-destruction "
"or a missing cstats.created()"); "or a missing cstats.created()");
}
} }
static void gc() { static void gc() {
...@@ -127,9 +128,11 @@ public: ...@@ -127,9 +128,11 @@ public:
int alive() { int alive() {
gc(); gc();
int total = 0; int total = 0;
for (const auto &p : _instances) for (const auto &p : _instances) {
if (p.second > 0) if (p.second > 0) {
total += p.second; total += p.second;
}
}
return total; return total;
} }
...@@ -145,7 +148,9 @@ public: ...@@ -145,7 +148,9 @@ public:
// Move out stored values // Move out stored values
py::list values() { py::list values() {
py::list l; 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(); _values.clear();
return l; return l;
} }
...@@ -181,7 +186,9 @@ public: ...@@ -181,7 +186,9 @@ public:
} }
} }
catch (const std::out_of_range&) {} 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); auto &cs1 = get(*t1);
// If we have both a t1 and t2 match, one is probably the trampoline class; return whichever // 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) // has more constructions (typically one or the other will be 0)
...@@ -189,7 +196,9 @@ public: ...@@ -189,7 +196,9 @@ public:
auto &cs2 = get(*t2); auto &cs2 = get(*t2);
int cs1_total = cs1.default_constructions + cs1.copy_constructions + cs1.move_constructions + (int) cs1._values.size(); 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(); 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; return cs1;
} }
......
...@@ -27,10 +27,11 @@ public: ...@@ -27,10 +27,11 @@ public:
*/ */
void decRef(bool dealloc = true) const { void decRef(bool dealloc = true) const {
--m_refCount; --m_refCount;
if (m_refCount == 0 && dealloc) if (m_refCount == 0 && dealloc) {
delete this; delete this;
else if (m_refCount < 0) } else if (m_refCount < 0) {
throw std::runtime_error("Internal error: reference count < 0!"); throw std::runtime_error("Internal error: reference count < 0!");
}
} }
virtual std::string toString() const = 0; virtual std::string toString() const = 0;
...@@ -66,7 +67,9 @@ public: ...@@ -66,7 +67,9 @@ public:
/// Construct a reference from a pointer /// Construct a reference from a pointer
explicit ref(T *ptr) : m_ptr(ptr) { 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"); print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer");
...@@ -74,8 +77,9 @@ public: ...@@ -74,8 +77,9 @@ public:
/// Copy constructor /// Copy constructor
ref(const ref &r) : m_ptr(r.m_ptr) { ref(const ref &r) : m_ptr(r.m_ptr) {
if (m_ptr) if (m_ptr) {
((Object *) m_ptr)->incRef(); ((Object *) m_ptr)->incRef();
}
print_copy_created(this, "with pointer", m_ptr); track_copy_created((ref_tag*) this); print_copy_created(this, "with pointer", m_ptr); track_copy_created((ref_tag*) this);
} }
...@@ -89,8 +93,9 @@ public: ...@@ -89,8 +93,9 @@ public:
/// Destroy this reference /// Destroy this reference
~ref() { ~ref() {
if (m_ptr) if (m_ptr) {
((Object *) m_ptr)->decRef(); ((Object *) m_ptr)->decRef();
}
print_destroyed(this); track_destroyed((ref_tag*) this); print_destroyed(this); track_destroyed((ref_tag*) this);
} }
...@@ -99,10 +104,12 @@ public: ...@@ -99,10 +104,12 @@ public:
ref &operator=(ref &&r) noexcept { ref &operator=(ref &&r) noexcept {
print_move_assigned(this, "pointer", r.m_ptr); track_move_assigned((ref_tag*) this); print_move_assigned(this, "pointer", r.m_ptr); track_move_assigned((ref_tag*) this);
if (*this == r) if (*this == r) {
return *this; return *this;
if (m_ptr) }
if (m_ptr) {
((Object *) m_ptr)->decRef(); ((Object *) m_ptr)->decRef();
}
m_ptr = r.m_ptr; m_ptr = r.m_ptr;
r.m_ptr = nullptr; r.m_ptr = nullptr;
return *this; return *this;
...@@ -116,13 +123,16 @@ public: ...@@ -116,13 +123,16 @@ public:
print_copy_assigned(this, "pointer", r.m_ptr); print_copy_assigned(this, "pointer", r.m_ptr);
track_copy_assigned((ref_tag *) this); track_copy_assigned((ref_tag *) this);
if (m_ptr == r.m_ptr) if (m_ptr == r.m_ptr) {
return *this; return *this;
if (m_ptr) }
if (m_ptr) {
((Object *) m_ptr)->decRef(); ((Object *) m_ptr)->decRef();
}
m_ptr = r.m_ptr; m_ptr = r.m_ptr;
if (m_ptr) if (m_ptr) {
((Object *) m_ptr)->incRef(); ((Object *) m_ptr)->incRef();
}
return *this; return *this;
} }
...@@ -130,13 +140,16 @@ public: ...@@ -130,13 +140,16 @@ public:
ref& operator=(T *ptr) { ref& operator=(T *ptr) {
print_values(this, "assigned pointer"); track_values((ref_tag*) this, "assigned pointer"); print_values(this, "assigned pointer"); track_values((ref_tag*) this, "assigned pointer");
if (m_ptr == ptr) if (m_ptr == ptr) {
return *this; return *this;
if (m_ptr) }
if (m_ptr) {
((Object *) m_ptr)->decRef(); ((Object *) m_ptr)->decRef();
}
m_ptr = ptr; m_ptr = ptr;
if (m_ptr) if (m_ptr) {
((Object *) m_ptr)->incRef(); ((Object *) m_ptr)->incRef();
}
return *this; return *this;
} }
......
...@@ -39,7 +39,9 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) { ...@@ -39,7 +39,9 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); }); m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); });
py::register_exception_translator([](std::exception_ptr p) { py::register_exception_translator([](std::exception_ptr p) {
try { try {
if (p) std::rethrow_exception(p); if (p) {
std::rethrow_exception(p);
}
} catch (const shared_exception &e) { } catch (const shared_exception &e) {
PyErr_SetString(PyExc_KeyError, e.what()); PyErr_SetString(PyExc_KeyError, e.what());
} }
......
...@@ -86,6 +86,7 @@ PYBIND11_MODULE(pybind11_tests, m) { ...@@ -86,6 +86,7 @@ PYBIND11_MODULE(pybind11_tests, m) {
.def(py::init<int>()) .def(py::init<int>())
.def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); }); .def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); });
for (const auto &initializer : initializers()) for (const auto &initializer : initializers()) {
initializer(m); initializer(m);
}
} }
...@@ -85,8 +85,9 @@ TEST_SUBMODULE(buffers, m) { ...@@ -85,8 +85,9 @@ TEST_SUBMODULE(buffers, m) {
/// Construct from a buffer /// Construct from a buffer
.def(py::init([](const py::buffer &b) { .def(py::init([](const py::buffer &b) {
py::buffer_info info = b.request(); 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!"); throw std::runtime_error("Incompatible buffer format!");
}
auto v = new Matrix(info.shape[0], info.shape[1]); auto v = new Matrix(info.shape[0], info.shape[1]);
memcpy(v->data(), info.ptr, sizeof(float) * (size_t) (v->rows() * v->cols())); memcpy(v->data(), info.ptr, sizeof(float) * (size_t) (v->rows() * v->cols()));
...@@ -99,14 +100,16 @@ TEST_SUBMODULE(buffers, m) { ...@@ -99,14 +100,16 @@ TEST_SUBMODULE(buffers, m) {
/// Bare bones interface /// Bare bones interface
.def("__getitem__", .def("__getitem__",
[](const Matrix &m, std::pair<py::ssize_t, py::ssize_t> i) { [](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(); throw py::index_error();
}
return m(i.first, i.second); return m(i.first, i.second);
}) })
.def("__setitem__", .def("__setitem__",
[](Matrix &m, std::pair<py::ssize_t, py::ssize_t> i, float v) { [](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(); throw py::index_error();
}
m(i.first, i.second) = v; m(i.first, i.second) = v;
}) })
/// Provide buffer access /// Provide buffer access
......
...@@ -93,8 +93,11 @@ TEST_SUBMODULE(builtin_casters, m) { ...@@ -93,8 +93,11 @@ TEST_SUBMODULE(builtin_casters, m) {
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
// Under Python 2.7, invalid unicode UTF-32 characters don't appear to trigger UnicodeDecodeError // 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 }); }); m.def("bad_utf32_string", [=]() { return std::u32string({ a32, char32_t(0xd800), z32 }); });
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) {
m.def("bad_wchar_string", [=]() { return std::wstring({ wchar_t(0x61), wchar_t(0xd800) }); }); m.def("bad_wchar_string", [=]() {
return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
});
}
#endif #endif
m.def("u8_Z", []() -> char { return 'Z'; }); m.def("u8_Z", []() -> char { return 'Z'; });
m.def("u8_eacute", []() -> char { return '\xe9'; }); m.def("u8_eacute", []() -> char { return '\xe9'; });
...@@ -133,9 +136,21 @@ TEST_SUBMODULE(builtin_casters, m) { ...@@ -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_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_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_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_view_chars", [](std::string_view s) { py::list l;
m.def("string_view16_chars", [](std::u16string_view s) { py::list l; for (auto c : s) l.append((int) c); return l; }); for (auto c : s) {
m.def("string_view32_chars", [](std::u32string_view s) { py::list l; for (auto c : s) l.append((int) c); return l; }); 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_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_view16_return", []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
m.def("string_view32_return", []() { return std::u32string_view(U"utf32 secret \U0001f382"); }); m.def("string_view32_return", []() { return std::u32string_view(U"utf32 secret \U0001f382"); });
......
...@@ -95,8 +95,9 @@ TEST_SUBMODULE(call_policies, m) { ...@@ -95,8 +95,9 @@ TEST_SUBMODULE(call_policies, m) {
// but it's unclear how to test it without `PyGILState_GetThisThreadState`. // but it's unclear how to test it without `PyGILState_GetThisThreadState`.
auto report_gil_status = []() { auto report_gil_status = []() {
auto is_gil_held = false; 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()); is_gil_held = (tstate == PyGILState_GetThisThreadState());
}
return is_gil_held ? "GIL held" : "GIL released"; return is_gil_held ? "GIL held" : "GIL released";
}; };
......
...@@ -136,11 +136,16 @@ TEST_SUBMODULE(callbacks, m) { ...@@ -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", [](int i, int j) { return i + j; });
m.def("dummy_function_overloaded", &dummy_function); m.def("dummy_function_overloaded", &dummy_function);
m.def("dummy_function2", [](int i, int j) { return i + j; }); m.def("dummy_function2", [](int i, int j) { return i + j; });
m.def("roundtrip", [](std::function<int(int)> f, bool expect_none = false) { m.def(
if (expect_none && f) "roundtrip",
throw std::runtime_error("Expected None to be converted to empty std::function"); [](std::function<int(int)> f, bool expect_none = false) {
return f; if (expect_none && f) {
}, py::arg("f"), py::arg("expect_none")=false); 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 { m.def("test_dummy_function", [](const std::function<int(int)> &f) -> std::string {
using fn_type = int (*)(int); using fn_type = int (*)(int);
auto result = f.target<fn_type>(); auto result = f.target<fn_type>();
...@@ -215,8 +220,9 @@ TEST_SUBMODULE(callbacks, m) { ...@@ -215,8 +220,9 @@ TEST_SUBMODULE(callbacks, m) {
}; };
// spawn worker threads // spawn worker threads
for (auto i : work) for (auto i : work) {
start_f(py::cast<int>(i)); start_f(py::cast<int>(i));
}
}); });
m.def("callback_num_times", [](const py::function &f, std::size_t num) { m.def("callback_num_times", [](const py::function &f, std::size_t num) {
......
...@@ -139,9 +139,13 @@ TEST_SUBMODULE(class_, m) { ...@@ -139,9 +139,13 @@ TEST_SUBMODULE(class_, m) {
m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); }); m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); }); m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
m.def("return_class_n", [](int n) -> BaseClass* { m.def("return_class_n", [](int n) -> BaseClass * {
if (n == 1) return new DerivedClass1(); if (n == 1) {
if (n == 2) return new DerivedClass2(); return new DerivedClass1();
}
if (n == 2) {
return new DerivedClass2();
}
return new BaseClass(); return new BaseClass();
}); });
m.def("return_none", []() -> BaseClass* { return nullptr; }); m.def("return_none", []() -> BaseClass* { return nullptr; });
...@@ -167,8 +171,9 @@ TEST_SUBMODULE(class_, m) { ...@@ -167,8 +171,9 @@ TEST_SUBMODULE(class_, m) {
// See https://github.com/pybind/pybind11/issues/2486 // See https://github.com/pybind/pybind11/issues/2486
// if (category == 2) // if (category == 2)
// return py::type::of<int>(); // return py::type::of<int>();
if (category == 1) if (category == 1) {
return py::type::of<DerivedClass1>(); return py::type::of<DerivedClass1>();
}
return py::type::of<Invalid>(); return py::type::of<Invalid>();
}); });
......
...@@ -104,7 +104,9 @@ public: ...@@ -104,7 +104,9 @@ public:
bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; } 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 &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) { 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); return cast(*src, policy, parent);
} }
explicit operator CopyOnlyInt *() { return &value; } explicit operator CopyOnlyInt *() { return &value; }
...@@ -203,8 +205,9 @@ TEST_SUBMODULE(copy_move_policies, m) { ...@@ -203,8 +205,9 @@ TEST_SUBMODULE(copy_move_policies, m) {
private: private:
void *operator new(size_t bytes) { void *operator new(size_t bytes) {
void *ptr = std::malloc(bytes); void *ptr = std::malloc(bytes);
if (ptr) if (ptr) {
return ptr; return ptr;
}
throw std::bad_alloc{}; throw std::bad_alloc{};
} }
}; };
......
...@@ -28,8 +28,11 @@ using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::R ...@@ -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 // Sets/resets a testing reference matrix to have values of 10*r + c, where r and c are the
// (1-based) row/column number. // (1-based) row/column number.
template <typename M> void reset_ref(M &x) { template <typename M> void reset_ref(M &x) {
for (int i = 0; i < x.rows(); i++) for (int j = 0; j < x.cols(); j++) for (int i = 0; i < x.rows(); i++) {
x(i, j) = 11 + 10*i + j; for (int j = 0; j < x.cols(); j++) {
x(i, j) = 11 + 10 * i + j;
}
}
} }
// Returns a static, column-major matrix // Returns a static, column-major matrix
...@@ -63,9 +66,11 @@ double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); }; ...@@ -63,9 +66,11 @@ double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); };
// reference is referencing rows/columns correctly). // reference is referencing rows/columns correctly).
template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m) { template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m) {
Eigen::MatrixXd ret(m); Eigen::MatrixXd ret(m);
for (int c = 0; c < m.cols(); c++) for (int c = 0; c < m.cols(); c++) {
for (int r = 0; r < m.rows(); r++) for (int r = 0; r < m.rows(); r++) {
ret(r, c) += 10*r + 100*c; // NOLINT(clang-analyzer-core.uninitialized.Assign) ret(r, c) += 10 * r + 100 * c; // NOLINT(clang-analyzer-core.uninitialized.Assign)
}
}
return ret; return ret;
} }
...@@ -225,7 +230,9 @@ TEST_SUBMODULE(eigen, m) { ...@@ -225,7 +230,9 @@ TEST_SUBMODULE(eigen, m) {
// Returns a DiagonalMatrix with diagonal (1,2,3,...) // Returns a DiagonalMatrix with diagonal (1,2,3,...)
m.def("incr_diag", [](int k) { m.def("incr_diag", [](int k) {
Eigen::DiagonalMatrix<int, Eigen::Dynamic> m(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; return m;
}); });
...@@ -320,8 +327,9 @@ TEST_SUBMODULE(eigen, m) { ...@@ -320,8 +327,9 @@ TEST_SUBMODULE(eigen, m) {
"matrix_multiply", "matrix_multiply",
[](const py::EigenDRef<const Eigen::MatrixXd> &A, [](const py::EigenDRef<const Eigen::MatrixXd> &A,
const py::EigenDRef<const Eigen::MatrixXd> &B) -> Eigen::MatrixXd { 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!"); throw std::domain_error("Nonconformable matrices!");
}
return A * B; return A * B;
}, },
py::arg("A"), py::arg("A"),
......
...@@ -307,7 +307,11 @@ TEST_CASE("Threads") { ...@@ -307,7 +307,11 @@ TEST_CASE("Threads") {
struct scope_exit { struct scope_exit {
std::function<void()> f_; std::function<void()> f_;
explicit scope_exit(std::function<void()> f) noexcept : f_(std::move(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") { TEST_CASE("Reload module from file") {
......
...@@ -93,8 +93,9 @@ TEST_SUBMODULE(eval_, m) { ...@@ -93,8 +93,9 @@ TEST_SUBMODULE(eval_, m) {
// test_eval_empty_globals // test_eval_empty_globals
m.def("eval_empty_globals", [](py::object global) { m.def("eval_empty_globals", [](py::object global) {
if (global.is_none()) if (global.is_none()) {
global = py::dict(); global = py::dict();
}
auto int_class = py::eval("isinstance(42, int)", global); auto int_class = py::eval("isinstance(42, int)", global);
return global; return global;
}); });
......
...@@ -116,7 +116,9 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -116,7 +116,9 @@ TEST_SUBMODULE(exceptions, m) {
static py::exception<MyException> ex(m, "MyException"); static py::exception<MyException> ex(m, "MyException");
py::register_exception_translator([](std::exception_ptr p) { py::register_exception_translator([](std::exception_ptr p) {
try { try {
if (p) std::rethrow_exception(p); if (p) {
std::rethrow_exception(p);
}
} catch (const MyException &e) { } catch (const MyException &e) {
// Set MyException as the active python error // Set MyException as the active python error
ex(e.what()); ex(e.what());
...@@ -128,7 +130,9 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -128,7 +130,9 @@ TEST_SUBMODULE(exceptions, m) {
// never by visible from Python // never by visible from Python
py::register_exception_translator([](std::exception_ptr p) { py::register_exception_translator([](std::exception_ptr p) {
try { try {
if (p) std::rethrow_exception(p); if (p) {
std::rethrow_exception(p);
}
} catch (const MyException2 &e) { } catch (const MyException2 &e) {
// Translate this exception to a standard RuntimeError // Translate this exception to a standard RuntimeError
PyErr_SetString(PyExc_RuntimeError, e.what()); PyErr_SetString(PyExc_RuntimeError, e.what());
...@@ -140,7 +144,9 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -140,7 +144,9 @@ TEST_SUBMODULE(exceptions, m) {
// translator for MyException by throwing a new exception // translator for MyException by throwing a new exception
py::register_exception_translator([](std::exception_ptr p) { py::register_exception_translator([](std::exception_ptr p) {
try { try {
if (p) std::rethrow_exception(p); if (p) {
std::rethrow_exception(p);
}
} catch (const MyException4 &e) { } catch (const MyException4 &e) {
throw MyException(e.what()); throw MyException(e.what());
} }
...@@ -181,7 +187,9 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -181,7 +187,9 @@ TEST_SUBMODULE(exceptions, m) {
py::object o = foo["bar"]; py::object o = foo["bar"];
} }
catch (py::error_already_set& ex) { catch (py::error_already_set& ex) {
if (!ex.matches(PyExc_KeyError)) throw; if (!ex.matches(PyExc_KeyError)) {
throw;
}
return true; return true;
} }
return false; return false;
...@@ -193,7 +201,9 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -193,7 +201,9 @@ TEST_SUBMODULE(exceptions, m) {
py::object o = foo["bar"]; py::object o = foo["bar"];
} }
catch (py::error_already_set &ex) { catch (py::error_already_set &ex) {
if (!ex.matches(PyExc_Exception)) throw; if (!ex.matches(PyExc_Exception)) {
throw;
}
return true; return true;
} }
return false; return false;
...@@ -204,15 +214,18 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -204,15 +214,18 @@ TEST_SUBMODULE(exceptions, m) {
py::module_::import("nonexistent"); py::module_::import("nonexistent");
} }
catch (py::error_already_set &ex) { catch (py::error_already_set &ex) {
if (!ex.matches(PyExc_ImportError)) throw; if (!ex.matches(PyExc_ImportError)) {
throw;
}
return true; return true;
} }
return false; return false;
}); });
m.def("throw_already_set", [](bool err) { m.def("throw_already_set", [](bool err) {
if (err) if (err) {
PyErr_SetString(PyExc_ValueError, "foo"); PyErr_SetString(PyExc_ValueError, "foo");
}
try { try {
throw py::error_already_set(); throw py::error_already_set();
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
...@@ -224,8 +237,9 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -224,8 +237,9 @@ TEST_SUBMODULE(exceptions, m) {
} }
} }
PyErr_Clear(); PyErr_Clear();
if (err) if (err) {
PyErr_SetString(PyExc_ValueError, "foo"); PyErr_SetString(PyExc_ValueError, "foo");
}
throw py::error_already_set(); throw py::error_already_set();
}); });
...@@ -252,10 +266,11 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -252,10 +266,11 @@ TEST_SUBMODULE(exceptions, m) {
try { try {
f(*args); f(*args);
} catch (py::error_already_set &ex) { } catch (py::error_already_set &ex) {
if (ex.matches(exc_type)) if (ex.matches(exc_type)) {
py::print(ex.what()); py::print(ex.what());
else } else {
throw; throw;
}
} }
}); });
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
void noisy_function(const std::string &msg, bool flush) { void noisy_function(const std::string &msg, bool flush) {
std::cout << msg; std::cout << msg;
if (flush) if (flush) {
std::cout << std::flush; std::cout << std::flush;
}
} }
void noisy_funct_dual(const std::string &msg, const std::string &emsg) { void noisy_funct_dual(const std::string &msg, const std::string &emsg) {
......
...@@ -26,8 +26,9 @@ TEST_SUBMODULE(kwargs_and_defaults, m) { ...@@ -26,8 +26,9 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
std::vector<int> list{{13, 17}}; std::vector<int> list{{13, 17}};
m.def("kw_func4", [](const std::vector<int> &entries) { m.def("kw_func4", [](const std::vector<int> &entries) {
std::string ret = "{"; std::string ret = "{";
for (int i : entries) for (int i : entries) {
ret += std::to_string(i) + " "; ret += std::to_string(i) + " ";
}
ret.back() = '}'; ret.back() = '}';
return ret; return ret;
}, py::arg("myList") = list); }, py::arg("myList") = list);
...@@ -89,18 +90,20 @@ TEST_SUBMODULE(kwargs_and_defaults, m) { ...@@ -89,18 +90,20 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
m.def("args_refcount", [](py::args a) { m.def("args_refcount", [](py::args a) {
GC_IF_NEEDED; GC_IF_NEEDED;
py::tuple t(a.size()); 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: // 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))); t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
}
return t; return t;
}); });
m.def("mixed_args_refcount", [](const py::object &o, py::args a) { m.def("mixed_args_refcount", [](const py::object &o, py::args a) {
GC_IF_NEEDED; GC_IF_NEEDED;
py::tuple t(a.size() + 1); py::tuple t(a.size() + 1);
t[0] = o.ref_count(); 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: // 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))); t[i + 1] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
}
return t; return t;
}); });
......
...@@ -47,8 +47,9 @@ TEST_SUBMODULE(local_bindings, m) { ...@@ -47,8 +47,9 @@ TEST_SUBMODULE(local_bindings, m) {
auto main = py::module_::import("pybind11_tests"); auto main = py::module_::import("pybind11_tests");
if (py::hasattr(main, "class_")) { if (py::hasattr(main, "class_")) {
bind_local<LocalExternal, 7>(m, "LocalExternal", py::module_local()); 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 // test_stl_bind_local
......
...@@ -90,15 +90,17 @@ template<typename... Ix> arr data_t(const arr_t& a, Ix... index) { ...@@ -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) { template<typename... Ix> arr& mutate_data(arr& a, Ix... index) {
auto ptr = (uint8_t *) a.mutable_data(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); ptr[i] = (uint8_t) (ptr[i] * 2);
}
return a; return a;
} }
template<typename... Ix> arr_t& mutate_data_t(arr_t& a, Ix... index) { template<typename... Ix> arr_t& mutate_data_t(arr_t& a, Ix... index) {
auto ptr = a.mutable_data(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]++; ptr[i]++;
}
return a; return a;
} }
...@@ -116,7 +118,9 @@ template<typename... Ix> arr_t& mutate_at_t(arr_t& a, Ix... idx) { a.mutable_at( ...@@ -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); }); 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) { 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; py::list l;
l.append(*r.data(0, 0)); l.append(*r.data(0, 0));
l.append(*r2.mutable_data(0, 0)); l.append(*r2.mutable_data(0, 0));
...@@ -292,34 +296,43 @@ TEST_SUBMODULE(numpy_array, sm) { ...@@ -292,34 +296,43 @@ TEST_SUBMODULE(numpy_array, sm) {
// test_array_unchecked_fixed_dims // test_array_unchecked_fixed_dims
sm.def("proxy_add2", [](py::array_t<double> a, double v) { sm.def("proxy_add2", [](py::array_t<double> a, double v) {
auto r = a.mutable_unchecked<2>(); auto r = a.mutable_unchecked<2>();
for (py::ssize_t i = 0; i < r.shape(0); i++) 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 j = 0; j < r.shape(1); j++) {
r(i, j) += v; r(i, j) += v;
}
}
}, py::arg{}.noconvert(), py::arg()); }, py::arg{}.noconvert(), py::arg());
sm.def("proxy_init3", [](double start) { sm.def("proxy_init3", [](double start) {
py::array_t<double, py::array::c_style> a({ 3, 3, 3 }); py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
auto r = a.mutable_unchecked<3>(); auto r = a.mutable_unchecked<3>();
for (py::ssize_t i = 0; i < r.shape(0); i++) 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 j = 0; j < r.shape(1); j++) {
for (py::ssize_t k = 0; k < r.shape(2); k++) for (py::ssize_t k = 0; k < r.shape(2); k++) {
r(i, j, k) = start++; r(i, j, k) = start++;
}
}
}
return a; return a;
}); });
sm.def("proxy_init3F", [](double start) { sm.def("proxy_init3F", [](double start) {
py::array_t<double, py::array::f_style> a({ 3, 3, 3 }); py::array_t<double, py::array::f_style> a({ 3, 3, 3 });
auto r = a.mutable_unchecked<3>(); auto r = a.mutable_unchecked<3>();
for (py::ssize_t k = 0; k < r.shape(2); k++) 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 j = 0; j < r.shape(1); j++) {
for (py::ssize_t i = 0; i < r.shape(0); i++) for (py::ssize_t i = 0; i < r.shape(0); i++) {
r(i, j, k) = start++; r(i, j, k) = start++;
}
}
}
return a; return a;
}); });
sm.def("proxy_squared_L2_norm", [](const py::array_t<double> &a) { sm.def("proxy_squared_L2_norm", [](const py::array_t<double> &a) {
auto r = a.unchecked<1>(); auto r = a.unchecked<1>();
double sumsq = 0; 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 sumsq += r[i] * r(i); // Either notation works for a 1D array
}
return sumsq; return sumsq;
}); });
...@@ -345,19 +358,28 @@ TEST_SUBMODULE(numpy_array, sm) { ...@@ -345,19 +358,28 @@ TEST_SUBMODULE(numpy_array, sm) {
// Same as the above, but without a compile-time dimensions specification: // Same as the above, but without a compile-time dimensions specification:
sm.def("proxy_add2_dyn", [](py::array_t<double> a, double v) { sm.def("proxy_add2_dyn", [](py::array_t<double> a, double v) {
auto r = a.mutable_unchecked(); auto r = a.mutable_unchecked();
if (r.ndim() != 2) throw std::domain_error("error: ndim != 2"); if (r.ndim() != 2) {
for (py::ssize_t i = 0; i < r.shape(0); i++) throw std::domain_error("error: ndim != 2");
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; r(i, j) += v;
}
}
}, py::arg{}.noconvert(), py::arg()); }, py::arg{}.noconvert(), py::arg());
sm.def("proxy_init3_dyn", [](double start) { sm.def("proxy_init3_dyn", [](double start) {
py::array_t<double, py::array::c_style> a({ 3, 3, 3 }); py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
auto r = a.mutable_unchecked(); auto r = a.mutable_unchecked();
if (r.ndim() != 3) throw std::domain_error("error: ndim != 3"); if (r.ndim() != 3) {
for (py::ssize_t i = 0; i < r.shape(0); i++) throw std::domain_error("error: ndim != 3");
for (py::ssize_t j = 0; j < r.shape(1); j++) }
for (py::ssize_t k = 0; k < r.shape(2); k++) for (py::ssize_t i = 0; i < r.shape(0); i++) {
r(i, j, k) = start++; 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; return a;
}); });
sm.def("proxy_auxiliaries2_dyn", [](py::array_t<double> a) { sm.def("proxy_auxiliaries2_dyn", [](py::array_t<double> a) {
...@@ -386,8 +408,10 @@ TEST_SUBMODULE(numpy_array, sm) { ...@@ -386,8 +408,10 @@ TEST_SUBMODULE(numpy_array, sm) {
// reshape array to 2D without changing size // reshape array to 2D without changing size
sm.def("array_reshape2", [](py::array_t<double> a) { sm.def("array_reshape2", [](py::array_t<double> a) {
const auto dim_sz = (py::ssize_t)std::sqrt(a.size()); const auto dim_sz = (py::ssize_t)std::sqrt(a.size());
if (dim_sz * dim_sz != a.size()) if (dim_sz * dim_sz != a.size()) {
throw std::domain_error("array_reshape2: input array total size is not a squared integer"); throw std::domain_error(
"array_reshape2: input array total size is not a squared integer");
}
a.resize({dim_sz, dim_sz}); a.resize({dim_sz, dim_sz});
}); });
......
...@@ -108,30 +108,35 @@ PYBIND11_PACKED(struct EnumStruct { ...@@ -108,30 +108,35 @@ PYBIND11_PACKED(struct EnumStruct {
std::ostream& operator<<(std::ostream& os, const StringStruct& v) { std::ostream& operator<<(std::ostream& os, const StringStruct& v) {
os << "a='"; 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 << v.a[i];
}
os << "',b='"; 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]; os << v.b[i];
}
return os << "'"; return os << "'";
} }
std::ostream& operator<<(std::ostream& os, const ArrayStruct& v) { std::ostream& operator<<(std::ostream& os, const ArrayStruct& v) {
os << "a={"; os << "a={";
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (i > 0) if (i > 0) {
os << ','; os << ',';
}
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][j] << ',';
}
os << v.a[i][3] << '}'; os << v.a[i][3] << '}';
} }
os << "},b={" << v.b[0] << ',' << v.b[1]; os << "},b={" << v.b[0] << ',' << v.b[1];
os << "},c={" << int(v.c[0]) << ',' << int(v.c[1]) << ',' << int(v.c[2]); os << "},c={" << int(v.c[0]) << ',' << int(v.c[1]) << ',' << int(v.c[2]);
os << "},d={"; os << "},d={";
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (i > 0) if (i > 0) {
os << ','; os << ',';
}
os << '{' << v.d[i][0] << ',' << v.d[i][1] << '}'; os << '{' << v.d[i][0] << ',' << v.d[i][1] << '}';
} }
return os << '}'; return os << '}';
...@@ -198,7 +203,9 @@ py::array_t<int32_t, 0> test_array_ctors(int i) { ...@@ -198,7 +203,9 @@ py::array_t<int32_t, 0> test_array_ctors(int i) {
auto fill = [](py::array arr) { auto fill = [](py::array arr) {
auto req = arr.request(); 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; return arr;
}; };
...@@ -373,32 +380,33 @@ TEST_SUBMODULE(numpy_dtypes, m) { ...@@ -373,32 +380,33 @@ TEST_SUBMODULE(numpy_dtypes, m) {
m.def("print_dtypes", []() { m.def("print_dtypes", []() {
py::list l; py::list l;
for (const py::handle &d : { for (const py::handle &d : {py::dtype::of<SimpleStruct>(),
py::dtype::of<SimpleStruct>(), py::dtype::of<PackedStruct>(),
py::dtype::of<PackedStruct>(), py::dtype::of<NestedStruct>(),
py::dtype::of<NestedStruct>(), py::dtype::of<PartialStruct>(),
py::dtype::of<PartialStruct>(), py::dtype::of<PartialNestedStruct>(),
py::dtype::of<PartialNestedStruct>(), py::dtype::of<StringStruct>(),
py::dtype::of<StringStruct>(), py::dtype::of<ArrayStruct>(),
py::dtype::of<ArrayStruct>(), py::dtype::of<EnumStruct>(),
py::dtype::of<EnumStruct>(), py::dtype::of<StructWithUglyNames>(),
py::dtype::of<StructWithUglyNames>(), py::dtype::of<ComplexStruct>()}) {
py::dtype::of<ComplexStruct>()
})
l.append(py::str(d)); l.append(py::str(d));
}
return l; return l;
}); });
m.def("test_dtype_ctors", &test_dtype_ctors); m.def("test_dtype_ctors", &test_dtype_ctors);
m.def("test_dtype_kind", [dtype_names]() { m.def("test_dtype_kind", [dtype_names]() {
py::list list; py::list list;
for (auto& dt_name : dtype_names) for (auto &dt_name : dtype_names) {
list.append(py::dtype(dt_name).kind()); list.append(py::dtype(dt_name).kind());
}
return list; return list;
}); });
m.def("test_dtype_char_", [dtype_names]() { m.def("test_dtype_char_", [dtype_names]() {
py::list list; py::list list;
for (auto& dt_name : dtype_names) for (auto &dt_name : dtype_names) {
list.append(py::dtype(dt_name).char_()); list.append(py::dtype(dt_name).char_());
}
return list; return list;
}); });
m.def("test_dtype_methods", []() { m.def("test_dtype_methods", []() {
...@@ -423,8 +431,9 @@ TEST_SUBMODULE(numpy_dtypes, m) { ...@@ -423,8 +431,9 @@ TEST_SUBMODULE(numpy_dtypes, m) {
if (non_empty) { if (non_empty) {
auto req = arr.request(); auto req = arr.request();
auto ptr = static_cast<StringStruct*>(req.ptr); auto ptr = static_cast<StringStruct*>(req.ptr);
for (py::ssize_t i = 0; i < req.size * req.itemsize; i++) for (py::ssize_t i = 0; i < req.size * req.itemsize; i++) {
static_cast<char*>(req.ptr)[i] = 0; static_cast<char *>(req.ptr)[i] = 0;
}
ptr[1].a[0] = 'a'; ptr[1].b[0] = 'a'; ptr[1].a[0] = 'a'; ptr[1].b[0] = 'a';
ptr[2].a[0] = 'a'; ptr[2].b[0] = 'a'; ptr[2].a[0] = 'a'; ptr[2].b[0] = 'a';
ptr[3].a[0] = 'a'; ptr[3].b[0] = 'a'; ptr[3].a[0] = 'a'; ptr[3].b[0] = 'a';
...@@ -443,16 +452,22 @@ TEST_SUBMODULE(numpy_dtypes, m) { ...@@ -443,16 +452,22 @@ TEST_SUBMODULE(numpy_dtypes, m) {
py::array_t<ArrayStruct, 0> arr = mkarray_via_buffer<ArrayStruct>(n); py::array_t<ArrayStruct, 0> arr = mkarray_via_buffer<ArrayStruct>(n);
auto ptr = (ArrayStruct *) arr.mutable_data(); auto ptr = (ArrayStruct *) arr.mutable_data();
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < 3; j++) for (size_t j = 0; j < 3; j++) {
for (size_t k = 0; k < 4; k++) for (size_t k = 0; k < 4; k++) {
ptr[i].a[j][k] = char('A' + (i * 100 + j * 10 + k) % 26); 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); 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); 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); ptr[i].d[j][k] = float(i) * 100.0f + float(j) * 10.0f + float(k);
}
}
} }
return arr; return arr;
}); });
......
...@@ -45,8 +45,9 @@ TEST_SUBMODULE(opaque_types, m) { ...@@ -45,8 +45,9 @@ TEST_SUBMODULE(opaque_types, m) {
std::string ret = "Opaque list: ["; std::string ret = "Opaque list: [";
bool first = true; bool first = true;
for (const auto &entry : l) { for (const auto &entry : l) {
if (!first) if (!first) {
ret += ", "; ret += ", ";
}
ret += entry; ret += entry;
first = false; first = false;
} }
......
...@@ -39,13 +39,15 @@ void wrap(py::module m) { ...@@ -39,13 +39,15 @@ void wrap(py::module m) {
.def(py::pickle( .def(py::pickle(
[](const py::object &self) { [](const py::object &self) {
py::dict d; py::dict d;
if (py::hasattr(self, "__dict__")) if (py::hasattr(self, "__dict__")) {
d = self.attr("__dict__"); d = self.attr("__dict__");
}
return py::make_tuple(self.attr("num"), d); return py::make_tuple(self.attr("num"), d);
}, },
[](const py::tuple &t) { [](const py::tuple &t) {
if (t.size() != 2) if (t.size() != 2) {
throw std::runtime_error("Invalid state!"); throw std::runtime_error("Invalid state!");
}
auto cpp_state = std::unique_ptr<SimpleBase>(new SimpleBaseTrampoline); auto cpp_state = std::unique_ptr<SimpleBase>(new SimpleBaseTrampoline);
cpp_state->num = t[0].cast<int>(); cpp_state->num = t[0].cast<int>();
auto py_state = t[1].cast<py::dict>(); auto py_state = t[1].cast<py::dict>();
...@@ -101,8 +103,9 @@ TEST_SUBMODULE(pickling, m) { ...@@ -101,8 +103,9 @@ TEST_SUBMODULE(pickling, m) {
}); });
ignoreOldStyleInitWarnings([&pyPickleable]() { ignoreOldStyleInitWarnings([&pyPickleable]() {
pyPickleable.def("__setstate__", [](Pickleable &p, const py::tuple &t) { pyPickleable.def("__setstate__", [](Pickleable &p, const py::tuple &t) {
if (t.size() != 3) if (t.size() != 3) {
throw std::runtime_error("Invalid state!"); throw std::runtime_error("Invalid state!");
}
/* Invoke the constructor (need to use in-place version) */ /* Invoke the constructor (need to use in-place version) */
new (&p) Pickleable(t[0].cast<std::string>()); new (&p) Pickleable(t[0].cast<std::string>());
...@@ -119,8 +122,9 @@ TEST_SUBMODULE(pickling, m) { ...@@ -119,8 +122,9 @@ TEST_SUBMODULE(pickling, m) {
return py::make_tuple(p.value(), p.extra1(), p.extra2()); return py::make_tuple(p.value(), p.extra1(), p.extra2());
}, },
[](const py::tuple &t) { [](const py::tuple &t) {
if (t.size() != 3) if (t.size() != 3) {
throw std::runtime_error("Invalid state!"); throw std::runtime_error("Invalid state!");
}
auto p = PickleableNew(t[0].cast<std::string>()); auto p = PickleableNew(t[0].cast<std::string>());
p.setExtra1(t[1].cast<int>()); p.setExtra1(t[1].cast<int>());
...@@ -153,8 +157,9 @@ TEST_SUBMODULE(pickling, m) { ...@@ -153,8 +157,9 @@ TEST_SUBMODULE(pickling, m) {
}); });
ignoreOldStyleInitWarnings([&pyPickleableWithDict]() { ignoreOldStyleInitWarnings([&pyPickleableWithDict]() {
pyPickleableWithDict.def("__setstate__", [](const py::object &self, const py::tuple &t) { 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!"); throw std::runtime_error("Invalid state!");
}
/* Cast and construct */ /* Cast and construct */
auto &p = self.cast<PickleableWithDict &>(); auto &p = self.cast<PickleableWithDict &>();
new (&p) PickleableWithDict(t[0].cast<std::string>()); new (&p) PickleableWithDict(t[0].cast<std::string>());
...@@ -174,8 +179,9 @@ TEST_SUBMODULE(pickling, m) { ...@@ -174,8 +179,9 @@ TEST_SUBMODULE(pickling, m) {
return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__")); return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
}, },
[](const py::tuple &t) { [](const py::tuple &t) {
if (t.size() != 3) if (t.size() != 3) {
throw std::runtime_error("Invalid state!"); throw std::runtime_error("Invalid state!");
}
auto cpp_state = PickleableWithDictNew(t[0].cast<std::string>()); auto cpp_state = PickleableWithDictNew(t[0].cast<std::string>());
cpp_state.extra = t[1].cast<int>(); cpp_state.extra = t[1].cast<int>();
......
...@@ -40,8 +40,9 @@ TEST_SUBMODULE(pytypes, m) { ...@@ -40,8 +40,9 @@ TEST_SUBMODULE(pytypes, m) {
}); });
m.def("print_list", [](const py::list &list) { m.def("print_list", [](const py::list &list) {
int index = 0; int index = 0;
for (auto item : list) for (auto item : list) {
py::print("list item {}: {}"_s.format(index++, item)); py::print("list item {}: {}"_s.format(index++, item));
}
}); });
// test_none // test_none
m.def("get_none", []{return py::none();}); m.def("get_none", []{return py::none();});
...@@ -56,8 +57,9 @@ TEST_SUBMODULE(pytypes, m) { ...@@ -56,8 +57,9 @@ TEST_SUBMODULE(pytypes, m) {
return set; return set;
}); });
m.def("print_set", [](const py::set &set) { m.def("print_set", [](const py::set &set) {
for (auto item : set) for (auto item : set) {
py::print("key:", item); py::print("key:", item);
}
}); });
m.def("set_contains", m.def("set_contains",
[](const py::set &set, const py::object &key) { return set.contains(key); }); [](const py::set &set, const py::object &key) { return set.contains(key); });
...@@ -66,8 +68,9 @@ TEST_SUBMODULE(pytypes, m) { ...@@ -66,8 +68,9 @@ TEST_SUBMODULE(pytypes, m) {
// test_dict // test_dict
m.def("get_dict", []() { return py::dict("key"_a="value"); }); m.def("get_dict", []() { return py::dict("key"_a="value"); });
m.def("print_dict", [](const py::dict &dict) { 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)); py::print("key: {}, value={}"_s.format(item.first, item.second));
}
}); });
m.def("dict_keyword_constructor", []() { m.def("dict_keyword_constructor", []() {
auto d1 = py::dict("x"_a=1, "y"_a=2); auto d1 = py::dict("x"_a=1, "y"_a=2);
...@@ -405,9 +408,9 @@ TEST_SUBMODULE(pytypes, m) { ...@@ -405,9 +408,9 @@ TEST_SUBMODULE(pytypes, m) {
m.def("test_memoryview_from_buffer", [](bool is_unsigned) { m.def("test_memoryview_from_buffer", [](bool is_unsigned) {
static const int16_t si16[] = { 3, 1, 4, 1, 5 }; static const int16_t si16[] = { 3, 1, 4, 1, 5 };
static const uint16_t ui16[] = { 2, 7, 1, 8 }; static const uint16_t ui16[] = { 2, 7, 1, 8 };
if (is_unsigned) if (is_unsigned) {
return py::memoryview::from_buffer( return py::memoryview::from_buffer(ui16, {4}, {sizeof(uint16_t)});
ui16, { 4 }, { sizeof(uint16_t) }); }
return py::memoryview::from_buffer(si16, {5}, {sizeof(int16_t)}); return py::memoryview::from_buffer(si16, {5}, {sizeof(int16_t)});
}); });
......
...@@ -74,8 +74,9 @@ PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>); ...@@ -74,8 +74,9 @@ PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>);
template <typename PythonType> template <typename PythonType>
py::list test_random_access_iterator(PythonType x) { 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."); throw py::value_error("Please provide at least 5 elements for testing.");
}
auto checks = py::list(); auto checks = py::list();
auto assert_equal = [&checks](py::handle a, py::handle b) { auto assert_equal = [&checks](py::handle a, py::handle b) {
...@@ -125,8 +126,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -125,8 +126,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
.def(py::init<int>()) .def(py::init<int>())
.def("__getitem__", [](const Sliceable &s, const py::slice &slice) { .def("__getitem__", [](const Sliceable &s, const py::slice &slice) {
py::ssize_t start = 0, stop = 0, step = 0, slicelength = 0; 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(); throw py::error_already_set();
}
int istart = static_cast<int>(start); int istart = static_cast<int>(start);
int istop = static_cast<int>(stop); int istop = static_cast<int>(stop);
int istep = static_cast<int>(step); int istep = static_cast<int>(step);
...@@ -195,10 +197,14 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -195,10 +197,14 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
} }
bool operator==(const Sequence &s) const { bool operator==(const Sequence &s) const {
if (m_size != s.size()) return false; if (m_size != s.size()) {
for (size_t i = 0; i < m_size; ++i) return false;
if (m_data[i] != s[i]) }
for (size_t i = 0; i < m_size; ++i) {
if (m_data[i] != s[i]) {
return false; return false;
}
}
return true; return true;
} }
bool operator!=(const Sequence &s) const { return !operator==(s); } bool operator!=(const Sequence &s) const { return !operator==(s); }
...@@ -207,16 +213,19 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -207,16 +213,19 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
float &operator[](size_t index) { return m_data[index]; } float &operator[](size_t index) { return m_data[index]; }
bool contains(float v) const { bool contains(float v) const {
for (size_t i = 0; i < m_size; ++i) for (size_t i = 0; i < m_size; ++i) {
if (v == m_data[i]) if (v == m_data[i]) {
return true; return true;
}
}
return false; return false;
} }
Sequence reversed() const { Sequence reversed() const {
Sequence result(m_size); 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]; result[m_size - i - 1] = m_data[i];
}
return result; return result;
} }
...@@ -235,14 +244,16 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -235,14 +244,16 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
/// Bare bones interface /// Bare bones interface
.def("__getitem__", .def("__getitem__",
[](const Sequence &s, size_t i) { [](const Sequence &s, size_t i) {
if (i >= s.size()) if (i >= s.size()) {
throw py::index_error(); throw py::index_error();
}
return s[i]; return s[i];
}) })
.def("__setitem__", .def("__setitem__",
[](Sequence &s, size_t i, float v) { [](Sequence &s, size_t i, float v) {
if (i >= s.size()) if (i >= s.size()) {
throw py::index_error(); throw py::index_error();
}
s[i] = v; s[i] = v;
}) })
.def("__len__", &Sequence::size) .def("__len__", &Sequence::size)
...@@ -257,8 +268,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -257,8 +268,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
.def("__getitem__", .def("__getitem__",
[](const Sequence &s, const py::slice &slice) -> Sequence * { [](const Sequence &s, const py::slice &slice) -> Sequence * {
size_t start = 0, stop = 0, step = 0, slicelength = 0; 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(); throw py::error_already_set();
}
auto *seq = new Sequence(slicelength); auto *seq = new Sequence(slicelength);
for (size_t i = 0; i < slicelength; ++i) { for (size_t i = 0; i < slicelength; ++i) {
(*seq)[i] = s[start]; (*seq)[i] = s[start];
...@@ -269,11 +281,13 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -269,11 +281,13 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
.def("__setitem__", .def("__setitem__",
[](Sequence &s, const py::slice &slice, const Sequence &value) { [](Sequence &s, const py::slice &slice, const Sequence &value) {
size_t start = 0, stop = 0, step = 0, slicelength = 0; 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(); throw py::error_already_set();
if (slicelength != value.size()) }
if (slicelength != value.size()) {
throw std::runtime_error( throw std::runtime_error(
"Left and right hand size of slice assignment have different sizes!"); "Left and right hand size of slice assignment have different sizes!");
}
for (size_t i = 0; i < slicelength; ++i) { for (size_t i = 0; i < slicelength; ++i) {
s[start] = value[i]; s[start] = value[i];
start += step; start += step;
......
...@@ -113,8 +113,9 @@ public: ...@@ -113,8 +113,9 @@ public:
static void cleanupAllInstances() { static void cleanupAllInstances() {
auto tmp = std::move(myobject4_instances); auto tmp = std::move(myobject4_instances);
myobject4_instances.clear(); myobject4_instances.clear();
for (auto o : tmp) for (auto o : tmp) {
delete o; delete o;
}
} }
private: private:
~MyObject4() { ~MyObject4() {
...@@ -140,8 +141,9 @@ public: ...@@ -140,8 +141,9 @@ public:
static void cleanupAllInstances() { static void cleanupAllInstances() {
auto tmp = std::move(myobject4a_instances); auto tmp = std::move(myobject4a_instances);
myobject4a_instances.clear(); myobject4a_instances.clear();
for (auto o : tmp) for (auto o : tmp) {
delete o; delete o;
}
} }
protected: protected:
virtual ~MyObject4a() { virtual ~MyObject4a() {
...@@ -445,8 +447,9 @@ TEST_SUBMODULE(smart_ptr, m) { ...@@ -445,8 +447,9 @@ TEST_SUBMODULE(smart_ptr, m) {
.def("add", &ElementList::add) .def("add", &ElementList::add)
.def("get", [](ElementList &el) { .def("get", [](ElementList &el) {
py::list list; py::list list;
for (auto &e : el.l) for (auto &e : el.l) {
list.append(py::cast(e)); list.append(py::cast(e));
}
return list; return list;
}); });
} }
...@@ -42,23 +42,27 @@ public: ...@@ -42,23 +42,27 @@ public:
template <class Container> Container *one_to_n(int n) { template <class Container> Container *one_to_n(int n) {
auto v = new Container(); auto v = new Container();
for (int i = 1; i <= n; i++) for (int i = 1; i <= n; i++) {
v->emplace_back(i); v->emplace_back(i);
}
return v; return v;
} }
template <class Map> Map *times_ten(int n) { template <class Map> Map *times_ten(int n) {
auto m = new Map(); auto m = new Map();
for (int i = 1; i <= n; i++) for (int i = 1; i <= n; i++) {
m->emplace(int(i), E_nc(10*i)); m->emplace(int(i), E_nc(10 * i));
}
return m; return m;
} }
template <class NestMap> NestMap *times_hundred(int n) { template <class NestMap> NestMap *times_hundred(int n) {
auto m = new NestMap(); auto m = new NestMap();
for (int i = 1; i <= n; i++) for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) for (int j = 1; j <= n; j++) {
(*m)[i].emplace(int(j*10), E_nc(100*j)); (*m)[i].emplace(int(j * 10), E_nc(100 * j));
}
}
return m; return m;
} }
...@@ -98,9 +102,11 @@ TEST_SUBMODULE(stl_binders, m) { ...@@ -98,9 +102,11 @@ TEST_SUBMODULE(stl_binders, m) {
m.def("get_nvnc", [](int n) m.def("get_nvnc", [](int n)
{ {
auto m = new std::map<int, std::vector<E_nc>>(); auto m = new std::map<int, std::vector<E_nc>>();
for (int i = 1; i <= n; i++) for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) for (int j = 1; j <= n; j++) {
(*m)[i].emplace_back(j); (*m)[i].emplace_back(j);
}
}
return m; return m;
}); });
py::bind_map<std::map<int, std::map<int, E_nc>>>(m, "MapMapENC"); 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) ...@@ -100,8 +100,12 @@ const std::type_info* Animal::type_of_kind(Kind kind)
case Kind::LastCat: break; case Kind::LastCat: break;
} }
if (kind >= Kind::Dog && kind <= Kind::LastDog) return &typeid(Dog); if (kind >= Kind::Dog && kind <= Kind::LastDog) {
if (kind >= Kind::Cat && kind <= Kind::LastCat) return &typeid(Cat); return &typeid(Dog);
}
if (kind >= Kind::Cat && kind <= Kind::LastCat) {
return &typeid(Cat);
}
return nullptr; return nullptr;
} }
......
...@@ -112,8 +112,9 @@ public: ...@@ -112,8 +112,9 @@ public:
void operator=(const NonCopyable &) = delete; void operator=(const NonCopyable &) = delete;
void operator=(NonCopyable &&) = delete; void operator=(NonCopyable &&) = delete;
std::string get_value() const { std::string get_value() const {
if (value) if (value) {
return std::to_string(*value); return std::to_string(*value);
}
return "(null)"; return "(null)";
} }
~NonCopyable() { print_destroyed(this); } ~NonCopyable() { print_destroyed(this); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment