Skip to content

Add tests to have full code coverage of the function _viewbaseset_richcmp #928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES/928.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Covered the unreachable code path in
``multidict._multidict_base._abc_itemsview_register()``
with typing -- by :user:`skinnyBat`.
3 changes: 3 additions & 0 deletions CHANGES/928.contrib.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added tests to have full code coverage of the
``multidict._multidict_base._viewbaseset_richcmp()`` function
-- by :user:`skinnyBat`.
8 changes: 8 additions & 0 deletions multidict/_multidict_base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import sys
from collections.abc import ItemsView, Iterable, KeysView, Set, ValuesView

if sys.version_info >= (3, 11):
from typing import assert_never
else:
from typing_extensions import assert_never


def _abc_itemsview_register(view_cls):
ItemsView.register(view_cls)
Expand Down Expand Up @@ -46,6 +52,8 @@ def _viewbaseset_richcmp(view, other, op):
if elem not in view:
return False
return True
else: # pragma: no cover
assert_never(op)


def _viewbaseset_and(view, other):
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ classifiers =

[options]
python_requires = >= 3.7
install_requires =
typing-extensions >= 4.1.0; python_version < '3.11'
packages =
multidict

Expand Down
103 changes: 95 additions & 8 deletions tests/test_multidict.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,34 +286,121 @@ def test_keys_is_set_less(self, cls: Type[MutableMultiMapping[str]]) -> None:

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

def test_keys_is_set_less_equal(self, cls: Type[MutableMultiMapping[str]]) -> None:
d = cls([("key", "value1")])
@pytest.mark.parametrize(
("contents", "expected"),
(
([("key", "value1")], True),
([("key", "value1"), ("key2", "value2")], True),
([("key", "value1"), ("key2", "value2"), ("key3", "value3")], False),
([("key", "value1"), ("key3", "value3")], False),
),
)
def test_keys_is_set_less_equal(
self,
cls: Type[MutableMultiMapping[str]],
contents: List[Tuple[str, str]],
expected: bool,
) -> None:
d = cls(contents)

assert d.keys() <= {"key"}
result = d.keys() <= {"key", "key2"}
assert result is expected

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

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

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

assert {"key", "key2"} > d.keys()
assert d.keys() > {"key"}

@pytest.mark.parametrize(
("set_", "expected"),
(
({"key"}, True),
({"key", "key2"}, True),
({"key", "key2", "key3"}, False),
({"key3"}, False),
),
)
def test_keys_is_set_greater_equal(
self,
cls: Type[MutableMultiMapping[str]],
self, cls: Type[MutableMultiMapping[str]], set_: Set[str], expected: bool
) -> None:
d = cls([("key", "value1"), ("key2", "value2")])

result = d.keys() >= set_
assert result is expected

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

sentinel_operation_result = object()

class RightOperand:
def __gt__(self, other: KeysView[str]) -> object:
assert isinstance(other, KeysView)
return sentinel_operation_result

assert (d.keys() < RightOperand()) is sentinel_operation_result

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

assert {"key"} >= d.keys()
sentinel_operation_result = object()

class RightOperand:
def __ge__(self, other: KeysView[str]) -> object:
assert isinstance(other, KeysView)
return sentinel_operation_result

assert (d.keys() <= RightOperand()) is sentinel_operation_result

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

sentinel_operation_result = object()

class RightOperand:
def __lt__(self, other: KeysView[str]) -> object:
assert isinstance(other, KeysView)
return sentinel_operation_result

assert (d.keys() > RightOperand()) is sentinel_operation_result

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

sentinel_operation_result = object()

class RightOperand:
def __le__(self, other: KeysView[str]) -> object:
assert isinstance(other, KeysView)
return sentinel_operation_result

assert (d.keys() >= RightOperand()) is sentinel_operation_result

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

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

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

assert d.keys() != "other"

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

Expand Down