Skip to content

Commit 584e8ae

Browse files
committed
Issue 26915: Add identity checks to the collections ABC __contains__ methods.
1 parent d7062de commit 584e8ae

3 files changed

Lines changed: 30 additions & 4 deletions

File tree

Lib/_collections_abc.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ def __contains__(self, item):
689689
except KeyError:
690690
return False
691691
else:
692-
return v == value
692+
return v is value or v == value
693693

694694
def __iter__(self):
695695
for key in self._mapping:
@@ -704,7 +704,8 @@ class ValuesView(MappingView):
704704

705705
def __contains__(self, value):
706706
for key in self._mapping:
707-
if value == self._mapping[key]:
707+
v = self._mapping[key]
708+
if v is value or v == value:
708709
return True
709710
return False
710711

@@ -839,7 +840,7 @@ def __iter__(self):
839840

840841
def __contains__(self, value):
841842
for v in self:
842-
if v == value:
843+
if v is value or v == value:
843844
return True
844845
return False
845846

Lib/test/test_collections.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
2424
from collections.abc import Sized, Container, Callable
2525
from collections.abc import Set, MutableSet
26-
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
26+
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
2727
from collections.abc import Sequence, MutableSequence
2828
from collections.abc import ByteString
2929

@@ -1074,6 +1074,26 @@ def __lt__(self, x):
10741074
self.assertFalse(ncs > cs)
10751075
self.assertTrue(ncs >= cs)
10761076

1077+
def test_issue26915(self):
1078+
# Container membership test should check identity first
1079+
class CustomEqualObject:
1080+
def __eq__(self, other):
1081+
return False
1082+
class CustomSequence(list):
1083+
def __contains__(self, value):
1084+
return Sequence.__contains__(self, value)
1085+
1086+
nan = float('nan')
1087+
obj = CustomEqualObject()
1088+
containers = [
1089+
CustomSequence([nan, obj]),
1090+
ItemsView({1: nan, 2: obj}),
1091+
ValuesView({1: nan, 2: obj})
1092+
]
1093+
for container in containers:
1094+
for elem in container:
1095+
self.assertIn(elem, container)
1096+
10771097
def assertSameSet(self, s1, s2):
10781098
# coerce both to a real set then check equality
10791099
self.assertSetEqual(set(s1), set(s2))

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ Library
268268
- Issue #26873: xmlrpc now raises ResponseError on unsupported type tags
269269
instead of silently return incorrect result.
270270

271+
- Issue #26915: The __contains__ methods in the collections ABCs now check
272+
for identity before checking equality. This better matches the behavior
273+
of the concrete classes, allows sensible handling of NaNs, and makes it
274+
easier to reason about container invariants.
275+
271276
- Issue #26711: Fixed the comparison of plistlib.Data with other types.
272277

273278
- Issue #24114: Fix an uninitialized variable in `ctypes.util`.

0 commit comments

Comments
 (0)