Skip to content

Commit f41d66f

Browse files
skinnyBatwebknjaz
andauthored
Add tests to have full code coverage of the function _viewbaseset_richcmp()
PR #928 Resolves #921 Co-authored-by: Sviatoslav Sydorenko <[email protected]>
1 parent 7e8f02a commit f41d66f

File tree

5 files changed

+111
-8
lines changed

5 files changed

+111
-8
lines changed

CHANGES/928.bugfix.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Covered the unreachable code path in
2+
``multidict._multidict_base._abc_itemsview_register()``
3+
with typing -- by :user:`skinnyBat`.

CHANGES/928.contrib.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added tests to have full code coverage of the
2+
``multidict._multidict_base._viewbaseset_richcmp()`` function
3+
-- by :user:`skinnyBat`.

multidict/_multidict_base.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import sys
12
from collections.abc import ItemsView, Iterable, KeysView, Set, ValuesView
23

4+
if sys.version_info >= (3, 11):
5+
from typing import assert_never
6+
else:
7+
from typing_extensions import assert_never
8+
39

410
def _abc_itemsview_register(view_cls):
511
ItemsView.register(view_cls)
@@ -46,6 +52,8 @@ def _viewbaseset_richcmp(view, other, op):
4652
if elem not in view:
4753
return False
4854
return True
55+
else: # pragma: no cover
56+
assert_never(op)
4957

5058

5159
def _viewbaseset_and(view, other):

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ classifiers =
4343

4444
[options]
4545
python_requires = >= 3.7
46+
install_requires =
47+
typing-extensions >= 4.1.0; python_version < '3.11'
4648
packages =
4749
multidict
4850

tests/test_multidict.py

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -286,34 +286,121 @@ def test_keys_is_set_less(self, cls: Type[MutableMultiMapping[str]]) -> None:
286286

287287
assert d.keys() < {"key", "key2"}
288288

289-
def test_keys_is_set_less_equal(self, cls: Type[MutableMultiMapping[str]]) -> None:
290-
d = cls([("key", "value1")])
289+
@pytest.mark.parametrize(
290+
("contents", "expected"),
291+
(
292+
([("key", "value1")], True),
293+
([("key", "value1"), ("key2", "value2")], True),
294+
([("key", "value1"), ("key2", "value2"), ("key3", "value3")], False),
295+
([("key", "value1"), ("key3", "value3")], False),
296+
),
297+
)
298+
def test_keys_is_set_less_equal(
299+
self,
300+
cls: Type[MutableMultiMapping[str]],
301+
contents: List[Tuple[str, str]],
302+
expected: bool,
303+
) -> None:
304+
d = cls(contents)
291305

292-
assert d.keys() <= {"key"}
306+
result = d.keys() <= {"key", "key2"}
307+
assert result is expected
293308

294309
def test_keys_is_set_equal(self, cls: Type[MutableMultiMapping[str]]) -> None:
295310
d = cls([("key", "value1")])
296311

297312
assert d.keys() == {"key"}
298313

299314
def test_keys_is_set_greater(self, cls: Type[MutableMultiMapping[str]]) -> None:
300-
d = cls([("key", "value1")])
315+
d = cls([("key", "value1"), ("key2", "value2")])
301316

302-
assert {"key", "key2"} > d.keys()
317+
assert d.keys() > {"key"}
303318

319+
@pytest.mark.parametrize(
320+
("set_", "expected"),
321+
(
322+
({"key"}, True),
323+
({"key", "key2"}, True),
324+
({"key", "key2", "key3"}, False),
325+
({"key3"}, False),
326+
),
327+
)
304328
def test_keys_is_set_greater_equal(
305-
self,
306-
cls: Type[MutableMultiMapping[str]],
329+
self, cls: Type[MutableMultiMapping[str]], set_: Set[str], expected: bool
330+
) -> None:
331+
d = cls([("key", "value1"), ("key2", "value2")])
332+
333+
result = d.keys() >= set_
334+
assert result is expected
335+
336+
def test_keys_less_than_not_implemented(
337+
self, cls: Type[MutableMultiMapping[str]]
338+
) -> None:
339+
d = cls([("key", "value1")])
340+
341+
sentinel_operation_result = object()
342+
343+
class RightOperand:
344+
def __gt__(self, other: KeysView[str]) -> object:
345+
assert isinstance(other, KeysView)
346+
return sentinel_operation_result
347+
348+
assert (d.keys() < RightOperand()) is sentinel_operation_result
349+
350+
def test_keys_less_than_or_equal_not_implemented(
351+
self, cls: Type[MutableMultiMapping[str]]
307352
) -> None:
308353
d = cls([("key", "value1")])
309354

310-
assert {"key"} >= d.keys()
355+
sentinel_operation_result = object()
356+
357+
class RightOperand:
358+
def __ge__(self, other: KeysView[str]) -> object:
359+
assert isinstance(other, KeysView)
360+
return sentinel_operation_result
361+
362+
assert (d.keys() <= RightOperand()) is sentinel_operation_result
363+
364+
def test_keys_greater_than_not_implemented(
365+
self, cls: Type[MutableMultiMapping[str]]
366+
) -> None:
367+
d = cls([("key", "value1")])
368+
369+
sentinel_operation_result = object()
370+
371+
class RightOperand:
372+
def __lt__(self, other: KeysView[str]) -> object:
373+
assert isinstance(other, KeysView)
374+
return sentinel_operation_result
375+
376+
assert (d.keys() > RightOperand()) is sentinel_operation_result
377+
378+
def test_keys_greater_than_or_equal_not_implemented(
379+
self, cls: Type[MutableMultiMapping[str]]
380+
) -> None:
381+
d = cls([("key", "value1")])
382+
383+
sentinel_operation_result = object()
384+
385+
class RightOperand:
386+
def __le__(self, other: KeysView[str]) -> object:
387+
assert isinstance(other, KeysView)
388+
return sentinel_operation_result
389+
390+
assert (d.keys() >= RightOperand()) is sentinel_operation_result
311391

312392
def test_keys_is_set_not_equal(self, cls: Type[MutableMultiMapping[str]]) -> None:
313393
d = cls([("key", "value1")])
314394

315395
assert d.keys() != {"key2"}
316396

397+
def test_keys_not_equal_unrelated_type(
398+
self, cls: Type[MutableMultiMapping[str]]
399+
) -> None:
400+
d = cls([("key", "value1")])
401+
402+
assert d.keys() != "other"
403+
317404
def test_eq(self, cls: Type[MutableMultiMapping[str]]) -> None:
318405
d = cls([("key", "value1")])
319406

0 commit comments

Comments
 (0)