Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4a1f593

Browse files
committed
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.
1 parent 3d4ca74 commit 4a1f593

4 files changed

Lines changed: 62 additions & 2 deletions

File tree

Lib/test/test_contains.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import deque
12
from test.support import run_unittest
23
import unittest
34

@@ -6,7 +7,7 @@ class base_set:
67
def __init__(self, el):
78
self.el = el
89

9-
class set(base_set):
10+
class myset(base_set):
1011
def __contains__(self, el):
1112
return self.el == el
1213

@@ -17,7 +18,7 @@ def __getitem__(self, n):
1718
class TestContains(unittest.TestCase):
1819
def test_common_tests(self):
1920
a = base_set(1)
20-
b = set(1)
21+
b = myset(1)
2122
c = seq(1)
2223
self.assert_(1 in b)
2324
self.assert_(0 not in b)
@@ -80,6 +81,25 @@ def __cmp__(self, other):
8081
except TypeError:
8182
pass
8283

84+
def test_nonreflexive(self):
85+
# containment and equality tests involving elements that are
86+
# not necessarily equal to themselves
87+
88+
class MyNonReflexive(object):
89+
def __eq__(self, other):
90+
return False
91+
def __hash__(self):
92+
return 28
93+
94+
values = float('nan'), 1, None, 'abc', MyNonReflexive()
95+
constructors = list, tuple, dict.fromkeys, set, frozenset, deque
96+
for constructor in constructors:
97+
container = constructor(values)
98+
for elem in container:
99+
self.assert_(elem in container)
100+
self.assert_(container == constructor(values))
101+
self.assert_(container == container)
102+
83103

84104
def test_main():
85105
run_unittest(TestContains)

Lib/test/test_float.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,33 @@ def test_floatasratio(self):
117117
self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
118118
self.assertRaises(ValueError, float('nan').as_integer_ratio)
119119

120+
def test_float_containment(self):
121+
floats = (INF, -INF, 0.0, 1.0, NAN)
122+
for f in floats:
123+
self.assert_(f in [f], "'%r' not in []" % f)
124+
self.assert_(f in (f,), "'%r' not in ()" % f)
125+
self.assert_(f in {f}, "'%r' not in set()" % f)
126+
self.assert_(f in {f: None}, "'%r' not in {}" % f)
127+
self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
128+
self.assert_(f in floats, "'%r' not in container" % f)
129+
130+
for f in floats:
131+
# nonidentical containers, same type, same contents
132+
self.assert_([f] == [f], "[%r] != [%r]" % (f, f))
133+
self.assert_((f,) == (f,), "(%r,) != (%r,)" % (f, f))
134+
self.assert_({f} == {f}, "{%r} != {%r}" % (f, f))
135+
self.assert_({f : None} == {f: None}, "{%r : None} != "
136+
"{%r : None}" % (f, f))
137+
138+
# identical containers
139+
l, t, s, d = [f], (f,), {f}, {f: None}
140+
self.assert_(l == l, "[%r] not equal to itself" % f)
141+
self.assert_(t == t, "(%r,) not equal to itself" % f)
142+
self.assert_(s == s, "{%r} not equal to itself" % f)
143+
self.assert_(d == d, "{%r : None} not equal to itself" % f)
144+
145+
146+
120147
class FormatFunctionsTestCase(unittest.TestCase):
121148

122149
def setUp(self):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ What's New in Python 3.0 release candiate 3?
1313
Core and Builtins
1414
-----------------
1515

16+
- Issue #4296: Fix PyObject_RichCompareBool so that "x in [x]" evaluates to
17+
True, even when x doesn't compare equal to itself. This was a regression
18+
from 2.6.
19+
1620
- Issue #3705: Command-line arguments were not correctly decoded when the
1721
terminal does not use UTF8.
1822

Objects/object.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,15 @@ PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
687687
PyObject *res;
688688
int ok;
689689

690+
/* Quick result when objects are the same.
691+
Guarantees that identity implies equality. */
692+
if (v == w) {
693+
if (op == Py_EQ)
694+
return 1;
695+
else if (op == Py_NE)
696+
return 0;
697+
}
698+
690699
res = PyObject_RichCompare(v, w, op);
691700
if (res == NULL)
692701
return -1;

0 commit comments

Comments
 (0)