mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-12 01:10:34 +00:00
Merge branch 'master' into sh_merge_master
This commit is contained in:
@@ -10,6 +10,10 @@ name = "pybind11_tests"
|
||||
version = "0.0.1"
|
||||
dependencies = ["pytest", "pytest-timeout", "numpy", "scipy"]
|
||||
|
||||
[tool.scikit-build]
|
||||
# Hide a warning while we also support CMake < 3.15
|
||||
cmake.version = ">=3.15"
|
||||
|
||||
[tool.scikit-build.cmake.define]
|
||||
PYBIND11_FINDPYTHON = true
|
||||
|
||||
|
||||
@@ -167,6 +167,14 @@ struct type_caster<ReferenceSensitiveOptional<T>>
|
||||
} // namespace detail
|
||||
} // namespace PYBIND11_NAMESPACE
|
||||
|
||||
int pass_std_vector_int(const std::vector<int> &v) {
|
||||
int zum = 100;
|
||||
for (const int i : v) {
|
||||
zum += 2 * i;
|
||||
}
|
||||
return zum;
|
||||
}
|
||||
|
||||
TEST_SUBMODULE(stl, m) {
|
||||
// test_vector
|
||||
m.def("cast_vector", []() { return std::vector<int>{1}; });
|
||||
@@ -546,4 +554,30 @@ TEST_SUBMODULE(stl, m) {
|
||||
[]() { return new std::vector<bool>(4513); },
|
||||
// Without explicitly specifying `take_ownership`, this function leaks.
|
||||
py::return_value_policy::take_ownership);
|
||||
|
||||
m.def("pass_std_vector_int", pass_std_vector_int);
|
||||
m.def("pass_std_vector_pair_int", [](const std::vector<std::pair<int, int>> &v) {
|
||||
int zum = 0;
|
||||
for (const auto &ij : v) {
|
||||
zum += ij.first * 100 + ij.second;
|
||||
}
|
||||
return zum;
|
||||
});
|
||||
m.def("pass_std_array_int_2", [](const std::array<int, 2> &a) {
|
||||
return pass_std_vector_int(std::vector<int>(a.begin(), a.end())) + 1;
|
||||
});
|
||||
m.def("pass_std_set_int", [](const std::set<int> &s) {
|
||||
int zum = 200;
|
||||
for (const int i : s) {
|
||||
zum += 3 * i;
|
||||
}
|
||||
return zum;
|
||||
});
|
||||
m.def("pass_std_map_int", [](const std::map<int, int> &m) {
|
||||
int zum = 500;
|
||||
for (const auto &p : m) {
|
||||
zum += p.first * 1000 + p.second;
|
||||
}
|
||||
return zum;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -381,3 +381,129 @@ def test_return_vector_bool_raw_ptr():
|
||||
v = m.return_vector_bool_raw_ptr()
|
||||
assert isinstance(v, list)
|
||||
assert len(v) == 4513
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("fn", "offset"), [(m.pass_std_vector_int, 0), (m.pass_std_array_int_2, 1)]
|
||||
)
|
||||
def test_pass_std_vector_int(fn, offset):
|
||||
assert fn([7, 13]) == 140 + offset
|
||||
assert fn({6, 2}) == 116 + offset
|
||||
assert fn({"x": 8, "y": 11}.values()) == 138 + offset
|
||||
assert fn({3: None, 9: None}.keys()) == 124 + offset
|
||||
assert fn(i for i in [4, 17]) == 142 + offset
|
||||
assert fn(map(lambda i: i * 3, [8, 7])) == 190 + offset # noqa: C417
|
||||
with pytest.raises(TypeError):
|
||||
fn({"x": 0, "y": 1})
|
||||
with pytest.raises(TypeError):
|
||||
fn({})
|
||||
|
||||
|
||||
def test_pass_std_vector_pair_int():
|
||||
fn = m.pass_std_vector_pair_int
|
||||
assert fn({1: 2, 3: 4}.items()) == 406
|
||||
assert fn(zip([5, 17], [13, 9])) == 2222
|
||||
|
||||
|
||||
def test_list_caster_fully_consumes_generator_object():
|
||||
def gen_invalid():
|
||||
yield from [1, 2.0, 3]
|
||||
|
||||
gen_obj = gen_invalid()
|
||||
with pytest.raises(TypeError):
|
||||
m.pass_std_vector_int(gen_obj)
|
||||
assert not tuple(gen_obj)
|
||||
|
||||
|
||||
def test_pass_std_set_int():
|
||||
fn = m.pass_std_set_int
|
||||
assert fn({3, 15}) == 254
|
||||
assert fn({5: None, 12: None}.keys()) == 251
|
||||
with pytest.raises(TypeError):
|
||||
fn([])
|
||||
with pytest.raises(TypeError):
|
||||
fn({})
|
||||
with pytest.raises(TypeError):
|
||||
fn({}.values())
|
||||
with pytest.raises(TypeError):
|
||||
fn(i for i in [])
|
||||
|
||||
|
||||
def test_set_caster_dict_keys_failure():
|
||||
dict_keys = {1: None, 2.0: None, 3: None}.keys()
|
||||
# The asserts does not really exercise anything in pybind11, but if one of
|
||||
# them fails in some future version of Python, the set_caster load
|
||||
# implementation may need to be revisited.
|
||||
assert tuple(dict_keys) == (1, 2.0, 3)
|
||||
assert tuple(dict_keys) == (1, 2.0, 3)
|
||||
with pytest.raises(TypeError):
|
||||
m.pass_std_set_int(dict_keys)
|
||||
assert tuple(dict_keys) == (1, 2.0, 3)
|
||||
|
||||
|
||||
class FakePyMappingMissingItems:
|
||||
def __getitem__(self, _):
|
||||
raise RuntimeError("Not expected to be called.")
|
||||
|
||||
|
||||
class FakePyMappingWithItems(FakePyMappingMissingItems):
|
||||
def items(self):
|
||||
return ((1, 3), (2, 4))
|
||||
|
||||
|
||||
class FakePyMappingBadItems(FakePyMappingMissingItems):
|
||||
def items(self):
|
||||
return ((1, 2), (3, "x"))
|
||||
|
||||
|
||||
class FakePyMappingItemsNotCallable(FakePyMappingMissingItems):
|
||||
@property
|
||||
def items(self):
|
||||
return ((1, 2), (3, 4))
|
||||
|
||||
|
||||
class FakePyMappingItemsWithArg(FakePyMappingMissingItems):
|
||||
def items(self, _):
|
||||
return ((1, 2), (3, 4))
|
||||
|
||||
|
||||
class FakePyMappingGenObj(FakePyMappingMissingItems):
|
||||
def __init__(self, gen_obj):
|
||||
super().__init__()
|
||||
self.gen_obj = gen_obj
|
||||
|
||||
def items(self):
|
||||
yield from self.gen_obj
|
||||
|
||||
|
||||
def test_pass_std_map_int():
|
||||
fn = m.pass_std_map_int
|
||||
assert fn({1: 2, 3: 4}) == 4506
|
||||
with pytest.raises(TypeError):
|
||||
fn([])
|
||||
assert fn(FakePyMappingWithItems()) == 3507
|
||||
with pytest.raises(TypeError):
|
||||
fn(FakePyMappingMissingItems())
|
||||
with pytest.raises(TypeError):
|
||||
fn(FakePyMappingBadItems())
|
||||
with pytest.raises(TypeError):
|
||||
fn(FakePyMappingItemsNotCallable())
|
||||
with pytest.raises(TypeError):
|
||||
fn(FakePyMappingItemsWithArg())
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("items", "expected_exception"),
|
||||
[
|
||||
(((1, 2), (3, "x"), (4, 5)), TypeError),
|
||||
(((1, 2), (3, 4, 5), (6, 7)), ValueError),
|
||||
],
|
||||
)
|
||||
def test_map_caster_fully_consumes_generator_object(items, expected_exception):
|
||||
def gen_invalid():
|
||||
yield from items
|
||||
|
||||
gen_obj = gen_invalid()
|
||||
with pytest.raises(expected_exception):
|
||||
m.pass_std_map_int(FakePyMappingGenObj(gen_obj))
|
||||
assert not tuple(gen_obj)
|
||||
|
||||
Reference in New Issue
Block a user