mark.dickinson
2008-11-12 23:23:37 UTC
Author: mark.dickinson
Date: Thu Nov 13 00:23:36 2008
New Revision: 67204
Log:
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.
Reviewed by R. Hettinger and C. Heimes.
Modified:
python/branches/py3k/Lib/test/test_contains.py
python/branches/py3k/Lib/test/test_float.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Objects/object.c
Modified: python/branches/py3k/Lib/test/test_contains.py
==============================================================================
--- python/branches/py3k/Lib/test/test_contains.py (original)
+++ python/branches/py3k/Lib/test/test_contains.py Thu Nov 13 00:23:36 2008
@@ -1,3 +1,4 @@
+from collections import deque
from test.support import run_unittest
import unittest
@@ -6,7 +7,7 @@
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 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 @@
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)
Modified: python/branches/py3k/Lib/test/test_float.py
==============================================================================
--- python/branches/py3k/Lib/test/test_float.py (original)
+++ python/branches/py3k/Lib/test/test_float.py Thu Nov 13 00:23:36 2008
@@ -117,6 +117,33 @@
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):
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Thu Nov 13 00:23:36 2008
@@ -13,6 +13,10 @@
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.
Modified: python/branches/py3k/Objects/object.c
==============================================================================
--- python/branches/py3k/Objects/object.c (original)
+++ python/branches/py3k/Objects/object.c Thu Nov 13 00:23:36 2008
@@ -687,6 +687,15 @@
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;
Date: Thu Nov 13 00:23:36 2008
New Revision: 67204
Log:
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.
Reviewed by R. Hettinger and C. Heimes.
Modified:
python/branches/py3k/Lib/test/test_contains.py
python/branches/py3k/Lib/test/test_float.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Objects/object.c
Modified: python/branches/py3k/Lib/test/test_contains.py
==============================================================================
--- python/branches/py3k/Lib/test/test_contains.py (original)
+++ python/branches/py3k/Lib/test/test_contains.py Thu Nov 13 00:23:36 2008
@@ -1,3 +1,4 @@
+from collections import deque
from test.support import run_unittest
import unittest
@@ -6,7 +7,7 @@
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 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 @@
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)
Modified: python/branches/py3k/Lib/test/test_float.py
==============================================================================
--- python/branches/py3k/Lib/test/test_float.py (original)
+++ python/branches/py3k/Lib/test/test_float.py Thu Nov 13 00:23:36 2008
@@ -117,6 +117,33 @@
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):
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Thu Nov 13 00:23:36 2008
@@ -13,6 +13,10 @@
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.
Modified: python/branches/py3k/Objects/object.c
==============================================================================
--- python/branches/py3k/Objects/object.c (original)
+++ python/branches/py3k/Objects/object.c Thu Nov 13 00:23:36 2008
@@ -687,6 +687,15 @@
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;