1 # Tests for rich comparisons
4 from test
import test_support
10 def __init__(self
, x
):
13 def __lt__(self
, other
):
16 def __le__(self
, other
):
17 return self
.x
<= other
19 def __eq__(self
, other
):
20 return self
.x
== other
22 def __ne__(self
, other
):
23 return self
.x
!= other
25 def __gt__(self
, other
):
28 def __ge__(self
, other
):
29 return self
.x
>= other
31 def __cmp__(self
, other
):
32 raise test_support
.TestFailed
, "Number.__cmp__() should not be called"
35 return "Number(%r)" % (self
.x
, )
39 def __init__(self
, data
):
45 def __getitem__(self
, i
):
48 def __setitem__(self
, i
, v
):
51 __hash__
= None # Vectors cannot be hashed
53 def __nonzero__(self
):
54 raise TypeError, "Vectors cannot be used in Boolean contexts"
56 def __cmp__(self
, other
):
57 raise test_support
.TestFailed
, "Vector.__cmp__() should not be called"
60 return "Vector(%r)" % (self
.data
, )
62 def __lt__(self
, other
):
63 return Vector([a
< b
for a
, b
in zip(self
.data
, self
.__cast
(other
))])
65 def __le__(self
, other
):
66 return Vector([a
<= b
for a
, b
in zip(self
.data
, self
.__cast
(other
))])
68 def __eq__(self
, other
):
69 return Vector([a
== b
for a
, b
in zip(self
.data
, self
.__cast
(other
))])
71 def __ne__(self
, other
):
72 return Vector([a
!= b
for a
, b
in zip(self
.data
, self
.__cast
(other
))])
74 def __gt__(self
, other
):
75 return Vector([a
> b
for a
, b
in zip(self
.data
, self
.__cast
(other
))])
77 def __ge__(self
, other
):
78 return Vector([a
>= b
for a
, b
in zip(self
.data
, self
.__cast
(other
))])
80 def __cast(self
, other
):
81 if isinstance(other
, Vector
):
83 if len(self
.data
) != len(other
):
84 raise ValueError, "Cannot compare vectors of different length"
88 "lt": (lambda a
,b
: a
< b
, operator
.lt
, operator
.__lt
__),
89 "le": (lambda a
,b
: a
<=b
, operator
.le
, operator
.__le
__),
90 "eq": (lambda a
,b
: a
==b
, operator
.eq
, operator
.__eq
__),
91 "ne": (lambda a
,b
: a
!=b
, operator
.ne
, operator
.__ne
__),
92 "gt": (lambda a
,b
: a
> b
, operator
.gt
, operator
.__gt
__),
93 "ge": (lambda a
,b
: a
>=b
, operator
.ge
, operator
.__ge
__)
96 class VectorTest(unittest
.TestCase
):
98 def checkfail(self
, error
, opname
, *args
):
99 for op
in opmap
[opname
]:
100 self
.assertRaises(error
, op
, *args
)
102 def checkequal(self
, opname
, a
, b
, expres
):
103 for op
in opmap
[opname
]:
105 # can't use assertEqual(realres, expres) here
106 self
.assertEqual(len(realres
), len(expres
))
107 for i
in xrange(len(realres
)):
108 # results are bool, so we can use "is" here
109 self
.assert_(realres
[i
] is expres
[i
])
111 def test_mixed(self
):
112 # check that comparisons involving Vector objects
113 # which return rich results (i.e. Vectors with itemwise
114 # comparison results) work
117 # all comparisons should fail for different length
119 self
.checkfail(ValueError, opname
, a
, b
)
123 # try mixed arguments (but not (a, b) as that won't return a bool vector)
124 args
= [(a
, Vector(b
)), (Vector(a
), b
), (Vector(a
), Vector(b
))]
126 self
.checkequal("lt", a
, b
, [True, True, False, False, False])
127 self
.checkequal("le", a
, b
, [True, True, True, False, False])
128 self
.checkequal("eq", a
, b
, [False, False, True, False, False])
129 self
.checkequal("ne", a
, b
, [True, True, False, True, True ])
130 self
.checkequal("gt", a
, b
, [False, False, False, True, True ])
131 self
.checkequal("ge", a
, b
, [False, False, True, True, True ])
133 for ops
in opmap
.itervalues():
135 # calls __nonzero__, which should fail
136 self
.assertRaises(TypeError, bool, op(a
, b
))
138 class NumberTest(unittest
.TestCase
):
140 def test_basic(self
):
141 # Check that comparisons involving Number objects
142 # give the same results give as comparing the
146 for typea
in (int, Number
):
147 for typeb
in (int, Number
):
148 if typea
==typeb
==int:
149 continue # the combination int, int is useless
152 for ops
in opmap
.itervalues():
154 realoutcome
= op(a
, b
)
155 testoutcome
= op(ta
, tb
)
156 self
.assertEqual(realoutcome
, testoutcome
)
158 def checkvalue(self
, opname
, a
, b
, expres
):
159 for typea
in (int, Number
):
160 for typeb
in (int, Number
):
163 for op
in opmap
[opname
]:
165 realres
= getattr(realres
, "x", realres
)
166 self
.assert_(realres
is expres
)
168 def test_values(self
):
169 # check all operators and all comparison results
170 self
.checkvalue("lt", 0, 0, False)
171 self
.checkvalue("le", 0, 0, True )
172 self
.checkvalue("eq", 0, 0, True )
173 self
.checkvalue("ne", 0, 0, False)
174 self
.checkvalue("gt", 0, 0, False)
175 self
.checkvalue("ge", 0, 0, True )
177 self
.checkvalue("lt", 0, 1, True )
178 self
.checkvalue("le", 0, 1, True )
179 self
.checkvalue("eq", 0, 1, False)
180 self
.checkvalue("ne", 0, 1, True )
181 self
.checkvalue("gt", 0, 1, False)
182 self
.checkvalue("ge", 0, 1, False)
184 self
.checkvalue("lt", 1, 0, False)
185 self
.checkvalue("le", 1, 0, False)
186 self
.checkvalue("eq", 1, 0, False)
187 self
.checkvalue("ne", 1, 0, True )
188 self
.checkvalue("gt", 1, 0, True )
189 self
.checkvalue("ge", 1, 0, True )
191 class MiscTest(unittest
.TestCase
):
193 def test_misbehavin(self
):
195 def __lt__(self
, other
): return 0
196 def __gt__(self
, other
): return 0
197 def __eq__(self
, other
): return 0
198 def __le__(self
, other
): raise TestFailed
, "This shouldn't happen"
199 def __ge__(self
, other
): raise TestFailed
, "This shouldn't happen"
200 def __ne__(self
, other
): raise TestFailed
, "This shouldn't happen"
201 def __cmp__(self
, other
): raise RuntimeError, "expected"
204 self
.assertEqual(a
<b
, 0)
205 self
.assertEqual(a
==b
, 0)
206 self
.assertEqual(a
>b
, 0)
207 self
.assertRaises(RuntimeError, cmp, a
, b
)
210 # Check that exceptions in __nonzero__ are properly
211 # propagated by the not operator
213 class Exc(Exception):
216 def __nonzero__(self
):
222 for func
in (do
, operator
.not_
):
223 self
.assertRaises(Exc
, func
, Bad())
225 def test_recursion(self
):
226 # Check that comparison for recursive objects fails gracefully
227 from UserList
import UserList
232 self
.assertRaises(RuntimeError, operator
.eq
, a
, b
)
233 self
.assertRaises(RuntimeError, operator
.ne
, a
, b
)
234 self
.assertRaises(RuntimeError, operator
.lt
, a
, b
)
235 self
.assertRaises(RuntimeError, operator
.le
, a
, b
)
236 self
.assertRaises(RuntimeError, operator
.gt
, a
, b
)
237 self
.assertRaises(RuntimeError, operator
.ge
, a
, b
)
240 # Even recursive lists of different lengths are different,
241 # but they cannot be ordered
242 self
.assert_(not (a
== b
))
244 self
.assertRaises(RuntimeError, operator
.lt
, a
, b
)
245 self
.assertRaises(RuntimeError, operator
.le
, a
, b
)
246 self
.assertRaises(RuntimeError, operator
.gt
, a
, b
)
247 self
.assertRaises(RuntimeError, operator
.ge
, a
, b
)
249 self
.assertRaises(RuntimeError, operator
.eq
, a
, b
)
250 self
.assertRaises(RuntimeError, operator
.ne
, a
, b
)
253 self
.assert_(not (a
== b
))
257 class DictTest(unittest
.TestCase
):
259 def test_dicts(self
):
260 # Verify that __eq__ and __ne__ work for dicts even if the keys and
261 # values don't support anything other than __eq__ and __ne__ (and
262 # __hash__). Complex numbers are a fine example of that.
266 imag1a
[random
.randrange(100)*1j
] = random
.randrange(100)*1j
267 items
= imag1a
.items()
268 random
.shuffle(items
)
272 imag2
= imag1b
.copy()
274 self
.assert_(imag1a
== imag1a
)
275 self
.assert_(imag1a
== imag1b
)
276 self
.assert_(imag2
== imag2
)
277 self
.assert_(imag1a
!= imag2
)
278 for opname
in ("lt", "le", "gt", "ge"):
279 for op
in opmap
[opname
]:
280 self
.assertRaises(TypeError, op
, imag1a
, imag2
)
282 class ListTest(unittest
.TestCase
):
284 def assertIs(self
, a
, b
):
287 def test_coverage(self
):
288 # exercise all comparisons for lists
290 self
.assertIs(x
<x
, False)
291 self
.assertIs(x
<=x
, True)
292 self
.assertIs(x
==x
, True)
293 self
.assertIs(x
!=x
, False)
294 self
.assertIs(x
>x
, False)
295 self
.assertIs(x
>=x
, True)
297 self
.assertIs(x
<y
, True)
298 self
.assertIs(x
<=y
, True)
299 self
.assertIs(x
==y
, False)
300 self
.assertIs(x
!=y
, True)
301 self
.assertIs(x
>y
, False)
302 self
.assertIs(x
>=y
, False)
304 def test_badentry(self
):
305 # make sure that exceptions for item comparison are properly
306 # propagated in list comparisons
307 class Exc(Exception):
310 def __eq__(self
, other
):
316 for op
in opmap
["eq"]:
317 self
.assertRaises(Exc
, op
, x
, y
)
319 def test_goodentry(self
):
320 # This test exercises the final call to PyObject_RichCompare()
321 # in Objects/listobject.c::list_richcompare()
323 def __lt__(self
, other
):
329 for op
in opmap
["lt"]:
330 self
.assertIs(op(x
, y
), True)
333 test_support
.run_unittest(VectorTest
, NumberTest
, MiscTest
, DictTest
, ListTest
)
335 if __name__
== "__main__":