mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
Support more natural syntax for vector extend
This commit is contained in:
parent
1aa8dd1745
commit
22859bb8fc
@ -94,6 +94,11 @@ v2.2.4 (September 11, 2018)
|
|||||||
* A few minor typo fixes and improvements to the test suite, and
|
* A few minor typo fixes and improvements to the test suite, and
|
||||||
patches that silence compiler warnings.
|
patches that silence compiler warnings.
|
||||||
|
|
||||||
|
* Vectors now support construction from generators, as well as ``extend()`` from a
|
||||||
|
list or generator.
|
||||||
|
`#1496 <https://github.com/pybind/pybind11/pull/1496>`_.
|
||||||
|
|
||||||
|
|
||||||
v2.2.3 (April 29, 2018)
|
v2.2.3 (April 29, 2018)
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
@ -1346,6 +1346,21 @@ inline size_t len(handle h) {
|
|||||||
return (size_t) result;
|
return (size_t) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t len_hint(handle h) {
|
||||||
|
#if PY_VERSION_HEX >= 0x03040000
|
||||||
|
ssize_t result = PyObject_LengthHint(h.ptr(), 0);
|
||||||
|
#else
|
||||||
|
ssize_t result = PyObject_Length(h.ptr());
|
||||||
|
#endif
|
||||||
|
if (result < 0) {
|
||||||
|
// Sometimes a length can't be determined at all (eg generators)
|
||||||
|
// In which case simply return 0
|
||||||
|
PyErr_Clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (size_t) result;
|
||||||
|
}
|
||||||
|
|
||||||
inline str repr(handle h) {
|
inline str repr(handle h) {
|
||||||
PyObject *str_value = PyObject_Repr(h.ptr());
|
PyObject *str_value = PyObject_Repr(h.ptr());
|
||||||
if (!str_value) throw error_already_set();
|
if (!str_value) throw error_already_set();
|
||||||
|
@ -122,7 +122,7 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
|||||||
|
|
||||||
cl.def(init([](iterable it) {
|
cl.def(init([](iterable it) {
|
||||||
auto v = std::unique_ptr<Vector>(new Vector());
|
auto v = std::unique_ptr<Vector>(new Vector());
|
||||||
v->reserve(len(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();
|
||||||
@ -136,6 +136,28 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
|||||||
"Extend the list by appending all the items in the given list"
|
"Extend the list by appending all the items in the given list"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cl.def("extend",
|
||||||
|
[](Vector &v, iterable it) {
|
||||||
|
const size_t old_size = v.size();
|
||||||
|
v.reserve(old_size + len_hint(it));
|
||||||
|
try {
|
||||||
|
for (handle h : it) {
|
||||||
|
v.push_back(h.cast<T>());
|
||||||
|
}
|
||||||
|
} catch (const cast_error &) {
|
||||||
|
v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size), v.end());
|
||||||
|
try {
|
||||||
|
v.shrink_to_fit();
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
arg("L"),
|
||||||
|
"Extend the list by appending all the items in the given list"
|
||||||
|
);
|
||||||
|
|
||||||
cl.def("insert",
|
cl.def("insert",
|
||||||
[](Vector &v, SizeType i, const T &x) {
|
[](Vector &v, SizeType i, const T &x) {
|
||||||
if (i > v.size())
|
if (i > v.size())
|
||||||
|
@ -11,6 +11,10 @@ def test_vector_int():
|
|||||||
assert len(v_int) == 2
|
assert len(v_int) == 2
|
||||||
assert bool(v_int) is True
|
assert bool(v_int) is True
|
||||||
|
|
||||||
|
# test construction from a generator
|
||||||
|
v_int1 = m.VectorInt(x for x in range(5))
|
||||||
|
assert v_int1 == m.VectorInt([0, 1, 2, 3, 4])
|
||||||
|
|
||||||
v_int2 = m.VectorInt([0, 0])
|
v_int2 = m.VectorInt([0, 0])
|
||||||
assert v_int == v_int2
|
assert v_int == v_int2
|
||||||
v_int2[1] = 1
|
v_int2[1] = 1
|
||||||
@ -33,6 +37,22 @@ def test_vector_int():
|
|||||||
del v_int2[0]
|
del v_int2[0]
|
||||||
assert v_int2 == m.VectorInt([0, 99, 2, 3])
|
assert v_int2 == m.VectorInt([0, 99, 2, 3])
|
||||||
|
|
||||||
|
v_int2.extend(m.VectorInt([4, 5]))
|
||||||
|
assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5])
|
||||||
|
|
||||||
|
v_int2.extend([6, 7])
|
||||||
|
assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7])
|
||||||
|
|
||||||
|
# test error handling, and that the vector is unchanged
|
||||||
|
with pytest.raises(RuntimeError):
|
||||||
|
v_int2.extend([8, 'a'])
|
||||||
|
|
||||||
|
assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7])
|
||||||
|
|
||||||
|
# test extending from a generator
|
||||||
|
v_int2.extend(x for x in range(5))
|
||||||
|
assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4])
|
||||||
|
|
||||||
|
|
||||||
# related to the PyPy's buffer protocol.
|
# related to the PyPy's buffer protocol.
|
||||||
@pytest.unsupported_on_pypy
|
@pytest.unsupported_on_pypy
|
||||||
|
Loading…
Reference in New Issue
Block a user