Update version number and release date.
[python/dscho.git] / Lib / test / test_richcmp.py
blobf4c2c7f43e8afb803c5c1a1eb4c37e3f420e5988
1 # Tests for rich comparisons
3 from test.test_support import TestFailed, verify, verbose
5 class Number:
7 def __init__(self, x):
8 self.x = x
10 def __lt__(self, other):
11 return self.x < other
13 def __le__(self, other):
14 return self.x <= other
16 def __eq__(self, other):
17 return self.x == other
19 def __ne__(self, other):
20 return self.x != other
22 def __gt__(self, other):
23 return self.x > other
25 def __ge__(self, other):
26 return self.x >= other
28 def __cmp__(self, other):
29 raise TestFailed, "Number.__cmp__() should not be called"
31 def __repr__(self):
32 return "Number(%s)" % repr(self.x)
34 class Vector:
36 def __init__(self, data):
37 self.data = data
39 def __len__(self):
40 return len(self.data)
42 def __getitem__(self, i):
43 return self.data[i]
45 def __setitem__(self, i, v):
46 self.data[i] = v
48 def __hash__(self):
49 raise TypeError, "Vectors cannot be hashed"
51 def __nonzero__(self):
52 raise TypeError, "Vectors cannot be used in Boolean contexts"
54 def __cmp__(self, other):
55 raise TestFailed, "Vector.__cmp__() should not be called"
57 def __repr__(self):
58 return "Vector(%s)" % repr(self.data)
60 def __lt__(self, other):
61 return Vector([a < b for a, b in zip(self.data, self.__cast(other))])
63 def __le__(self, other):
64 return Vector([a <= b for a, b in zip(self.data, self.__cast(other))])
66 def __eq__(self, other):
67 return Vector([a == b for a, b in zip(self.data, self.__cast(other))])
69 def __ne__(self, other):
70 return Vector([a != b for a, b in zip(self.data, self.__cast(other))])
72 def __gt__(self, other):
73 return Vector([a > b for a, b in zip(self.data, self.__cast(other))])
75 def __ge__(self, other):
76 return Vector([a >= b for a, b in zip(self.data, self.__cast(other))])
78 def __cast(self, other):
79 if isinstance(other, Vector):
80 other = other.data
81 if len(self.data) != len(other):
82 raise ValueError, "Cannot compare vectors of different length"
83 return other
85 operators = "<", "<=", "==", "!=", ">", ">="
86 opmap = {}
87 for op in operators:
88 opmap[op] = eval("lambda a, b: a %s b" % op)
90 def testvector():
91 a = Vector(range(2))
92 b = Vector(range(3))
93 for op in operators:
94 try:
95 opmap[op](a, b)
96 except ValueError:
97 pass
98 else:
99 raise TestFailed, "a %s b for different length should fail" % op
100 a = Vector(range(5))
101 b = Vector(5 * [2])
102 for op in operators:
103 print "%23s %-2s %-23s -> %s" % (a, op, b, opmap[op](a, b))
104 print "%23s %-2s %-23s -> %s" % (a, op, b.data, opmap[op](a, b.data))
105 print "%23s %-2s %-23s -> %s" % (a.data, op, b, opmap[op](a.data, b))
106 try:
107 if opmap[op](a, b):
108 raise TestFailed, "a %s b shouldn't be true" % op
109 else:
110 raise TestFailed, "a %s b shouldn't be false" % op
111 except TypeError:
112 pass
114 def testop(a, b, op):
115 try:
116 ax = a.x
117 except AttributeError:
118 ax = a
119 try:
120 bx = b.x
121 except AttributeError:
122 bx = b
123 opfunc = opmap[op]
124 realoutcome = opfunc(ax, bx)
125 testoutcome = opfunc(a, b)
126 if realoutcome != testoutcome:
127 print "Error for", a, op, b, ": expected", realoutcome,
128 print "but got", testoutcome
129 ## else:
130 ## print a, op, b, "-->", testoutcome # and "true" or "false"
132 def testit(a, b):
133 testop(a, b, "<")
134 testop(a, b, "<=")
135 testop(a, b, "==")
136 testop(a, b, "!=")
137 testop(a, b, ">")
138 testop(a, b, ">=")
140 def basic():
141 for a in range(3):
142 for b in range(3):
143 testit(Number(a), Number(b))
144 testit(a, Number(b))
145 testit(Number(a), b)
147 def tabulate(c1=Number, c2=Number):
148 for op in operators:
149 opfunc = opmap[op]
150 print
151 print "operator:", op
152 print
153 print "%9s" % "",
154 for b in range(3):
155 b = c2(b)
156 print "| %9s" % b,
157 print "|"
158 print '----------+-' * 4
159 for a in range(3):
160 a = c1(a)
161 print "%9s" % a,
162 for b in range(3):
163 b = c2(b)
164 print "| %9s" % opfunc(a, b),
165 print "|"
166 print '----------+-' * 4
167 print
168 print '*' * 50
170 def misbehavin():
171 class Misb:
172 def __lt__(self, other): return 0
173 def __gt__(self, other): return 0
174 def __eq__(self, other): return 0
175 def __le__(self, other): raise TestFailed, "This shouldn't happen"
176 def __ge__(self, other): raise TestFailed, "This shouldn't happen"
177 def __ne__(self, other): raise TestFailed, "This shouldn't happen"
178 def __cmp__(self, other): raise RuntimeError, "expected"
179 a = Misb()
180 b = Misb()
181 verify((a<b) == 0)
182 verify((a==b) == 0)
183 verify((a>b) == 0)
184 try:
185 print cmp(a, b)
186 except RuntimeError:
187 pass
188 else:
189 raise TestFailed, "cmp(Misb(), Misb()) didn't raise RuntimeError"
191 def recursion():
192 from UserList import UserList
193 a = UserList(); a.append(a)
194 b = UserList(); b.append(b)
195 def check(s, a=a, b=b):
196 if verbose:
197 print "check", s
198 try:
199 if not eval(s):
200 raise TestFailed, s + " was false but expected to be true"
201 except RuntimeError, msg:
202 raise TestFailed, str(msg)
203 if verbose:
204 print "recursion tests: a=%s, b=%s" % (a, b)
205 check('a==b')
206 check('not a!=b')
207 a.append(1)
208 if verbose:
209 print "recursion tests: a=%s, b=%s" % (a, b)
210 check('a!=b')
211 check('not a==b')
212 b.append(0)
213 if verbose:
214 print "recursion tests: a=%s, b=%s" % (a, b)
215 check('a!=b')
216 check('not a==b')
217 a[1] = -1
218 if verbose:
219 print "recursion tests: a=%s, b=%s" % (a, b)
220 check('a!=b')
221 check('not a==b')
222 if verbose: print "recursion tests ok"
224 def dicts():
225 # Verify that __eq__ and __ne__ work for dicts even if the keys and
226 # values don't support anything other than __eq__ and __ne__. Complex
227 # numbers are a fine example of that.
228 import random
229 imag1a = {}
230 for i in range(50):
231 imag1a[random.randrange(100)*1j] = random.randrange(100)*1j
232 items = imag1a.items()
233 random.shuffle(items)
234 imag1b = {}
235 for k, v in items:
236 imag1b[k] = v
237 imag2 = imag1b.copy()
238 imag2[k] = v + 1.0
239 verify(imag1a == imag1a, "imag1a == imag1a should have worked")
240 verify(imag1a == imag1b, "imag1a == imag1b should have worked")
241 verify(imag2 == imag2, "imag2 == imag2 should have worked")
242 verify(imag1a != imag2, "imag1a != imag2 should have worked")
243 for op in "<", "<=", ">", ">=":
244 try:
245 eval("imag1a %s imag2" % op)
246 except TypeError:
247 pass
248 else:
249 raise TestFailed("expected TypeError from imag1a %s imag2" % op)
251 def main():
252 basic()
253 tabulate()
254 tabulate(c1=int)
255 tabulate(c2=int)
256 testvector()
257 misbehavin()
258 recursion()
259 dicts()
261 main()