mirror of
https://github.com/pybind/pybind11.git
synced 2026-04-20 14:59:27 +00:00
perf: Add object rvalue overload for accessors. Enables reference stealing (#3970)
* Add object rvalue overload for accessors. Enables reference stealing * Fix comments * Fix more comment typos * Fix bug * reorder declarations for clarity * fix another perf bug * should be static * future proof operator overloads * Fix perfect forwarding * Add a couple of tests * Remove errant include * Improve test documentation * Add dict test * add object attr tests * Optimize STL map caster and cleanup enum * Reorder to match declarations * adjust increfs * Remove comment * revert value change * add missing move
This commit is contained in:
@@ -661,4 +661,38 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
double v = x.get_value();
|
||||
return v * v;
|
||||
});
|
||||
|
||||
m.def("tuple_rvalue_getter", [](const py::tuple &tup) {
|
||||
// tests accessing tuple object with rvalue int
|
||||
for (size_t i = 0; i < tup.size(); i++) {
|
||||
auto o = py::handle(tup[py::int_(i)]);
|
||||
if (!o) {
|
||||
throw py::value_error("tuple is malformed");
|
||||
}
|
||||
}
|
||||
return tup;
|
||||
});
|
||||
m.def("list_rvalue_getter", [](const py::list &l) {
|
||||
// tests accessing list with rvalue int
|
||||
for (size_t i = 0; i < l.size(); i++) {
|
||||
auto o = py::handle(l[py::int_(i)]);
|
||||
if (!o) {
|
||||
throw py::value_error("list is malformed");
|
||||
}
|
||||
}
|
||||
return l;
|
||||
});
|
||||
m.def("populate_dict_rvalue", [](int population) {
|
||||
auto d = py::dict();
|
||||
for (int i = 0; i < population; i++) {
|
||||
d[py::int_(i)] = py::int_(i);
|
||||
}
|
||||
return d;
|
||||
});
|
||||
m.def("populate_obj_str_attrs", [](py::object &o, int population) {
|
||||
for (int i = 0; i < population; i++) {
|
||||
o.attr(py::str(py::int_(i))) = py::str(py::int_(i));
|
||||
}
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import contextlib
|
||||
import sys
|
||||
import types
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -320,8 +321,7 @@ def test_accessors():
|
||||
def test_accessor_moves():
|
||||
inc_refs = m.accessor_moves()
|
||||
if inc_refs:
|
||||
# To be changed in PR #3970: [1, 0, 1, 0, ...]
|
||||
assert inc_refs == [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
assert inc_refs == [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
|
||||
else:
|
||||
pytest.skip("Not defined: PYBIND11_HANDLE_REF_DEBUG")
|
||||
|
||||
@@ -707,3 +707,30 @@ def test_implementation_details():
|
||||
def test_external_float_():
|
||||
r1 = m.square_float_(2.0)
|
||||
assert r1 == 4.0
|
||||
|
||||
|
||||
def test_tuple_rvalue_getter():
|
||||
pop = 1000
|
||||
tup = tuple(range(pop))
|
||||
m.tuple_rvalue_getter(tup)
|
||||
|
||||
|
||||
def test_list_rvalue_getter():
|
||||
pop = 1000
|
||||
my_list = list(range(pop))
|
||||
m.list_rvalue_getter(my_list)
|
||||
|
||||
|
||||
def test_populate_dict_rvalue():
|
||||
pop = 1000
|
||||
my_dict = {i: i for i in range(pop)}
|
||||
assert m.populate_dict_rvalue(pop) == my_dict
|
||||
|
||||
|
||||
def test_populate_obj_str_attrs():
|
||||
pop = 1000
|
||||
o = types.SimpleNamespace(**{str(i): i for i in range(pop)})
|
||||
new_o = m.populate_obj_str_attrs(o, pop)
|
||||
new_attrs = {k: v for k, v in new_o.__dict__.items() if not k.startswith("_")}
|
||||
assert all(isinstance(v, str) for v in new_attrs.values())
|
||||
assert len(new_attrs) == pop
|
||||
|
||||
Reference in New Issue
Block a user