Unverified Commit dac74ebd authored by Aaron Gokaslan's avatar Aaron Gokaslan Committed by GitHub
Browse files

fix(clang-tidy): performance fixes applied in tests and CI (#3051)

* Initial fixes

* Whoops

* Finish clang-tidy manual fixes

* Add two missing fixes

* Revert

* Update clang-tidy

* Try to fix unreachable code error

* Move nolint comment

* Apply missing fix

* Don't override clang-tidy config

* Does this fix clang-tidy?

* Make all clang-tidy errors visible

* Add comments about NOLINTs and remove a few

* Fix typo
parent 3b30b0a5
......@@ -17,15 +17,14 @@
#include <iostream>
#include <thread>
void noisy_function(std::string msg, bool flush) {
void noisy_function(const std::string &msg, bool flush) {
std::cout << msg;
if (flush)
std::cout << std::flush;
}
void noisy_funct_dual(std::string msg, std::string emsg) {
void noisy_funct_dual(const std::string &msg, const std::string &emsg) {
std::cout << msg;
std::cerr << emsg;
}
......@@ -70,12 +69,12 @@ TEST_SUBMODULE(iostream, m) {
// test_evals
m.def("captured_output_default", [](std::string msg) {
m.def("captured_output_default", [](const std::string &msg) {
py::scoped_ostream_redirect redir;
std::cout << msg << std::flush;
});
m.def("captured_output", [](std::string msg) {
m.def("captured_output", [](const std::string &msg) {
py::scoped_ostream_redirect redir(std::cout, py::module_::import("sys").attr("stdout"));
std::cout << msg << std::flush;
});
......@@ -84,7 +83,7 @@ TEST_SUBMODULE(iostream, m) {
py::call_guard<py::scoped_ostream_redirect>(),
py::arg("msg"), py::arg("flush")=true);
m.def("captured_err", [](std::string msg) {
m.def("captured_err", [](const std::string &msg) {
py::scoped_ostream_redirect redir(std::cerr, py::module_::import("sys").attr("stderr"));
std::cerr << msg << std::flush;
});
......@@ -95,15 +94,11 @@ TEST_SUBMODULE(iostream, m) {
py::call_guard<py::scoped_ostream_redirect, py::scoped_estream_redirect>(),
py::arg("msg"), py::arg("emsg"));
m.def("raw_output", [](std::string msg) {
std::cout << msg << std::flush;
});
m.def("raw_output", [](const std::string &msg) { std::cout << msg << std::flush; });
m.def("raw_err", [](std::string msg) {
std::cerr << msg << std::flush;
});
m.def("raw_err", [](const std::string &msg) { std::cerr << msg << std::flush; });
m.def("captured_dual", [](std::string msg, std::string emsg) {
m.def("captured_dual", [](const std::string &msg, const std::string &emsg) {
py::scoped_ostream_redirect redirout(std::cout, py::module_::import("sys").attr("stdout"));
py::scoped_ostream_redirect redirerr(std::cerr, py::module_::import("sys").attr("stderr"));
std::cout << msg << std::flush;
......
......@@ -11,6 +11,8 @@
#include "constructor_stats.h"
#include <pybind11/stl.h>
#include <utility>
TEST_SUBMODULE(kwargs_and_defaults, m) {
auto kw_func = [](int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); };
......@@ -37,18 +39,16 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
m.def("args_function", [](py::args args) -> py::tuple {
return std::move(args);
});
m.def("args_kwargs_function", [](py::args args, py::kwargs kwargs) {
m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) {
return py::make_tuple(args, kwargs);
});
// test_mixed_args_and_kwargs
m.def("mixed_plus_args", [](int i, double j, py::args args) {
return py::make_tuple(i, j, args);
});
m.def("mixed_plus_kwargs", [](int i, double j, py::kwargs kwargs) {
return py::make_tuple(i, j, kwargs);
});
auto mixed_plus_both = [](int i, double j, py::args args, py::kwargs kwargs) {
m.def("mixed_plus_args",
[](int i, double j, const py::args &args) { return py::make_tuple(i, j, args); });
m.def("mixed_plus_kwargs",
[](int i, double j, const py::kwargs &kwargs) { return py::make_tuple(i, j, kwargs); });
auto mixed_plus_both = [](int i, double j, const py::args &args, const py::kwargs &kwargs) {
return py::make_tuple(i, j, args, kwargs);
};
m.def("mixed_plus_args_kwargs", mixed_plus_both);
......@@ -65,6 +65,8 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
#endif
m.def("arg_refcount_h", [](py::handle h) { GC_IF_NEEDED; return h.ref_count(); });
m.def("arg_refcount_h", [](py::handle h, py::handle, py::handle) { GC_IF_NEEDED; return h.ref_count(); });
// TODO replace the following nolints as appropiate
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("arg_refcount_o", [](py::object o) { GC_IF_NEEDED; return o.ref_count(); });
m.def("args_refcount", [](py::args a) {
GC_IF_NEEDED;
......@@ -74,6 +76,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
return t;
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("mixed_args_refcount", [](py::object o, py::args a) {
GC_IF_NEEDED;
py::tuple t(a.size() + 1);
......@@ -103,6 +106,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
py::arg() = 3, "j"_a = 4, py::kw_only(), "k"_a = 5, "z"_a);
m.def("kw_only_mixed", [](int i, int j) { return py::make_tuple(i, j); },
"i"_a, py::kw_only(), "j"_a);
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("kw_only_plus_more", [](int i, int j, int k, py::kwargs kwargs) {
return py::make_tuple(i, j, k, kwargs); },
py::arg() /* positional */, py::arg("j") = -1 /* both */, py::kw_only(), py::arg("k") /* kw-only */);
......@@ -137,6 +141,8 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
// Make sure a class (not an instance) can be used as a default argument.
// The return value doesn't matter, only that the module is importable.
m.def("class_default_argument", [](py::object a) { return py::repr(a); },
m.def(
"class_default_argument",
[](py::object a) { return py::repr(std::move(a)); },
"a"_a = py::module_::import("decimal").attr("Decimal"));
}
......@@ -86,6 +86,8 @@ TEST_SUBMODULE(local_bindings, m) {
m.def("return_self", [](LocalVec *v) { return v; });
m.def("return_copy", [](const LocalVec &v) { return LocalVec(v); });
// Reformatting this class broke pygrep checks
// NOLINTNEXTLINE
class Cat : public pets::Pet { public: Cat(std::string name) : Pet(name) {}; };
py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("get_name", &pets::Pet::name);
......
......@@ -22,14 +22,18 @@ public:
ExampleMandA(int value) : value(value) { print_created(this, value); }
ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); }
ExampleMandA(std::string&&) {}
ExampleMandA(ExampleMandA &&e) : value(e.value) { print_move_created(this); }
ExampleMandA(ExampleMandA &&e) noexcept : value(e.value) { print_move_created(this); }
~ExampleMandA() { print_destroyed(this); }
std::string toString() const { return "ExampleMandA[value=" + std::to_string(value) + "]"; }
void operator=(const ExampleMandA &e) { print_copy_assigned(this); value = e.value; }
void operator=(ExampleMandA &&e) { print_move_assigned(this); value = e.value; }
void operator=(ExampleMandA &&e) noexcept {
print_move_assigned(this);
value = e.value;
}
// NOLINTNEXTLINE(performance-unnecessary-value-param)
void add1(ExampleMandA other) { value += other.value; } // passing by value
void add2(ExampleMandA &other) { value += other.value; } // passing by reference
void add3(const ExampleMandA &other) { value += other.value; } // passing by const reference
......@@ -112,7 +116,7 @@ int none1(const NoneTester &obj) { return obj.answer; }
int none2(NoneTester *obj) { return obj ? obj->answer : -1; }
int none3(std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; }
int none4(std::shared_ptr<NoneTester> *obj) { return obj && *obj ? (*obj)->answer : -1; }
int none5(std::shared_ptr<NoneTester> obj) { return obj ? obj->answer : -1; }
int none5(const std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; }
struct StrIssue {
int val = -1;
......@@ -226,36 +230,41 @@ TEST_SUBMODULE(methods_and_attributes, m) {
.def(py::init<>())
.def_readonly("def_readonly", &TestProperties::value)
.def_readwrite("def_readwrite", &TestProperties::value)
.def_property("def_writeonly", nullptr,
[](TestProperties& s,int v) { s.value = v; } )
.def_property("def_writeonly", nullptr, [](TestProperties &s, int v) { s.value = v; })
.def_property("def_property_writeonly", nullptr, &TestProperties::set)
.def_property_readonly("def_property_readonly", &TestProperties::get)
.def_property("def_property", &TestProperties::get, &TestProperties::set)
.def_property("def_property_impossible", nullptr, nullptr)
.def_readonly_static("def_readonly_static", &TestProperties::static_value)
.def_readwrite_static("def_readwrite_static", &TestProperties::static_value)
.def_property_static("def_writeonly_static", nullptr,
[](py::object, int v) { TestProperties::static_value = v; })
.def_property_readonly_static("def_property_readonly_static",
[](py::object) { return TestProperties::static_get(); })
.def_property_static("def_property_writeonly_static", nullptr,
[](py::object, int v) { return TestProperties::static_set(v); })
.def_property_static("def_property_static",
[](py::object) { return TestProperties::static_get(); },
[](py::object, int v) { TestProperties::static_set(v); })
.def_property_static("static_cls",
[](py::object cls) { return cls; },
[](py::object cls, py::function f) { f(cls); });
.def_property_static("def_writeonly_static",
nullptr,
[](const py::object &, int v) { TestProperties::static_value = v; })
.def_property_readonly_static(
"def_property_readonly_static",
[](const py::object &) { return TestProperties::static_get(); })
.def_property_static(
"def_property_writeonly_static",
nullptr,
[](const py::object &, int v) { return TestProperties::static_set(v); })
.def_property_static(
"def_property_static",
[](const py::object &) { return TestProperties::static_get(); },
[](const py::object &, int v) { TestProperties::static_set(v); })
.def_property_static(
"static_cls",
[](py::object cls) { return cls; },
[](const py::object &cls, const py::function &f) { f(cls); });
py::class_<TestPropertiesOverride, TestProperties>(m, "TestPropertiesOverride")
.def(py::init<>())
.def_readonly("def_readonly", &TestPropertiesOverride::value)
.def_readonly_static("def_readonly_static", &TestPropertiesOverride::static_value);
auto static_get1 = [](py::object) -> const UserType & { return TestPropRVP::sv1; };
auto static_get2 = [](py::object) -> const UserType & { return TestPropRVP::sv2; };
auto static_set1 = [](py::object, int v) { TestPropRVP::sv1.set(v); };
auto static_set2 = [](py::object, int v) { TestPropRVP::sv2.set(v); };
auto static_get1 = [](const py::object &) -> const UserType & { return TestPropRVP::sv1; };
auto static_get2 = [](const py::object &) -> const UserType & { return TestPropRVP::sv2; };
auto static_set1 = [](const py::object &, int v) { TestPropRVP::sv1.set(v); };
auto static_set2 = [](const py::object &, int v) { TestPropRVP::sv2.set(v); };
auto rvp_copy = py::return_value_policy::copy;
// test_property_return_value_policies
......@@ -266,24 +275,30 @@ TEST_SUBMODULE(methods_and_attributes, m) {
.def_property_readonly("ro_func", py::cpp_function(&TestPropRVP::get2, rvp_copy))
.def_property("rw_ref", &TestPropRVP::get1, &TestPropRVP::set1)
.def_property("rw_copy", &TestPropRVP::get2, &TestPropRVP::set2, rvp_copy)
.def_property("rw_func", py::cpp_function(&TestPropRVP::get2, rvp_copy), &TestPropRVP::set2)
.def_property(
"rw_func", py::cpp_function(&TestPropRVP::get2, rvp_copy), &TestPropRVP::set2)
.def_property_readonly_static("static_ro_ref", static_get1)
.def_property_readonly_static("static_ro_copy", static_get2, rvp_copy)
.def_property_readonly_static("static_ro_func", py::cpp_function(static_get2, rvp_copy))
.def_property_static("static_rw_ref", static_get1, static_set1)
.def_property_static("static_rw_copy", static_get2, static_set2, rvp_copy)
.def_property_static("static_rw_func", py::cpp_function(static_get2, rvp_copy), static_set2)
.def_property_static(
"static_rw_func", py::cpp_function(static_get2, rvp_copy), static_set2)
// test_property_rvalue_policy
.def_property_readonly("rvalue", &TestPropRVP::get_rvalue)
// NOLINTNEXTLINE(performance-unnecessary-value-param)
.def_property_readonly_static("static_rvalue", [](py::object) { return UserType(1); });
// test_metaclass_override
struct MetaclassOverride { };
py::class_<MetaclassOverride>(m, "MetaclassOverride", py::metaclass((PyObject *) &PyType_Type))
// NOLINTNEXTLINE(performance-unnecessary-value-param)
.def_property_readonly_static("readonly", [](py::object) { return 1; });
// test_overload_ordering
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("overload_order", [](std::string) { return 1; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("overload_order", [](std::string) { return 2; });
m.def("overload_order", [](int) { return 3; });
m.def("overload_order", [](int) { return 4; }, py::prepend{});
......
......@@ -141,6 +141,7 @@ TEST_SUBMODULE(multiple_inheritance, m) {
.def(py::init<int, int>());
m.def("bar_base2a", [](Base2a *b) { return b->bar(); });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("bar_base2a_sharedptr", [](std::shared_ptr<Base2a> b) { return b->bar(); });
// test_mi_unaligned_base
......
......@@ -13,6 +13,7 @@
#include <pybind11/stl.h>
#include <cstdint>
#include <utility>
// Size / dtype checks.
struct DtypeCheck {
......@@ -192,7 +193,7 @@ TEST_SUBMODULE(numpy_array, sm) {
sm.def("scalar_int", []() { return py::array(py::dtype("i"), {}, {}, &data_i); });
// test_wrap
sm.def("wrap", [](py::array a) {
sm.def("wrap", [](const py::array &a) {
return py::array(
a.dtype(),
{a.shape(), a.shape() + a.ndim()},
......@@ -222,8 +223,10 @@ TEST_SUBMODULE(numpy_array, sm) {
// test_isinstance
sm.def("isinstance_untyped", [](py::object yes, py::object no) {
return py::isinstance<py::array>(yes) && !py::isinstance<py::array>(no);
return py::isinstance<py::array>(std::move(yes))
&& !py::isinstance<py::array>(std::move(no));
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("isinstance_typed", [](py::object o) {
return py::isinstance<py::array_t<double>>(o) && !py::isinstance<py::array_t<int>>(o);
});
......@@ -236,7 +239,7 @@ TEST_SUBMODULE(numpy_array, sm) {
"array_t<double>"_a=py::array_t<double>()
);
});
sm.def("converting_constructors", [](py::object o) {
sm.def("converting_constructors", [](const py::object &o) {
return py::dict(
"array"_a=py::array(o),
"array_t<int32>"_a=py::array_t<std::int32_t>(o),
......@@ -245,39 +248,59 @@ TEST_SUBMODULE(numpy_array, sm) {
});
// test_overload_resolution
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<double>) { return "double"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<float>) { return "float"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<int>) { return "int"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<unsigned short>) { return "unsigned short"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<long long>) { return "long long"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<std::complex<double>>) { return "double complex"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded", [](py::array_t<std::complex<float>>) { return "float complex"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded2", [](py::array_t<std::complex<double>>) { return "double complex"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded2", [](py::array_t<double>) { return "double"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded2", [](py::array_t<std::complex<float>>) { return "float complex"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded2", [](py::array_t<float>) { return "float"; });
// [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
// Only accept the exact types:
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded3", [](py::array_t<int>) { return "int"; }, py::arg{}.noconvert());
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded3", [](py::array_t<double>) { return "double"; }, py::arg{}.noconvert());
// Make sure we don't do unsafe coercion (e.g. float to int) when not using forcecast, but
// rather that float gets converted via the safe (conversion to double) overload:
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded4", [](py::array_t<long long, 0>) { return "long long"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded4", [](py::array_t<double, 0>) { return "double"; });
// But we do allow conversion to int if forcecast is enabled (but only if no overload matches
// without conversion)
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded5", [](py::array_t<unsigned int>) { return "unsigned int"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("overloaded5", [](py::array_t<double>) { return "double"; });
// test_greedy_string_overload
// Issue 685: ndarray shouldn't go to std::string overload
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("issue685", [](std::string) { return "string"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("issue685", [](py::array) { return "array"; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("issue685", [](py::object) { return "other"; });
// test_array_unchecked_fixed_dims
......@@ -306,7 +329,7 @@ TEST_SUBMODULE(numpy_array, sm) {
r(i, j, k) = start++;
return a;
});
sm.def("proxy_squared_L2_norm", [](py::array_t<double> a) {
sm.def("proxy_squared_L2_norm", [](const py::array_t<double> &a) {
auto r = a.unchecked<1>();
double sumsq = 0;
for (py::ssize_t i = 0; i < r.shape(0); i++)
......@@ -396,51 +419,78 @@ TEST_SUBMODULE(numpy_array, sm) {
return a;
});
sm.def("index_using_ellipsis", [](py::array a) {
return a[py::make_tuple(0, py::ellipsis(), 0)];
});
sm.def("index_using_ellipsis",
[](const py::array &a) { return a[py::make_tuple(0, py::ellipsis(), 0)]; });
// test_argument_conversions
sm.def("accept_double",
[](py::array_t<double, 0>) {},
py::arg("a"));
sm.def("accept_double_forcecast",
[](py::array_t<double, py::array::forcecast>) {},
py::arg("a"));
sm.def("accept_double_c_style",
[](py::array_t<double, py::array::c_style>) {},
py::arg("a"));
sm.def("accept_double_c_style_forcecast",
[](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
py::arg("a"));
sm.def("accept_double_f_style",
[](py::array_t<double, py::array::f_style>) {},
py::arg("a"));
sm.def("accept_double_f_style_forcecast",
[](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
py::arg("a"));
sm.def("accept_double_noconvert",
[](py::array_t<double, 0>) {},
"a"_a.noconvert());
sm.def("accept_double_forcecast_noconvert",
[](py::array_t<double, py::array::forcecast>) {},
"a"_a.noconvert());
sm.def("accept_double_c_style_noconvert",
[](py::array_t<double, py::array::c_style>) {},
"a"_a.noconvert());
sm.def("accept_double_c_style_forcecast_noconvert",
[](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
"a"_a.noconvert());
sm.def("accept_double_f_style_noconvert",
[](py::array_t<double, py::array::f_style>) {},
"a"_a.noconvert());
sm.def("accept_double_f_style_forcecast_noconvert",
[](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
"a"_a.noconvert());
sm.def(
"accept_double",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, 0>) {},
py::arg("a"));
sm.def(
"accept_double_forcecast",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::forcecast>) {},
py::arg("a"));
sm.def(
"accept_double_c_style",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::c_style>) {},
py::arg("a"));
sm.def(
"accept_double_c_style_forcecast",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
py::arg("a"));
sm.def(
"accept_double_f_style",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::f_style>) {},
py::arg("a"));
sm.def(
"accept_double_f_style_forcecast",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
py::arg("a"));
sm.def(
"accept_double_noconvert",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, 0>) {},
"a"_a.noconvert());
sm.def(
"accept_double_forcecast_noconvert",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::forcecast>) {},
"a"_a.noconvert());
sm.def(
"accept_double_c_style_noconvert",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::c_style>) {},
"a"_a.noconvert());
sm.def(
"accept_double_c_style_forcecast_noconvert",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
"a"_a.noconvert());
sm.def(
"accept_double_f_style_noconvert",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::f_style>) {},
"a"_a.noconvert());
sm.def(
"accept_double_f_style_forcecast_noconvert",
// NOLINTNEXTLINE(performance-unnecessary-value-param)
[](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
"a"_a.noconvert());
// Check that types returns correct npy format descriptor
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("test_fmt_desc_float", [](py::array_t<float>) {});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("test_fmt_desc_double", [](py::array_t<double>) {});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("test_fmt_desc_const_float", [](py::array_t<const float>) {});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
sm.def("test_fmt_desc_const_double", [](py::array_t<const double>) {});
}
......@@ -266,10 +266,11 @@ TEST_SUBMODULE(numpy_dtypes, m) {
.def_readwrite("uint_", &SimpleStruct::uint_)
.def_readwrite("float_", &SimpleStruct::float_)
.def_readwrite("ldbl_", &SimpleStruct::ldbl_)
.def("astuple", [](const SimpleStruct& self) {
return py::make_tuple(self.bool_, self.uint_, self.float_, self.ldbl_);
})
.def_static("fromtuple", [](const py::tuple tup) {
.def("astuple",
[](const SimpleStruct &self) {
return py::make_tuple(self.bool_, self.uint_, self.float_, self.ldbl_);
})
.def_static("fromtuple", [](const py::tuple &tup) {
if (py::len(tup) != 4) {
throw py::cast_error("Invalid size");
}
......
......@@ -11,6 +11,8 @@
#include "pybind11_tests.h"
#include <pybind11/numpy.h>
#include <utility>
double my_func(int x, float y, double z) {
py::print("my_func(x:int={}, y:float={:.0f}, z:float={:.0f})"_s.format(x, y, z));
return (float) x*y*z;
......@@ -25,11 +27,10 @@ TEST_SUBMODULE(numpy_vectorize, m) {
m.def("vectorized_func", py::vectorize(my_func));
// Vectorize a lambda function with a capture object (e.g. to exclude some arguments from the vectorization)
m.def("vectorized_func2",
[](py::array_t<int> x, py::array_t<float> y, float z) {
return py::vectorize([z](int x, float y) { return my_func(x, y, z); })(x, y);
}
);
m.def("vectorized_func2", [](py::array_t<int> x, py::array_t<float> y, float z) {
return py::vectorize([z](int x, float y) { return my_func(x, y, z); })(std::move(x),
std::move(y));
});
// Vectorize a complex-valued function
m.def("vectorized_func3", py::vectorize(
......@@ -38,8 +39,12 @@ TEST_SUBMODULE(numpy_vectorize, m) {
// test_type_selection
// NumPy function which only accepts specific data types
// Alot of these no lints could be replaced with const refs, and probably should at some point.
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { return "Int branch taken."; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { return "Float branch taken."; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { return "Complex float branch taken."; });
......@@ -53,11 +58,16 @@ TEST_SUBMODULE(numpy_vectorize, m) {
py::class_<NonPODClass>(m, "NonPODClass")
.def(py::init<int>())
.def_readwrite("value", &NonPODClass::value);
m.def("vec_passthrough", py::vectorize(
[](double *a, double b, py::array_t<double> c, const int &d, int &e, NonPODClass f, const double g) {
return *a + b + c.at(0) + d + e + f.value + g;
}
));
m.def("vec_passthrough",
py::vectorize([](double *a,
double b,
// Changing this broke things
// NOLINTNEXTLINE(performance-unnecessary-value-param)
py::array_t<double> c,
const int &d,
int &e,
NonPODClass f,
const double g) { return *a + b + c.at(0) + d + e + f.value + g; }));
// test_method_vectorization
struct VectorizeTestClass {
......@@ -78,16 +88,20 @@ TEST_SUBMODULE(numpy_vectorize, m) {
.value("f_trivial", py::detail::broadcast_trivial::f_trivial)
.value("c_trivial", py::detail::broadcast_trivial::c_trivial)
.value("non_trivial", py::detail::broadcast_trivial::non_trivial);
m.def("vectorized_is_trivial", [](
py::array_t<int, py::array::forcecast> arg1,
py::array_t<float, py::array::forcecast> arg2,
py::array_t<double, py::array::forcecast> arg3
) {
py::ssize_t ndim;
std::vector<py::ssize_t> shape;
std::array<py::buffer_info, 3> buffers {{ arg1.request(), arg2.request(), arg3.request() }};
return py::detail::broadcast(buffers, ndim, shape);
});
m.def("vectorized_is_trivial",
[](
// NOLINTNEXTLINE(performance-unnecessary-value-param)
py::array_t<int, py::array::forcecast> arg1,
// NOLINTNEXTLINE(performance-unnecessary-value-param)
py::array_t<float, py::array::forcecast> arg2,
// NOLINTNEXTLINE(performance-unnecessary-value-param)
py::array_t<double, py::array::forcecast> arg3) {
py::ssize_t ndim;
std::vector<py::ssize_t> shape;
std::array<py::buffer_info, 3> buffers{
{arg1.request(), arg2.request(), arg3.request()}};
return py::detail::broadcast(buffers, ndim, shape);
});
m.def("add_to", py::vectorize([](NonPODClass& x, int a) { x.value += a; }));
}
......@@ -44,7 +44,7 @@ TEST_SUBMODULE(opaque_types, m) {
m.def("print_opaque_list", [](const StringList &l) {
std::string ret = "Opaque list: [";
bool first = true;
for (auto entry : l) {
for (const auto &entry : l) {
if (!first)
ret += ", ";
ret += entry;
......
......@@ -16,9 +16,18 @@ class Vector2 {
public:
Vector2(float x, float y) : x(x), y(y) { print_created(this, toString()); }
Vector2(const Vector2 &v) : x(v.x), y(v.y) { print_copy_created(this); }
Vector2(Vector2 &&v) : x(v.x), y(v.y) { print_move_created(this); v.x = v.y = 0; }
Vector2(Vector2 &&v) noexcept : x(v.x), y(v.y) {
print_move_created(this);
v.x = v.y = 0;
}
Vector2 &operator=(const Vector2 &v) { x = v.x; y = v.y; print_copy_assigned(this); return *this; }
Vector2 &operator=(Vector2 &&v) { x = v.x; y = v.y; v.x = v.y = 0; print_move_assigned(this); return *this; }
Vector2 &operator=(Vector2 &&v) noexcept {
x = v.x;
y = v.y;
v.x = v.y = 0;
print_move_assigned(this);
return *this;
}
~Vector2() { print_destroyed(this); }
std::string toString() const { return "[" + std::to_string(x) + ", " + std::to_string(y) + "]"; }
......
......@@ -46,17 +46,16 @@ TEST_SUBMODULE(pickling, m) {
return py::make_tuple(p.value(), p.extra1(), p.extra2());
});
ignoreOldStyleInitWarnings([&pyPickleable]() {
pyPickleable
.def("__setstate__", [](Pickleable &p, py::tuple t) {
if (t.size() != 3)
throw std::runtime_error("Invalid state!");
/* Invoke the constructor (need to use in-place version) */
new (&p) Pickleable(t[0].cast<std::string>());
/* Assign any additional state */
p.setExtra1(t[1].cast<int>());
p.setExtra2(t[2].cast<int>());
});
pyPickleable.def("__setstate__", [](Pickleable &p, const py::tuple &t) {
if (t.size() != 3)
throw std::runtime_error("Invalid state!");
/* Invoke the constructor (need to use in-place version) */
new (&p) Pickleable(t[0].cast<std::string>());
/* Assign any additional state */
p.setExtra1(t[1].cast<int>());
p.setExtra2(t[2].cast<int>());
});
});
py::class_<PickleableNew, Pickleable>(m, "PickleableNew")
......@@ -65,7 +64,7 @@ TEST_SUBMODULE(pickling, m) {
[](const PickleableNew &p) {
return py::make_tuple(p.value(), p.extra1(), p.extra2());
},
[](py::tuple t) {
[](const py::tuple &t) {
if (t.size() != 3)
throw std::runtime_error("Invalid state!");
auto p = PickleableNew(t[0].cast<std::string>());
......@@ -73,8 +72,7 @@ TEST_SUBMODULE(pickling, m) {
p.setExtra1(t[1].cast<int>());
p.setExtra2(t[2].cast<int>());
return p;
}
));
}));
#if !defined(PYPY_VERSION)
// test_roundtrip_with_dict
......@@ -92,35 +90,33 @@ TEST_SUBMODULE(pickling, m) {
};
py::class_<PickleableWithDict> pyPickleableWithDict(m, "PickleableWithDict", py::dynamic_attr());
pyPickleableWithDict
.def(py::init<std::string>())
pyPickleableWithDict.def(py::init<std::string>())
.def_readwrite("value", &PickleableWithDict::value)
.def_readwrite("extra", &PickleableWithDict::extra)
.def("__getstate__", [](py::object self) {
.def("__getstate__", [](const py::object &self) {
/* Also include __dict__ in state */
return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
});
ignoreOldStyleInitWarnings([&pyPickleableWithDict]() {
pyPickleableWithDict
.def("__setstate__", [](py::object self, py::tuple t) {
if (t.size() != 3)
throw std::runtime_error("Invalid state!");
/* Cast and construct */
auto& p = self.cast<PickleableWithDict&>();
new (&p) PickleableWithDict(t[0].cast<std::string>());
/* Assign C++ state */
p.extra = t[1].cast<int>();
/* Assign Python state */
self.attr("__dict__") = t[2];
});
pyPickleableWithDict.def("__setstate__", [](const py::object &self, const py::tuple &t) {
if (t.size() != 3)
throw std::runtime_error("Invalid state!");
/* Cast and construct */
auto &p = self.cast<PickleableWithDict &>();
new (&p) PickleableWithDict(t[0].cast<std::string>());
/* Assign C++ state */
p.extra = t[1].cast<int>();
/* Assign Python state */
self.attr("__dict__") = t[2];
});
});
py::class_<PickleableWithDictNew, PickleableWithDict>(m, "PickleableWithDictNew")
.def(py::init<std::string>())
.def(py::pickle(
[](py::object self) {
[](const py::object &self) {
return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
},
[](const py::tuple &t) {
......@@ -132,7 +128,6 @@ TEST_SUBMODULE(pickling, m) {
auto py_state = t[2].cast<py::dict>();
return std::make_pair(cpp_state, py_state);
}
));
}));
#endif
}
......@@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/
#include <utility>
#include "pybind11_tests.h"
......@@ -27,16 +29,14 @@ TEST_SUBMODULE(pytypes, m) {
list.insert(2, "inserted-2");
return list;
});
m.def("print_list", [](py::list list) {
m.def("print_list", [](const py::list &list) {
int index = 0;
for (auto item : list)
py::print("list item {}: {}"_s.format(index++, item));
});
// test_none
m.def("get_none", []{return py::none();});
m.def("print_none", [](py::none none) {
py::print("none: {}"_s.format(none));
});
m.def("print_none", [](const py::none &none) { py::print("none: {}"_s.format(none)); });
// test_set
m.def("get_set", []() {
......@@ -46,20 +46,17 @@ TEST_SUBMODULE(pytypes, m) {
set.add(std::string("key3"));
return set;
});
m.def("print_set", [](py::set set) {
m.def("print_set", [](const py::set &set) {
for (auto item : set)
py::print("key:", item);
});
m.def("set_contains", [](py::set set, py::object key) {
return set.contains(key);
});
m.def("set_contains", [](py::set set, const char* key) {
return set.contains(key);
});
m.def("set_contains",
[](const py::set &set, const py::object &key) { return set.contains(key); });
m.def("set_contains", [](const py::set &set, const char *key) { return set.contains(key); });
// test_dict
m.def("get_dict", []() { return py::dict("key"_a="value"); });
m.def("print_dict", [](py::dict dict) {
m.def("print_dict", [](const py::dict &dict) {
for (auto item : dict)
py::print("key: {}, value={}"_s.format(item.first, item.second));
});
......@@ -68,12 +65,10 @@ TEST_SUBMODULE(pytypes, m) {
auto d2 = py::dict("z"_a=3, **d1);
return d2;
});
m.def("dict_contains", [](py::dict dict, py::object val) {
return dict.contains(val);
});
m.def("dict_contains", [](py::dict dict, const char* val) {
return dict.contains(val);
});
m.def("dict_contains",
[](const py::dict &dict, py::object val) { return dict.contains(val); });
m.def("dict_contains",
[](const py::dict &dict, const char *val) { return dict.contains(val); });
// test_str
m.def("str_from_string", []() { return py::str(std::string("baz")); });
......@@ -137,7 +132,7 @@ TEST_SUBMODULE(pytypes, m) {
});
// test_accessors
m.def("accessor_api", [](py::object o) {
m.def("accessor_api", [](const py::object &o) {
auto d = py::dict();
d["basic_attr"] = o.attr("basic_attr");
......@@ -178,7 +173,7 @@ TEST_SUBMODULE(pytypes, m) {
return d;
});
m.def("tuple_accessor", [](py::tuple existing_t) {
m.def("tuple_accessor", [](const py::tuple &existing_t) {
try {
existing_t[0] = 1;
} catch (const py::error_already_set &) {
......@@ -226,7 +221,7 @@ TEST_SUBMODULE(pytypes, m) {
);
});
m.def("converting_constructors", [](py::dict d) {
m.def("converting_constructors", [](const py::dict &d) {
return py::dict(
"bytes"_a=py::bytes(d["bytes"]),
"bytearray"_a=py::bytearray(d["bytearray"]),
......@@ -242,6 +237,7 @@ TEST_SUBMODULE(pytypes, m) {
);
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("cast_functions", [](py::dict d) {
// When converting between Python types, obj.cast<T>() should be the same as T(obj)
return py::dict(
......@@ -259,8 +255,10 @@ TEST_SUBMODULE(pytypes, m) {
);
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("convert_to_pybind11_str", [](py::object o) { return py::str(o); });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("nonconverting_constructor", [](std::string type, py::object value, bool move) -> py::object {
if (type == "bytes") {
return move ? py::bytes(std::move(value)) : py::bytes(value);
......@@ -333,8 +331,9 @@ TEST_SUBMODULE(pytypes, m) {
m.def("print_failure", []() { py::print(42, UnregisteredType()); });
m.def("hash_function", [](py::object obj) { return py::hash(obj); });
m.def("hash_function", [](py::object obj) { return py::hash(std::move(obj)); });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("test_number_protocol", [](py::object a, py::object b) {
py::list l;
l.append(a.equal(b));
......@@ -355,6 +354,7 @@ TEST_SUBMODULE(pytypes, m) {
return l;
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("test_list_slicing", [](py::list a) {
return a[py::slice(0, -1, 2)];
});
......@@ -369,10 +369,12 @@ TEST_SUBMODULE(pytypes, m) {
return is_this_none;
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("test_memoryview_object", [](py::buffer b) {
return py::memoryview(b);
});
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("test_memoryview_buffer_info", [](py::buffer b) {
return py::memoryview(b.request());
});
......@@ -425,20 +427,22 @@ TEST_SUBMODULE(pytypes, m) {
m.attr("PYBIND11_STR_LEGACY_PERMISSIVE") = true;
#endif
m.def("isinstance_pybind11_bytes", [](py::object o) { return py::isinstance<py::bytes>(o); });
m.def("isinstance_pybind11_str", [](py::object o) { return py::isinstance<py::str>(o); });
m.def("isinstance_pybind11_bytes",
[](py::object o) { return py::isinstance<py::bytes>(std::move(o)); });
m.def("isinstance_pybind11_str",
[](py::object o) { return py::isinstance<py::str>(std::move(o)); });
m.def("pass_to_pybind11_bytes", [](py::bytes b) { return py::len(b); });
m.def("pass_to_pybind11_str", [](py::str s) { return py::len(s); });
m.def("pass_to_pybind11_bytes", [](py::bytes b) { return py::len(std::move(b)); });
m.def("pass_to_pybind11_str", [](py::str s) { return py::len(std::move(s)); });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("pass_to_std_string", [](std::string s) { return s.size(); });
// test_weakref
m.def("weakref_from_handle",
[](py::handle h) { return py::weakref(h); });
m.def("weakref_from_handle_and_function",
[](py::handle h, py::function f) { return py::weakref(h, f); });
m.def("weakref_from_object",
[](py::object o) { return py::weakref(o); });
[](py::handle h, py::function f) { return py::weakref(h, std::move(f)); });
m.def("weakref_from_object", [](const py::object &o) { return py::weakref(o); });
m.def("weakref_from_object_and_function",
[](py::object o, py::function f) { return py::weakref(o, f); });
[](py::object o, py::function f) { return py::weakref(std::move(o), std::move(f)); });
}
......@@ -14,6 +14,7 @@
#include <pybind11/stl.h>
#include <algorithm>
#include <utility>
template<typename T>
class NonZeroIterator {
......@@ -80,18 +81,17 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
int start,stop,step;
int size;
};
py::class_<Sliceable>(m,"Sliceable")
py::class_<Sliceable>(m, "Sliceable")
.def(py::init<int>())
.def("__getitem__",[](const Sliceable &s, py::slice slice) {
py::ssize_t start, stop, step, slicelength;
if (!slice.compute(s.size, &start, &stop, &step, &slicelength))
throw py::error_already_set();
int istart = static_cast<int>(start);
int istop = static_cast<int>(stop);
int istep = static_cast<int>(step);
return std::make_tuple(istart,istop,istep);
})
;
.def("__getitem__", [](const Sliceable &s, const py::slice &slice) {
py::ssize_t start, stop, step, slicelength;
if (!slice.compute(s.size, &start, &stop, &step, &slicelength))
throw py::error_already_set();
int istart = static_cast<int>(start);
int istop = static_cast<int>(stop);
int istep = static_cast<int>(step);
return std::make_tuple(istart, istop, istep);
});
// test_sequence
class Sequence {
......@@ -111,7 +111,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
m_data = new float[m_size];
memcpy(m_data, s.m_data, sizeof(float)*m_size);
}
Sequence(Sequence &&s) : m_size(s.m_size), m_data(s.m_data) {
Sequence(Sequence &&s) noexcept : m_size(s.m_size), m_data(s.m_data) {
print_move_created(this);
s.m_size = 0;
s.m_data = nullptr;
......@@ -130,7 +130,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
return *this;
}
Sequence &operator=(Sequence &&s) {
Sequence &operator=(Sequence &&s) noexcept {
if (&s != this) {
delete[] m_data;
m_size = s.m_size;
......@@ -179,43 +179,54 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
};
py::class_<Sequence>(m, "Sequence")
.def(py::init<size_t>())
.def(py::init<const std::vector<float>&>())
.def(py::init<const std::vector<float> &>())
/// Bare bones interface
.def("__getitem__", [](const Sequence &s, size_t i) {
if (i >= s.size()) throw py::index_error();
return s[i];
})
.def("__setitem__", [](Sequence &s, size_t i, float v) {
if (i >= s.size()) throw py::index_error();
s[i] = v;
})
.def("__getitem__",
[](const Sequence &s, size_t i) {
if (i >= s.size())
throw py::index_error();
return s[i];
})
.def("__setitem__",
[](Sequence &s, size_t i, float v) {
if (i >= s.size())
throw py::index_error();
s[i] = v;
})
.def("__len__", &Sequence::size)
/// Optional sequence protocol operations
.def("__iter__", [](const Sequence &s) { return py::make_iterator(s.begin(), s.end()); },
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)
.def(
"__iter__",
[](const Sequence &s) { return py::make_iterator(s.begin(), s.end()); },
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)
.def("__contains__", [](const Sequence &s, float v) { return s.contains(v); })
.def("__reversed__", [](const Sequence &s) -> Sequence { return s.reversed(); })
/// Slicing protocol (optional)
.def("__getitem__", [](const Sequence &s, py::slice slice) -> Sequence* {
size_t start, stop, step, slicelength;
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
auto *seq = new Sequence(slicelength);
for (size_t i = 0; i < slicelength; ++i) {
(*seq)[i] = s[start]; start += step;
}
return seq;
})
.def("__setitem__", [](Sequence &s, py::slice slice, const Sequence &value) {
size_t start, stop, step, slicelength;
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
if (slicelength != value.size())
throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
for (size_t i = 0; i < slicelength; ++i) {
s[start] = value[i]; start += step;
}
})
.def("__getitem__",
[](const Sequence &s, const py::slice &slice) -> Sequence * {
size_t start, stop, step, slicelength;
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
auto *seq = new Sequence(slicelength);
for (size_t i = 0; i < slicelength; ++i) {
(*seq)[i] = s[start];
start += step;
}
return seq;
})
.def("__setitem__",
[](Sequence &s, const py::slice &slice, const Sequence &value) {
size_t start, stop, step, slicelength;
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
if (slicelength != value.size())
throw std::runtime_error(
"Left and right hand size of slice assignment have different sizes!");
for (size_t i = 0; i < slicelength; ++i) {
s[start] = value[i];
start += step;
}
})
/// Comparisons
.def(py::self == py::self)
.def(py::self != py::self)
......@@ -231,8 +242,8 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
StringMap(std::unordered_map<std::string, std::string> init)
: map(std::move(init)) {}
void set(std::string key, std::string val) { map[key] = val; }
std::string get(std::string key) const { return map.at(key); }
void set(const std::string &key, std::string val) { map[key] = std::move(val); }
std::string get(const std::string &key) const { return map.at(key); }
size_t size() const { return map.size(); }
private:
std::unordered_map<std::string, std::string> map;
......@@ -243,19 +254,24 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
py::class_<StringMap>(m, "StringMap")
.def(py::init<>())
.def(py::init<std::unordered_map<std::string, std::string>>())
.def("__getitem__", [](const StringMap &map, std::string key) {
try { return map.get(key); }
catch (const std::out_of_range&) {
throw py::key_error("key '" + key + "' does not exist");
}
})
.def("__getitem__",
[](const StringMap &map, const std::string &key) {
try {
return map.get(key);
} catch (const std::out_of_range &) {
throw py::key_error("key '" + key + "' does not exist");
}
})
.def("__setitem__", &StringMap::set)
.def("__len__", &StringMap::size)
.def("__iter__", [](const StringMap &map) { return py::make_key_iterator(map.begin(), map.end()); },
py::keep_alive<0, 1>())
.def("items", [](const StringMap &map) { return py::make_iterator(map.begin(), map.end()); },
py::keep_alive<0, 1>())
;
.def(
"__iter__",
[](const StringMap &map) { return py::make_key_iterator(map.begin(), map.end()); },
py::keep_alive<0, 1>())
.def(
"items",
[](const StringMap &map) { return py::make_iterator(map.begin(), map.end()); },
py::keep_alive<0, 1>());
// test_generalized_iterators
class IntPairs {
......@@ -304,7 +320,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
#endif
// test_python_iterator_in_cpp
m.def("object_to_list", [](py::object o) {
m.def("object_to_list", [](const py::object &o) {
auto l = py::list();
for (auto item : o) {
l.append(item);
......@@ -322,22 +338,22 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
});
// test_sequence_length: check that Python sequences can be converted to py::sequence.
m.def("sequence_length", [](py::sequence seq) { return seq.size(); });
m.def("sequence_length", [](const py::sequence &seq) { return seq.size(); });
// Make sure that py::iterator works with std algorithms
m.def("count_none", [](py::object o) {
m.def("count_none", [](const py::object &o) {
return std::count_if(o.begin(), o.end(), [](py::handle h) { return h.is_none(); });
});
m.def("find_none", [](py::object o) {
m.def("find_none", [](const py::object &o) {
auto it = std::find_if(o.begin(), o.end(), [](py::handle h) { return h.is_none(); });
return it->is_none();
});
m.def("count_nonzeros", [](py::dict d) {
return std::count_if(d.begin(), d.end(), [](std::pair<py::handle, py::handle> p) {
return p.second.cast<int>() != 0;
});
m.def("count_nonzeros", [](const py::dict &d) {
return std::count_if(d.begin(), d.end(), [](std::pair<py::handle, py::handle> p) {
return p.second.cast<int>() != 0;
});
});
m.def("tuple_iterator", &test_random_access_iterator<py::tuple>);
......
......@@ -170,7 +170,7 @@ struct SharedPtrRef {
struct A {
A() { print_created(this); }
A(const A &) { print_copy_created(this); }
A(A &&) { print_move_created(this); }
A(A &&) noexcept { print_move_created(this); }
~A() { print_destroyed(this); }
};
......@@ -183,7 +183,7 @@ struct SharedFromThisRef {
struct B : std::enable_shared_from_this<B> {
B() { print_created(this); }
B(const B &) : std::enable_shared_from_this<B>() { print_copy_created(this); }
B(B &&) : std::enable_shared_from_this<B>() { print_move_created(this); }
B(B &&) noexcept : std::enable_shared_from_this<B>() { print_move_created(this); }
~B() { print_destroyed(this); }
};
......@@ -209,7 +209,9 @@ struct C {
struct TypeForHolderWithAddressOf {
TypeForHolderWithAddressOf() { print_created(this); }
TypeForHolderWithAddressOf(const TypeForHolderWithAddressOf &) { print_copy_created(this); }
TypeForHolderWithAddressOf(TypeForHolderWithAddressOf &&) { print_move_created(this); }
TypeForHolderWithAddressOf(TypeForHolderWithAddressOf &&) noexcept {
print_move_created(this);
}
~TypeForHolderWithAddressOf() { print_destroyed(this); }
std::string toString() const {
return "TypeForHolderWithAddressOf[" + std::to_string(value) + "]";
......@@ -245,7 +247,7 @@ struct ElementA : ElementBase {
};
struct ElementList {
void add(std::shared_ptr<ElementBase> e) { l.push_back(e); }
void add(const std::shared_ptr<ElementBase> &e) { l.push_back(e); }
std::vector<std::shared_ptr<ElementBase>> l;
};
......@@ -308,6 +310,7 @@ TEST_SUBMODULE(smart_ptr, m) {
m.def("make_myobject2_1", []() { return new MyObject2(6); });
m.def("make_myobject2_2", []() { return std::make_shared<MyObject2>(7); });
m.def("print_myobject2_1", [](const MyObject2 *obj) { py::print(obj->toString()); });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("print_myobject2_2", [](std::shared_ptr<MyObject2> obj) { py::print(obj->toString()); });
m.def("print_myobject2_3", [](const std::shared_ptr<MyObject2> &obj) { py::print(obj->toString()); });
m.def("print_myobject2_4", [](const std::shared_ptr<MyObject2> *obj) { py::print((*obj)->toString()); });
......@@ -317,6 +320,7 @@ TEST_SUBMODULE(smart_ptr, m) {
m.def("make_myobject3_1", []() { return new MyObject3(8); });
m.def("make_myobject3_2", []() { return std::make_shared<MyObject3>(9); });
m.def("print_myobject3_1", [](const MyObject3 *obj) { py::print(obj->toString()); });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("print_myobject3_2", [](std::shared_ptr<MyObject3> obj) { py::print(obj->toString()); });
m.def("print_myobject3_3", [](const std::shared_ptr<MyObject3> &obj) { py::print(obj->toString()); });
m.def("print_myobject3_4", [](const std::shared_ptr<MyObject3> *obj) { py::print((*obj)->toString()); });
......@@ -358,12 +362,15 @@ TEST_SUBMODULE(smart_ptr, m) {
py::class_<SharedPtrRef, std::unique_ptr<SharedPtrRef>>(m, "SharedPtrRef")
.def(py::init<>())
.def_readonly("ref", &SharedPtrRef::value)
.def_property_readonly("copy", [](const SharedPtrRef &s) { return s.value; },
py::return_value_policy::copy)
.def_property_readonly(
"copy", [](const SharedPtrRef &s) { return s.value; }, py::return_value_policy::copy)
.def_readonly("holder_ref", &SharedPtrRef::shared)
.def_property_readonly("holder_copy", [](const SharedPtrRef &s) { return s.shared; },
py::return_value_policy::copy)
.def_property_readonly(
"holder_copy",
[](const SharedPtrRef &s) { return s.shared; },
py::return_value_policy::copy)
.def("set_ref", [](SharedPtrRef &, const A &) { return true; })
// NOLINTNEXTLINE(performance-unnecessary-value-param)
.def("set_holder", [](SharedPtrRef &, std::shared_ptr<A>) { return true; });
// test_shared_ptr_from_this_and_references
......@@ -372,13 +379,19 @@ TEST_SUBMODULE(smart_ptr, m) {
py::class_<SharedFromThisRef, std::unique_ptr<SharedFromThisRef>>(m, "SharedFromThisRef")
.def(py::init<>())
.def_readonly("bad_wp", &SharedFromThisRef::value)
.def_property_readonly("ref", [](const SharedFromThisRef &s) -> const B & { return *s.shared; })
.def_property_readonly("copy", [](const SharedFromThisRef &s) { return s.value; },
py::return_value_policy::copy)
.def_property_readonly("ref",
[](const SharedFromThisRef &s) -> const B & { return *s.shared; })
.def_property_readonly(
"copy",
[](const SharedFromThisRef &s) { return s.value; },
py::return_value_policy::copy)
.def_readonly("holder_ref", &SharedFromThisRef::shared)
.def_property_readonly("holder_copy", [](const SharedFromThisRef &s) { return s.shared; },
py::return_value_policy::copy)
.def_property_readonly(
"holder_copy",
[](const SharedFromThisRef &s) { return s.shared; },
py::return_value_policy::copy)
.def("set_ref", [](SharedFromThisRef &, const B &) { return true; })
// NOLINTNEXTLINE(performance-unnecessary-value-param)
.def("set_holder", [](SharedFromThisRef &, std::shared_ptr<B>) { return true; });
// Issue #865: shared_from_this doesn't work with virtual inheritance
......@@ -396,10 +409,14 @@ TEST_SUBMODULE(smart_ptr, m) {
py::class_<TypeForHolderWithAddressOf, HolderWithAddressOf>(m, "TypeForHolderWithAddressOf")
.def_static("make", []() { return HolderWithAddressOf(new TypeForHolderWithAddressOf); })
.def("get", [](const HolderWithAddressOf &self) { return self.get(); })
.def("print_object_1", [](const TypeForHolderWithAddressOf *obj) { py::print(obj->toString()); })
.def("print_object_1",
[](const TypeForHolderWithAddressOf *obj) { py::print(obj->toString()); })
// NOLINTNEXTLINE(performance-unnecessary-value-param)
.def("print_object_2", [](HolderWithAddressOf obj) { py::print(obj.get()->toString()); })
.def("print_object_3", [](const HolderWithAddressOf &obj) { py::print(obj.get()->toString()); })
.def("print_object_4", [](const HolderWithAddressOf *obj) { py::print((*obj).get()->toString()); });
.def("print_object_3",
[](const HolderWithAddressOf &obj) { py::print(obj.get()->toString()); })
.def("print_object_4",
[](const HolderWithAddressOf *obj) { py::print((*obj).get()->toString()); });
// test_move_only_holder_with_addressof_operator
using MoveOnlyHolderWithAddressOf = unique_ptr_with_addressof_operator<TypeForMoveOnlyHolderWithAddressOf>;
......@@ -411,6 +428,7 @@ TEST_SUBMODULE(smart_ptr, m) {
// test_smart_ptr_from_default
py::class_<HeldByDefaultHolder, std::unique_ptr<HeldByDefaultHolder>>(m, "HeldByDefaultHolder")
.def(py::init<>())
// NOLINTNEXTLINE(performance-unnecessary-value-param)
.def_static("load_shared_ptr", [](std::shared_ptr<HeldByDefaultHolder>) {});
// test_shared_ptr_gc
......
......@@ -202,6 +202,7 @@ TEST_SUBMODULE(stl, m) {
}, py::arg_v("x", std::nullopt, "None"));
m.def("nodefer_none_optional", [](std::optional<int>) { return true; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("nodefer_none_optional", [](py::none) { return false; });
using opt_holder = OptionalHolder<std::optional, MoveOutDetector>;
......@@ -245,13 +246,13 @@ TEST_SUBMODULE(stl, m) {
using result_type = const char *;
result_type operator()(int) { return "int"; }
result_type operator()(std::string) { return "std::string"; }
result_type operator()(const std::string &) { return "std::string"; }
result_type operator()(double) { return "double"; }
result_type operator()(std::nullptr_t) { return "std::nullptr_t"; }
};
// test_variant
m.def("load_variant", [](variant<int, std::string, double, std::nullptr_t> v) {
m.def("load_variant", [](const variant<int, std::string, double, std::nullptr_t> &v) {
return py::detail::visit_helper<variant>::call(visitor(), v);
});
m.def("load_variant_2pass", [](variant<double, int> v) {
......@@ -287,8 +288,11 @@ TEST_SUBMODULE(stl, m) {
m.def("stl_pass_by_pointer", [](std::vector<int>* v) { return *v; }, "v"_a=nullptr);
// #1258: pybind11/stl.h converts string to vector<string>
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("func_with_string_or_vector_string_arg_overload", [](std::vector<std::string>) { return 1; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("func_with_string_or_vector_string_arg_overload", [](std::list<std::string>) { return 2; });
// NOLINTNEXTLINE(performance-unnecessary-value-param)
m.def("func_with_string_or_vector_string_arg_overload", [](std::string) { return 3; });
class Placeholder {
......
......@@ -17,7 +17,10 @@ class ExampleVirt {
public:
ExampleVirt(int state) : state(state) { print_created(this, state); }
ExampleVirt(const ExampleVirt &e) : state(e.state) { print_copy_created(this); }
ExampleVirt(ExampleVirt &&e) : state(e.state) { print_move_created(this); e.state = 0; }
ExampleVirt(ExampleVirt &&e) noexcept : state(e.state) {
print_move_created(this);
e.state = 0;
}
virtual ~ExampleVirt() { print_destroyed(this); }
virtual int run(int value) {
......@@ -100,7 +103,10 @@ public:
class NonCopyable {
public:
NonCopyable(int a, int b) : value{new int(a*b)} { print_created(this, a, b); }
NonCopyable(NonCopyable &&o) { value = std::move(o.value); print_move_created(this); }
NonCopyable(NonCopyable &&o) noexcept {
value = std::move(o.value);
print_move_created(this);
}
NonCopyable(const NonCopyable &) = delete;
NonCopyable() = delete;
void operator=(const NonCopyable &) = delete;
......@@ -120,7 +126,10 @@ class Movable {
public:
Movable(int a, int b) : value{a+b} { print_created(this, a, b); }
Movable(const Movable &m) { value = m.value; print_copy_created(this); }
Movable(Movable &&m) { value = std::move(m.value); print_move_created(this); }
Movable(Movable &&m) noexcept {
value = m.value;
print_move_created(this);
}
std::string get_value() const { return std::to_string(value); }
~Movable() { print_destroyed(this); }
private:
......
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