Skip to content

Commit ab68d73

Browse files
authored
Define SortedDictKeys.__contains__ (#157)
Reduce fuzz test iterations to speed up GitHub Actions workflows. No difference in coverage observed.
1 parent 7e5d3fa commit ab68d73

File tree

5 files changed

+40
-23
lines changed

5 files changed

+40
-23
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.7.2"
11+
version = "0.7.3"
1212
authors = [
1313
{name = "Vishal Pankaj Chandratreya"},
1414
]

src/pysorteddict/sorted_dict_keys_type.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ PyObject* SortedDictKeysIterType::next(void)
88
{
99
return Py_XNewRef(this->SortedDictViewIterType::next().first); // 🆕
1010
}
11+
12+
int SortedDictKeysType::contains(PyObject* key)
13+
{
14+
return this->sd->contains(key);
15+
}

src/pysorteddict/sorted_dict_keys_type.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct SortedDictKeysIterType : public SortedDictViewIterType
1313

1414
struct SortedDictKeysType : public SortedDictViewType
1515
{
16+
int contains(PyObject*);
1617
};
1718

1819
#endif

src/pysorteddict/sorted_dict_module.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,24 @@ static PyObject* sorted_dict_keys_type_repr(PyObject* self)
6363
/**
6464
* Obtain the number of keys.
6565
*/
66-
Py_ssize_t sorted_dict_keys_type_len(PyObject* self)
66+
static Py_ssize_t sorted_dict_keys_type_len(PyObject* self)
6767
{
6868
SortedDictKeysType* sdk = reinterpret_cast<SortedDictKeysType*>(self);
6969
return sdk->len();
7070
}
7171

72+
/**
73+
* Check whether a key is present.
74+
*/
75+
static int sorted_dict_keys_type_contains(PyObject* self, PyObject* key)
76+
{
77+
SortedDictKeysType* sdk = reinterpret_cast<SortedDictKeysType*>(self);
78+
return sdk->contains(key);
79+
}
80+
7281
static PySequenceMethods sorted_dict_keys_type_sequence = {
7382
.sq_length = sorted_dict_keys_type_len,
83+
.sq_contains = sorted_dict_keys_type_contains,
7484
};
7585

7686
/**

tests/test_fuzz.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def test_fuzz(self, key_type: type):
5454
"__len__", "__lt__", "__ne__", "__reduce__", "__reduce_ex__", "__repr__", "__setattr__", "__sizeof__",
5555
"__str__", "__subclasshook__", "__weakref__", "items", "key_type", "values",
5656
)) # fmt: skip
57-
for attr in self._rg.choices([*attrs], k=50_000):
57+
for attr in self._rg.choices([*attrs], k=10_000):
5858
getattr(self, f"_test_{attr}")()
5959

6060
with pytest.raises(TypeError, match="^unhashable type: 'pysorteddict.SortedDict'$"):
@@ -71,26 +71,27 @@ def test_fuzz(self, key_type: type):
7171
assert self.sorted_dict.values() == [*sorted_normal_dict.values()]
7272

7373
def _test___contains__(self):
74-
for key_type in all_types:
75-
key = self._gen(key_type)
76-
if self.is_sorted_dict_new:
77-
with pytest.raises(RuntimeError, match="^key type not set: insert at least one item first$"):
78-
key in self.sorted_dict # noqa: B015
79-
continue
80-
if key_type is not self.key_type:
81-
with pytest.raises(
82-
TypeError,
83-
match=re.escape(f"got key {key!r} of type {key_type!r}, want key of type {self.key_type!r}"),
84-
):
85-
key in self.sorted_dict # noqa: B015
86-
continue
87-
if (key_type is float or key_type is decimal.Decimal) and math.isnan(key):
88-
with pytest.raises(ValueError, match=re.escape(f"got bad key {key!r} of type {key_type!r}")):
89-
key in self.sorted_dict # noqa: B015
90-
continue
91-
if self.normal_dict:
92-
assert self._rg.choice([*self.normal_dict]) in self.sorted_dict
93-
assert (key in self.sorted_dict) == (key in self.normal_dict)
74+
for sorted_dict_or_sorted_dict_keys in (self.sorted_dict, self.sorted_dict_keys):
75+
for key_type in all_types:
76+
key = self._gen(key_type)
77+
if self.is_sorted_dict_new:
78+
with pytest.raises(RuntimeError, match="^key type not set: insert at least one item first$"):
79+
key in sorted_dict_or_sorted_dict_keys # noqa: B015
80+
continue
81+
if key_type is not self.key_type:
82+
with pytest.raises(
83+
TypeError,
84+
match=re.escape(f"got key {key!r} of type {key_type!r}, want key of type {self.key_type!r}"),
85+
):
86+
key in sorted_dict_or_sorted_dict_keys # noqa: B015
87+
continue
88+
if (key_type is float or key_type is decimal.Decimal) and math.isnan(key):
89+
with pytest.raises(ValueError, match=re.escape(f"got bad key {key!r} of type {key_type!r}")):
90+
key in sorted_dict_or_sorted_dict_keys # noqa: B015
91+
continue
92+
if self.normal_dict:
93+
assert self._rg.choice([*self.normal_dict]) in sorted_dict_or_sorted_dict_keys
94+
assert (key in sorted_dict_or_sorted_dict_keys) == (key in self.normal_dict)
9495

9596
def _test___delattr__(self):
9697
with pytest.raises(AttributeError):

0 commit comments

Comments
 (0)