Skip to content

Commit 21c3911

Browse files
sizmailovwjakob
authored andcommitted
add signed overload for py::slice::compute
1 parent 22859bb commit 21c3911

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

include/pybind11/pytypes.h

+7
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,13 @@ class slice : public object {
11331133
(ssize_t *) stop, (ssize_t *) step,
11341134
(ssize_t *) slicelength) == 0;
11351135
}
1136+
bool compute(ssize_t length, ssize_t *start, ssize_t *stop, ssize_t *step,
1137+
ssize_t *slicelength) const {
1138+
return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr,
1139+
length, start,
1140+
stop, step,
1141+
slicelength) == 0;
1142+
}
11361143
};
11371144

11381145
class capsule : public object {

tests/test_sequences_and_iterators.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ py::list test_random_access_iterator(PythonType x) {
7171
}
7272

7373
TEST_SUBMODULE(sequences_and_iterators, m) {
74+
// test_sliceable
75+
class Sliceable{
76+
public:
77+
Sliceable(int n): size(n) {}
78+
int start,stop,step;
79+
int size;
80+
};
81+
py::class_<Sliceable>(m,"Sliceable")
82+
.def(py::init<int>())
83+
.def("__getitem__",[](const Sliceable &s, py::slice slice) {
84+
ssize_t start, stop, step, slicelength;
85+
if (!slice.compute(s.size, &start, &stop, &step, &slicelength))
86+
throw py::error_already_set();
87+
int istart = static_cast<int>(start);
88+
int istop = static_cast<int>(stop);
89+
int istep = static_cast<int>(step);
90+
return std::make_tuple(istart,istop,istep);
91+
})
92+
;
7493

7594
// test_sequence
7695
class Sequence {

tests/test_sequences_and_iterators.py

+13
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ def test_generalized_iterators():
3333
next(it)
3434

3535

36+
def test_sliceable():
37+
sliceable = m.Sliceable(100)
38+
assert sliceable[::] == (0, 100, 1)
39+
assert sliceable[10::] == (10, 100, 1)
40+
assert sliceable[:10:] == (0, 10, 1)
41+
assert sliceable[::10] == (0, 100, 10)
42+
assert sliceable[-10::] == (90, 100, 1)
43+
assert sliceable[:-10:] == (0, 90, 1)
44+
assert sliceable[::-10] == (99, -1, -10)
45+
assert sliceable[50:60:1] == (50, 60, 1)
46+
assert sliceable[50:60:-1] == (50, 60, -1)
47+
48+
3649
def test_sequence():
3750
cstats = ConstructorStats.get(m.Sequence)
3851

0 commit comments

Comments
 (0)