Skip to content

Commit dc3dd8a

Browse files
authored
Make SortedDictKeys indexing errors match list indexing errors (#169)
[skip ci]
1 parent 580d312 commit dc3dd8a

File tree

3 files changed

+47
-42
lines changed

3 files changed

+47
-42
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
88

99
[project]
1010
name = "pysorteddict"
11-
version = "0.8.0"
11+
version = "0.8.1"
1212
authors = [
1313
{name = "Vishal Pankaj Chandratreya"},
1414
]

src/pysorteddict/sorted_dict_keys_type.cc

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,21 +92,29 @@ int SortedDictKeysType::contains(PyObject* key)
9292

9393
PyObject* SortedDictKeysType::getitem(PyObject* idx)
9494
{
95-
Py_ssize_t position = PyNumber_AsSsize_t(idx, PyExc_IndexError);
96-
if (position != -1 || PyErr_Occurred() == nullptr)
95+
if (PyIndex_Check(idx) != 0)
9796
{
97+
Py_ssize_t position = PyNumber_AsSsize_t(idx, PyExc_IndexError);
98+
if (position == -1 && PyErr_Occurred() != nullptr)
99+
{
100+
return nullptr;
101+
}
98102
return this->getitem(position);
99103
}
100-
PyErr_Clear();
101-
Py_ssize_t start, stop, step;
102-
if (PySlice_Check(idx) && PySlice_Unpack(idx, &start, &stop, &step) == 0)
104+
105+
if (PySlice_Check(idx))
103106
{
107+
Py_ssize_t start, stop, step;
108+
if (PySlice_Unpack(idx, &start, &stop, &step) != 0)
109+
{
110+
return nullptr;
111+
}
104112
return this->getitem(start, stop, step);
105113
}
106-
PyErr_Clear();
114+
107115
PyErr_Format(
108-
PyExc_TypeError, "got index %R of type %R, want index of type %R or %R with non-zero step", idx, Py_TYPE(idx),
109-
&PyLong_Type, &PySlice_Type
116+
PyExc_TypeError, "got index %R of type %R, want index of type %R or %R", idx, Py_TYPE(idx), &PyLong_Type,
117+
&PySlice_Type
110118
);
111119
return nullptr;
112120
}

tests/test_fuzz.py

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import random
55
import re
66
import string
7+
import sys
78

89
import pytest
910

@@ -194,42 +195,38 @@ def _test_copy(self):
194195
self.sorted_dict_keys = self.sorted_dict.keys()
195196

196197
def _test_keys(self):
197-
sorted_normal_dict_keys = sorted(self.normal_dict.keys())
198-
sorted_normal_dict_keys_len = len(sorted_normal_dict_keys)
199-
sorted_normal_dict_keys_len_ex = int(1.3 * sorted_normal_dict_keys_len)
200-
assert repr(self.sorted_dict_keys) == f"SortedDictKeys({sorted_normal_dict_keys})"
201-
assert len(self.sorted_dict_keys) == sorted_normal_dict_keys_len
202-
start = self._rg.randint(-sorted_normal_dict_keys_len_ex, sorted_normal_dict_keys_len_ex)
203-
stop = self._rg.randint(-sorted_normal_dict_keys_len_ex, sorted_normal_dict_keys_len_ex)
198+
self._test_view("SortedDictKeys", self.sorted_dict_keys, sorted(self.normal_dict.keys()))
199+
200+
def _test_view(self, name, view, view_as_list):
201+
view_as_list_len = len(view_as_list)
202+
view_as_list_len_ex = int(1.3 * view_as_list_len)
203+
assert repr(view) == f"{name}({view_as_list})"
204+
assert len(view) == view_as_list_len
205+
start = self._rg.randint(-view_as_list_len_ex, view_as_list_len_ex)
206+
stop = self._rg.randint(-view_as_list_len_ex, view_as_list_len_ex)
204207
for idx in [start, stop]:
205-
if -sorted_normal_dict_keys_len <= idx < sorted_normal_dict_keys_len:
206-
assert self.sorted_dict_keys[idx] == sorted_normal_dict_keys[idx]
208+
if -view_as_list_len <= idx < view_as_list_len:
209+
assert view[idx] == view_as_list[idx]
207210
else:
208211
with pytest.raises(
209-
IndexError,
210-
match=rf"^got invalid index {idx} for view of length {sorted_normal_dict_keys_len}$",
212+
IndexError, match=rf"^got invalid index {idx} for view of length {view_as_list_len}$"
211213
):
212-
self.sorted_dict_keys[idx]
213-
step = self._rg.randint(-sorted_normal_dict_keys_len_ex, sorted_normal_dict_keys_len_ex)
214+
view[idx]
215+
with pytest.raises(IndexError, match="^cannot fit 'int' into an index-sized integer$"):
216+
view[sys.maxsize + 1]
217+
with pytest.raises(TypeError, match=rf"^got index 0.0 of type {float}, want index of type {int} or {slice}$"):
218+
view[0.0]
219+
step = self._rg.randint(-view_as_list_len_ex, view_as_list_len_ex)
214220
if step == 0:
215-
with pytest.raises(
216-
TypeError,
217-
match=re.escape(
218-
f"got index slice({start}, {stop}, {step}) of type {slice}, want index of type {int} or {slice} with non-zero step"
219-
),
220-
):
221-
self.sorted_dict_keys[start:stop:step]
221+
with pytest.raises(ValueError, match="^slice step cannot be zero$"):
222+
view[start:stop:step]
222223
else:
223-
assert self.sorted_dict_keys[start:stop:step] == sorted_normal_dict_keys[start:stop:step]
224-
assert self.sorted_dict_keys[:stop:step] == sorted_normal_dict_keys[:stop:step]
225-
assert self.sorted_dict_keys[start::step] == sorted_normal_dict_keys[start::step]
226-
assert self.sorted_dict_keys[::step] == sorted_normal_dict_keys[::step]
227-
with pytest.raises(
228-
TypeError,
229-
match=rf"^got index 0.0 of type {float}, want index of type {int} or {slice} with non-zero step$",
230-
):
231-
self.sorted_dict_keys[0.0]
232-
assert self.sorted_dict_keys[start:stop] == sorted_normal_dict_keys[start:stop]
233-
assert self.sorted_dict_keys[start:] == sorted_normal_dict_keys[start:]
234-
assert self.sorted_dict_keys[:stop] == sorted_normal_dict_keys[:stop]
235-
assert [*self.sorted_dict_keys] == sorted_normal_dict_keys
224+
assert view[start:stop:step] == view_as_list[start:stop:step]
225+
assert view[:stop:step] == view_as_list[:stop:step]
226+
assert view[start::step] == view_as_list[start::step]
227+
assert view[::step] == view_as_list[::step]
228+
assert view[start:stop] == view_as_list[start:stop]
229+
assert view[start:] == view_as_list[start:]
230+
assert view[:stop] == view_as_list[:stop]
231+
assert view[:] == view_as_list
232+
assert [*view] == view_as_list

0 commit comments

Comments
 (0)