Skip to content

Commit fcab621

Browse files
author
Pim Schellart
authored
Merge pull request #4 from lsst-dm/tickets/DM-7115
Accept any sequence type as std::vector
2 parents 26df852 + d2afe7f commit fcab621

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

include/pybind11/pytypes.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ namespace accessor_policies {
2929
struct obj_attr;
3030
struct str_attr;
3131
struct generic_item;
32+
struct sequence_item;
3233
struct list_item;
3334
struct tuple_item;
3435
}
3536
using obj_attr_accessor = accessor<accessor_policies::obj_attr>;
3637
using str_attr_accessor = accessor<accessor_policies::str_attr>;
3738
using item_accessor = accessor<accessor_policies::generic_item>;
39+
using sequence_accessor = accessor<accessor_policies::sequence_item>;
3840
using list_accessor = accessor<accessor_policies::list_item>;
3941
using tuple_accessor = accessor<accessor_policies::tuple_item>;
4042

@@ -261,6 +263,23 @@ struct generic_item {
261263
}
262264
};
263265

266+
struct sequence_item {
267+
using key_type = size_t;
268+
269+
static object get(handle obj, size_t index) {
270+
PyObject *result = PySequence_GetItem(obj.ptr(), static_cast<ssize_t>(index));
271+
if (!result) { throw error_already_set(); }
272+
return {result, true};
273+
}
274+
275+
static void set(handle obj, size_t index, handle val) {
276+
// PySequence_SetItem does not steal a reference to 'val'
277+
if (PySequence_SetItem(obj.ptr(), static_cast<ssize_t>(index), val.ptr()) != 0) {
278+
throw error_already_set();
279+
}
280+
}
281+
};
282+
264283
struct list_item {
265284
using key_type = size_t;
266285

@@ -673,6 +692,13 @@ class dict : public object {
673692
bool contains(const char *key) const { return PyDict_Contains(ptr(), pybind11::str(key).ptr()) == 1; }
674693
};
675694

695+
class sequence : public object {
696+
public:
697+
PYBIND11_OBJECT(sequence, object, PySequence_Check)
698+
size_t size() const { return (size_t) PySequence_Size(m_ptr); }
699+
detail::sequence_accessor operator[](size_t index) const { return {*this, index}; }
700+
};
701+
676702
class list : public object {
677703
public:
678704
PYBIND11_OBJECT(list, object, PyList_Check)

include/pybind11/stl.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@ template <typename Type, typename Value> struct list_caster {
9797
using value_conv = make_caster<Value>;
9898

9999
bool load(handle src, bool convert) {
100-
list l(src, true);
101-
if (!l.check())
100+
sequence s(src, true);
101+
if (!s.check())
102102
return false;
103103
value_conv conv;
104104
value.clear();
105-
reserve_maybe(l, &value);
106-
for (auto it : l) {
105+
reserve_maybe(s, &value);
106+
for (auto it : s) {
107107
if (!conv.load(it, convert))
108108
return false;
109109
value.push_back((Value) conv);
@@ -113,8 +113,8 @@ template <typename Type, typename Value> struct list_caster {
113113

114114
template <typename T = Type,
115115
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
116-
void reserve_maybe(list l, Type *) { value.reserve(l.size()); }
117-
void reserve_maybe(list, void *) { }
116+
void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); }
117+
void reserve_maybe(sequence, void *) { }
118118

119119
static handle cast(const Type &src, return_value_policy policy, handle parent) {
120120
list l(src.size());

tests/test_python_types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ def test_instance(capture):
7171
list item 0: value
7272
list item 1: value2
7373
"""
74+
with capture:
75+
list_result = instance.get_list_2()
76+
list_result.append('value2')
77+
instance.print_list_2(tuple(list_result))
78+
assert capture.unordered == """
79+
list item 0: value
80+
list item 1: value2
81+
"""
7482
array_result = instance.get_array()
7583
assert array_result == ['array entry 1', 'array entry 2']
7684
with capture:

0 commit comments

Comments
 (0)