]> granicus.if.org Git - python/commitdiff
Issue 26915: Add identity checks to the collections ABC __contains__ methods.
authorRaymond Hettinger <python@rcn.com>
Thu, 5 May 2016 08:14:06 +0000 (11:14 +0300)
committerRaymond Hettinger <python@rcn.com>
Thu, 5 May 2016 08:14:06 +0000 (11:14 +0300)
Lib/_collections_abc.py
Lib/test/test_collections.py
Misc/NEWS

index d3375847e2861cb4e20c981531a8412437001c0d..31583731fc7388c60ba515606ff00e0ffa4ba4ba 100644 (file)
@@ -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
 
index 42024628c5e27dd60031254ffa01841da47c0261..3824a87365f3edc5c8c56ac202df9b440f2e2e9d 100644 (file)
@@ -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))
index 4833aa37e29ce2debc7f4b44ca6cb6515fe6b7c5..875c11360214c69327cdc8e60ff9987f611f3488 100644 (file)
--- 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`.