summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2016-05-05 08:14:06 (GMT)
committerRaymond Hettinger <python@rcn.com>2016-05-05 08:14:06 (GMT)
commit584e8aedc3d66721efcdcbd1a43d4c5b7476427b (patch)
tree55e0a4e70a641ef36665489fac95802d5fba3cb3
parentd7062de95d035121abbab526c3b59904361aa256 (diff)
downloadcpython-584e8aedc3d66721efcdcbd1a43d4c5b7476427b.zip
cpython-584e8aedc3d66721efcdcbd1a43d4c5b7476427b.tar.gz
cpython-584e8aedc3d66721efcdcbd1a43d4c5b7476427b.tar.bz2
Issue 26915: Add identity checks to the collections ABC __contains__ methods.
-rw-r--r--Lib/_collections_abc.py7
-rw-r--r--Lib/test/test_collections.py22
-rw-r--r--Misc/NEWS5
3 files changed, 30 insertions, 4 deletions
diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py
index d337584..3158373 100644
--- a/Lib/_collections_abc.py
+++ b/Lib/_collections_abc.py
@@ -689,7 +689,7 @@ class ItemsView(MappingView, Set):
except KeyError:
return False
else:
- return v == value
+ return v is value or v == value
def __iter__(self):
for key in self._mapping:
@@ -704,7 +704,8 @@ class ValuesView(MappingView):
def __contains__(self, value):
for key in self._mapping:
- if value == self._mapping[key]:
+ v = self._mapping[key]
+ if v is value or v == value:
return True
return False
@@ -839,7 +840,7 @@ class Sequence(Sized, Reversible, Container):
def __contains__(self, value):
for v in self:
- if v == value:
+ if v is value or v == value:
return True
return False
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 4202462..3824a87 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -23,7 +23,7 @@ from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable
from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
from collections.abc import Sized, Container, Callable
from collections.abc import Set, MutableSet
-from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
+from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
from collections.abc import Sequence, MutableSequence
from collections.abc import ByteString
@@ -1074,6 +1074,26 @@ class TestCollectionABCs(ABCTestCase):
self.assertFalse(ncs > cs)
self.assertTrue(ncs >= cs)
+ def test_issue26915(self):
+ # Container membership test should check identity first
+ class CustomEqualObject:
+ def __eq__(self, other):
+ return False
+ class CustomSequence(list):
+ def __contains__(self, value):
+ return Sequence.__contains__(self, value)
+
+ nan = float('nan')
+ obj = CustomEqualObject()
+ containers = [
+ CustomSequence([nan, obj]),
+ ItemsView({1: nan, 2: obj}),
+ ValuesView({1: nan, 2: obj})
+ ]
+ for container in containers:
+ for elem in container:
+ self.assertIn(elem, container)
+
def assertSameSet(self, s1, s2):
# coerce both to a real set then check equality
self.assertSetEqual(set(s1), set(s2))
diff --git a/Misc/NEWS b/Misc/NEWS
index 4833aa3..875c113 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -268,6 +268,11 @@ Library
- Issue #26873: xmlrpc now raises ResponseError on unsupported type tags
instead of silently return incorrect result.
+- Issue #26915: The __contains__ methods in the collections ABCs now check
+ for identity before checking equality. This better matches the behavior
+ of the concrete classes, allows sensible handling of NaNs, and makes it
+ easier to reason about container invariants.
+
- Issue #26711: Fixed the comparison of plistlib.Data with other types.
- Issue #24114: Fix an uninitialized variable in `ctypes.util`.