0001 # Tests for rich comparisons 0002 0003 import unittest 0004 from test import test_support 0005 0006 import operator 0007 0008 class Number: 0009 0010 def __init__(self, x): 0011 self.x = x 0012 0013 def __lt__(self, other): 0014 return self.x < other 0015 0016 def __le__(self, other): 0017 return self.x <= other 0018 0019 def __eq__(self, other): 0020 return self.x == other 0021 0022 def __ne__(self, other): 0023 return self.x != other 0024 0025 def __gt__(self, other): 0026 return self.x > other 0027 0028 def __ge__(self, other): 0029 return self.x >= other 0030 0031 def __cmp__(self, other): 0032 raise test_support.TestFailed, "Number.__cmp__() should not be called" 0033 0034 def __repr__(self): 0035 return "Number(%r)" % (self.x, ) 0036 0037 class Vector: 0038 0039 def __init__(self, data): 0040 self.data = data 0041 0042 def __len__(self): 0043 return len(self.data) 0044 0045 def __getitem__(self, i): 0046 return self.data[i] 0047 0048 def __setitem__(self, i, v): 0049 self.data[i] = v 0050 0051 def __hash__(self): 0052 raise TypeError, "Vectors cannot be hashed" 0053 0054 def __nonzero__(self): 0055 raise TypeError, "Vectors cannot be used in Boolean contexts" 0056 0057 def __cmp__(self, other): 0058 raise test_support.TestFailed, "Vector.__cmp__() should not be called" 0059 0060 def __repr__(self): 0061 return "Vector(%r)" % (self.data, ) 0062 0063 def __lt__(self, other): 0064 return Vector([a < b for a, b in zip(self.data, self.__cast(other))]) 0065 0066 def __le__(self, other): 0067 return Vector([a <= b for a, b in zip(self.data, self.__cast(other))]) 0068 0069 def __eq__(self, other): 0070 return Vector([a == b for a, b in zip(self.data, self.__cast(other))]) 0071 0072 def __ne__(self, other): 0073 return Vector([a != b for a, b in zip(self.data, self.__cast(other))]) 0074 0075 def __gt__(self, other): 0076 return Vector([a > b for a, b in zip(self.data, self.__cast(other))]) 0077 0078 def __ge__(self, other): 0079 return Vector([a >= b for a, b in zip(self.data, self.__cast(other))]) 0080 0081 def __cast(self, other): 0082 if isinstance(other, Vector): 0083 other = other.data 0084 if len(self.data) != len(other): 0085 raise ValueError, "Cannot compare vectors of different length" 0086 return other 0087 0088 opmap = { 0089 "lt": (lambda a,b: a< b, operator.lt, operator.__lt__), 0090 "le": (lambda a,b: a<=b, operator.le, operator.__le__), 0091 "eq": (lambda a,b: a==b, operator.eq, operator.__eq__), 0092 "ne": (lambda a,b: a!=b, operator.ne, operator.__ne__), 0093 "gt": (lambda a,b: a> b, operator.gt, operator.__gt__), 0094 "ge": (lambda a,b: a>=b, operator.ge, operator.__ge__) 0095 } 0096 0097 class VectorTest(unittest.TestCase): 0098 0099 def checkfail(self, error, opname, *args): 0100 for op in opmap[opname]: 0101 self.assertRaises(error, op, *args) 0102 0103 def checkequal(self, opname, a, b, expres): 0104 for op in opmap[opname]: 0105 realres = op(a, b) 0106 # can't use assertEqual(realres, expres) here 0107 self.assertEqual(len(realres), len(expres)) 0108 for i in xrange(len(realres)): 0109 # results are bool, so we can use "is" here 0110 self.assert_(realres[i] is expres[i]) 0111 0112 def test_mixed(self): 0113 # check that comparisons involving Vector objects 0114 # which return rich results (i.e. Vectors with itemwise 0115 # comparison results) work 0116 a = Vector(range(2)) 0117 b = Vector(range(3)) 0118 # all comparisons should fail for different length 0119 for opname in opmap: 0120 self.checkfail(ValueError, opname, a, b) 0121 0122 a = range(5) 0123 b = 5 * [2] 0124 # try mixed arguments (but not (a, b) as that won't return a bool vector) 0125 args = [(a, Vector(b)), (Vector(a), b), (Vector(a), Vector(b))] 0126 for (a, b) in args: 0127 self.checkequal("lt", a, b, [True, True, False, False, False]) 0128 self.checkequal("le", a, b, [True, True, True, False, False]) 0129 self.checkequal("eq", a, b, [False, False, True, False, False]) 0130 self.checkequal("ne", a, b, [True, True, False, True, True ]) 0131 self.checkequal("gt", a, b, [False, False, False, True, True ]) 0132 self.checkequal("ge", a, b, [False, False, True, True, True ]) 0133 0134 for ops in opmap.itervalues(): 0135 for op in ops: 0136 # calls __nonzero__, which should fail 0137 self.assertRaises(TypeError, bool, op(a, b)) 0138 0139 class NumberTest(unittest.TestCase): 0140 0141 def test_basic(self): 0142 # Check that comparisons involving Number objects 0143 # give the same results give as comparing the 0144 # corresponding ints 0145 for a in xrange(3): 0146 for b in xrange(3): 0147 for typea in (int, Number): 0148 for typeb in (int, Number): 0149 if typea==typeb==int: 0150 continue # the combination int, int is useless 0151 ta = typea(a) 0152 tb = typeb(b) 0153 for ops in opmap.itervalues(): 0154 for op in ops: 0155 realoutcome = op(a, b) 0156 testoutcome = op(ta, tb) 0157 self.assertEqual(realoutcome, testoutcome) 0158 0159 def checkvalue(self, opname, a, b, expres): 0160 for typea in (int, Number): 0161 for typeb in (int, Number): 0162 ta = typea(a) 0163 tb = typeb(b) 0164 for op in opmap[opname]: 0165 realres = op(ta, tb) 0166 realres = getattr(realres, "x", realres) 0167 self.assert_(realres is expres) 0168 0169 def test_values(self): 0170 # check all operators and all comparison results 0171 self.checkvalue("lt", 0, 0, False) 0172 self.checkvalue("le", 0, 0, True ) 0173 self.checkvalue("eq", 0, 0, True ) 0174 self.checkvalue("ne", 0, 0, False) 0175 self.checkvalue("gt", 0, 0, False) 0176 self.checkvalue("ge", 0, 0, True ) 0177 0178 self.checkvalue("lt", 0, 1, True ) 0179 self.checkvalue("le", 0, 1, True ) 0180 self.checkvalue("eq", 0, 1, False) 0181 self.checkvalue("ne", 0, 1, True ) 0182 self.checkvalue("gt", 0, 1, False) 0183 self.checkvalue("ge", 0, 1, False) 0184 0185 self.checkvalue("lt", 1, 0, False) 0186 self.checkvalue("le", 1, 0, False) 0187 self.checkvalue("eq", 1, 0, False) 0188 self.checkvalue("ne", 1, 0, True ) 0189 self.checkvalue("gt", 1, 0, True ) 0190 self.checkvalue("ge", 1, 0, True ) 0191 0192 class MiscTest(unittest.TestCase): 0193 0194 def test_misbehavin(self): 0195 class Misb: 0196 def __lt__(self, other): return 0 0197 def __gt__(self, other): return 0 0198 def __eq__(self, other): return 0 0199 def __le__(self, other): raise TestFailed, "This shouldn't happen" 0200 def __ge__(self, other): raise TestFailed, "This shouldn't happen" 0201 def __ne__(self, other): raise TestFailed, "This shouldn't happen" 0202 def __cmp__(self, other): raise RuntimeError, "expected" 0203 a = Misb() 0204 b = Misb() 0205 self.assertEqual(a<b, 0) 0206 self.assertEqual(a==b, 0) 0207 self.assertEqual(a>b, 0) 0208 self.assertRaises(RuntimeError, cmp, a, b) 0209 0210 def test_not(self): 0211 # Check that exceptions in __nonzero__ are properly 0212 # propagated by the not operator 0213 import operator 0214 class Exc: 0215 pass 0216 class Bad: 0217 def __nonzero__(self): 0218 raise Exc 0219 0220 def do(bad): 0221 not bad 0222 0223 for func in (do, operator.not_): 0224 self.assertRaises(Exc, func, Bad()) 0225 0226 def test_recursion(self): 0227 # Check that comparison for recursive objects fails gracefully 0228 from UserList import UserList 0229 a = UserList() 0230 b = UserList() 0231 a.append(b) 0232 b.append(a) 0233 self.assertRaises(RuntimeError, operator.eq, a, b) 0234 self.assertRaises(RuntimeError, operator.ne, a, b) 0235 self.assertRaises(RuntimeError, operator.lt, a, b) 0236 self.assertRaises(RuntimeError, operator.le, a, b) 0237 self.assertRaises(RuntimeError, operator.gt, a, b) 0238 self.assertRaises(RuntimeError, operator.ge, a, b) 0239 0240 b.append(17) 0241 # Even recursive lists of different lengths are different, 0242 # but they cannot be ordered 0243 self.assert_(not (a == b)) 0244 self.assert_(a != b) 0245 self.assertRaises(RuntimeError, operator.lt, a, b) 0246 self.assertRaises(RuntimeError, operator.le, a, b) 0247 self.assertRaises(RuntimeError, operator.gt, a, b) 0248 self.assertRaises(RuntimeError, operator.ge, a, b) 0249 a.append(17) 0250 self.assertRaises(RuntimeError, operator.eq, a, b) 0251 self.assertRaises(RuntimeError, operator.ne, a, b) 0252 a.insert(0, 11) 0253 b.insert(0, 12) 0254 self.assert_(not (a == b)) 0255 self.assert_(a != b) 0256 self.assert_(a < b) 0257 0258 class DictTest(unittest.TestCase): 0259 0260 def test_dicts(self): 0261 # Verify that __eq__ and __ne__ work for dicts even if the keys and 0262 # values don't support anything other than __eq__ and __ne__. Complex 0263 # numbers are a fine example of that. 0264 import random 0265 imag1a = {} 0266 for i in range(50): 0267 imag1a[random.randrange(100)*1j] = random.randrange(100)*1j 0268 items = imag1a.items() 0269 random.shuffle(items) 0270 imag1b = {} 0271 for k, v in items: 0272 imag1b[k] = v 0273 imag2 = imag1b.copy() 0274 imag2[k] = v + 1.0 0275 self.assert_(imag1a == imag1a) 0276 self.assert_(imag1a == imag1b) 0277 self.assert_(imag2 == imag2) 0278 self.assert_(imag1a != imag2) 0279 for opname in ("lt", "le", "gt", "ge"): 0280 for op in opmap[opname]: 0281 self.assertRaises(TypeError, op, imag1a, imag2) 0282 0283 class ListTest(unittest.TestCase): 0284 0285 def assertIs(self, a, b): 0286 self.assert_(a is b) 0287 0288 def test_coverage(self): 0289 # exercise all comparisons for lists 0290 x = [42] 0291 self.assertIs(x<x, False) 0292 self.assertIs(x<=x, True) 0293 self.assertIs(x==x, True) 0294 self.assertIs(x!=x, False) 0295 self.assertIs(x>x, False) 0296 self.assertIs(x>=x, True) 0297 y = [42, 42] 0298 self.assertIs(x<y, True) 0299 self.assertIs(x<=y, True) 0300 self.assertIs(x==y, False) 0301 self.assertIs(x!=y, True) 0302 self.assertIs(x>y, False) 0303 self.assertIs(x>=y, False) 0304 0305 def test_badentry(self): 0306 # make sure that exceptions for item comparison are properly 0307 # propagated in list comparisons 0308 class Exc: 0309 pass 0310 class Bad: 0311 def __eq__(self, other): 0312 raise Exc 0313 0314 x = [Bad()] 0315 y = [Bad()] 0316 0317 for op in opmap["eq"]: 0318 self.assertRaises(Exc, op, x, y) 0319 0320 def test_goodentry(self): 0321 # This test exercises the final call to PyObject_RichCompare() 0322 # in Objects/listobject.c::list_richcompare() 0323 class Good: 0324 def __lt__(self, other): 0325 return True 0326 0327 x = [Good()] 0328 y = [Good()] 0329 0330 for op in opmap["lt"]: 0331 self.assertIs(op(x, y), True) 0332 0333 def test_main(): 0334 test_support.run_unittest(VectorTest, NumberTest, MiscTest, DictTest, ListTest) 0335 0336 if __name__ == "__main__": 0337 test_main() 0338
Generated by PyXR 0.9.4