]> granicus.if.org Git - python/commitdiff
Issue #4296: Fix PyObject_RichCompareBool so that "x in [x]" evaluates to
authorMark Dickinson <dickinsm@gmail.com>
Wed, 12 Nov 2008 23:23:36 +0000 (23:23 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Wed, 12 Nov 2008 23:23:36 +0000 (23:23 +0000)
True, even when x doesn't compare equal to itself.  This was a regression
from 2.6.

Reviewed by R. Hettinger and C. Heimes.

Lib/test/test_contains.py
Lib/test/test_float.py
Misc/NEWS
Objects/object.c

index e5707874489f187167780d3a3a9eeb3a288cb510..39c61bd2b5c4035be4bad53c168d52f2278b8fbe 100644 (file)
@@ -1,3 +1,4 @@
+from collections import deque
 from test.support import run_unittest
 import unittest
 
@@ -6,7 +7,7 @@ class base_set:
     def __init__(self, el):
         self.el = el
 
-class set(base_set):
+class myset(base_set):
     def __contains__(self, el):
         return self.el == el
 
@@ -17,7 +18,7 @@ class seq(base_set):
 class TestContains(unittest.TestCase):
     def test_common_tests(self):
         a = base_set(1)
-        b = set(1)
+        b = myset(1)
         c = seq(1)
         self.assert_(1 in b)
         self.assert_(0 not in b)
@@ -80,6 +81,25 @@ class TestContains(unittest.TestCase):
         except TypeError:
             pass
 
+    def test_nonreflexive(self):
+        # containment and equality tests involving elements that are
+        # not necessarily equal to themselves
+
+        class MyNonReflexive(object):
+            def __eq__(self, other):
+                return False
+            def __hash__(self):
+                return 28
+
+        values = float('nan'), 1, None, 'abc', MyNonReflexive()
+        constructors = list, tuple, dict.fromkeys, set, frozenset, deque
+        for constructor in constructors:
+            container = constructor(values)
+            for elem in container:
+                self.assert_(elem in container)
+            self.assert_(container == constructor(values))
+            self.assert_(container == container)
+
 
 def test_main():
     run_unittest(TestContains)
index 4f8446a98d8bd713cc79604506572fabed93b5a0..2d3b3575ccbb5a4111d633b5ed4a62f33ff8c747 100644 (file)
@@ -117,6 +117,33 @@ class GeneralFloatCases(unittest.TestCase):
         self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
         self.assertRaises(ValueError, float('nan').as_integer_ratio)
 
+    def test_float_containment(self):
+        floats = (INF, -INF, 0.0, 1.0, NAN)
+        for f in floats:
+            self.assert_(f in [f], "'%r' not in []" % f)
+            self.assert_(f in (f,), "'%r' not in ()" % f)
+            self.assert_(f in {f}, "'%r' not in set()" % f)
+            self.assert_(f in {f: None}, "'%r' not in {}" % f)
+            self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
+            self.assert_(f in floats, "'%r' not in container" % f)
+
+        for f in floats:
+            # nonidentical containers, same type, same contents
+            self.assert_([f] == [f], "[%r] != [%r]" % (f, f))
+            self.assert_((f,) == (f,), "(%r,) != (%r,)" % (f, f))
+            self.assert_({f} == {f}, "{%r} != {%r}" % (f, f))
+            self.assert_({f : None} == {f: None}, "{%r : None} != "
+                                                   "{%r : None}" % (f, f))
+
+            # identical containers
+            l, t, s, d = [f], (f,), {f}, {f: None}
+            self.assert_(l == l, "[%r] not equal to itself" % f)
+            self.assert_(t == t, "(%r,) not equal to itself" % f)
+            self.assert_(s == s, "{%r} not equal to itself" % f)
+            self.assert_(d == d, "{%r : None} not equal to itself" % f)
+
+
+
 class FormatFunctionsTestCase(unittest.TestCase):
 
     def setUp(self):
index ecc808feadd2876947cda37eb60486f11ecfcf02..035867c4291fac10a00463f3f07e88e6a0f2ca38 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@ What's New in Python 3.0 release candiate 3?
 Core and Builtins
 -----------------
 
+- Issue #4296: Fix PyObject_RichCompareBool so that "x in [x]" evaluates to
+  True, even when x doesn't compare equal to itself.  This was a regression
+  from 2.6.
+
 - Issue #3705: Command-line arguments were not correctly decoded when the
   terminal does not use UTF8.
 
index cdbceaf381e242dc2028999e3553c054c7395d26..2c43221a1e31f71513b631a1ca5b2b2a97cba255 100644 (file)
@@ -687,6 +687,15 @@ PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
        PyObject *res;
        int ok;
 
+       /* Quick result when objects are the same.
+          Guarantees that identity implies equality. */
+       if (v == w) {
+               if (op == Py_EQ)
+                       return 1;
+               else if (op == Py_NE)
+                       return 0;
+       }
+
        res = PyObject_RichCompare(v, w, op);
        if (res == NULL)
                return -1;