|
1 "Test the functionality of Python classes implementing operators." |
|
2 |
|
3 from test.test_support import TestFailed |
|
4 |
|
5 testmeths = [ |
|
6 |
|
7 # Binary operations |
|
8 "add", |
|
9 "radd", |
|
10 "sub", |
|
11 "rsub", |
|
12 "mul", |
|
13 "rmul", |
|
14 "div", |
|
15 "rdiv", |
|
16 "mod", |
|
17 "rmod", |
|
18 "divmod", |
|
19 "rdivmod", |
|
20 "pow", |
|
21 "rpow", |
|
22 "rshift", |
|
23 "rrshift", |
|
24 "lshift", |
|
25 "rlshift", |
|
26 "and", |
|
27 "rand", |
|
28 "or", |
|
29 "ror", |
|
30 "xor", |
|
31 "rxor", |
|
32 |
|
33 # List/dict operations |
|
34 "contains", |
|
35 "getitem", |
|
36 "getslice", |
|
37 "setitem", |
|
38 "setslice", |
|
39 "delitem", |
|
40 "delslice", |
|
41 |
|
42 # Unary operations |
|
43 "neg", |
|
44 "pos", |
|
45 "abs", |
|
46 |
|
47 # generic operations |
|
48 "init", |
|
49 ] |
|
50 |
|
51 # These need to return something other than None |
|
52 # "coerce", |
|
53 # "hash", |
|
54 # "str", |
|
55 # "repr", |
|
56 # "int", |
|
57 # "long", |
|
58 # "float", |
|
59 # "oct", |
|
60 # "hex", |
|
61 |
|
62 # These are separate because they can influence the test of other methods. |
|
63 # "getattr", |
|
64 # "setattr", |
|
65 # "delattr", |
|
66 |
|
67 class AllTests: |
|
68 def __coerce__(self, *args): |
|
69 print "__coerce__:", args |
|
70 return (self,) + args |
|
71 |
|
72 def __hash__(self, *args): |
|
73 print "__hash__:", args |
|
74 return hash(id(self)) |
|
75 |
|
76 def __str__(self, *args): |
|
77 print "__str__:", args |
|
78 return "AllTests" |
|
79 |
|
80 def __repr__(self, *args): |
|
81 print "__repr__:", args |
|
82 return "AllTests" |
|
83 |
|
84 def __int__(self, *args): |
|
85 print "__int__:", args |
|
86 return 1 |
|
87 |
|
88 def __float__(self, *args): |
|
89 print "__float__:", args |
|
90 return 1.0 |
|
91 |
|
92 def __long__(self, *args): |
|
93 print "__long__:", args |
|
94 return 1L |
|
95 |
|
96 def __oct__(self, *args): |
|
97 print "__oct__:", args |
|
98 return '01' |
|
99 |
|
100 def __hex__(self, *args): |
|
101 print "__hex__:", args |
|
102 return '0x1' |
|
103 |
|
104 def __cmp__(self, *args): |
|
105 print "__cmp__:", args |
|
106 return 0 |
|
107 |
|
108 def __del__(self, *args): |
|
109 print "__del__:", args |
|
110 |
|
111 # Synthesize AllTests methods from the names in testmeths. |
|
112 |
|
113 method_template = """\ |
|
114 def __%(method)s__(self, *args): |
|
115 print "__%(method)s__:", args |
|
116 """ |
|
117 |
|
118 for method in testmeths: |
|
119 exec method_template % locals() in AllTests.__dict__ |
|
120 |
|
121 del method, method_template |
|
122 |
|
123 # this also tests __init__ of course. |
|
124 testme = AllTests() |
|
125 |
|
126 # Binary operations |
|
127 |
|
128 testme + 1 |
|
129 1 + testme |
|
130 |
|
131 testme - 1 |
|
132 1 - testme |
|
133 |
|
134 testme * 1 |
|
135 1 * testme |
|
136 |
|
137 if 1/2 == 0: |
|
138 testme / 1 |
|
139 1 / testme |
|
140 else: |
|
141 # True division is in effect, so "/" doesn't map to __div__ etc; but |
|
142 # the canned expected-output file requires that __div__ etc get called. |
|
143 testme.__coerce__(1) |
|
144 testme.__div__(1) |
|
145 testme.__coerce__(1) |
|
146 testme.__rdiv__(1) |
|
147 |
|
148 testme % 1 |
|
149 1 % testme |
|
150 |
|
151 divmod(testme,1) |
|
152 divmod(1, testme) |
|
153 |
|
154 testme ** 1 |
|
155 1 ** testme |
|
156 |
|
157 testme >> 1 |
|
158 1 >> testme |
|
159 |
|
160 testme << 1 |
|
161 1 << testme |
|
162 |
|
163 testme & 1 |
|
164 1 & testme |
|
165 |
|
166 testme | 1 |
|
167 1 | testme |
|
168 |
|
169 testme ^ 1 |
|
170 1 ^ testme |
|
171 |
|
172 |
|
173 # List/dict operations |
|
174 |
|
175 class Empty: pass |
|
176 |
|
177 try: |
|
178 1 in Empty() |
|
179 print 'failed, should have raised TypeError' |
|
180 except TypeError: |
|
181 pass |
|
182 |
|
183 1 in testme |
|
184 |
|
185 testme[1] |
|
186 testme[1] = 1 |
|
187 del testme[1] |
|
188 |
|
189 testme[:42] |
|
190 testme[:42] = "The Answer" |
|
191 del testme[:42] |
|
192 |
|
193 testme[2:1024:10] |
|
194 testme[2:1024:10] = "A lot" |
|
195 del testme[2:1024:10] |
|
196 |
|
197 testme[:42, ..., :24:, 24, 100] |
|
198 testme[:42, ..., :24:, 24, 100] = "Strange" |
|
199 del testme[:42, ..., :24:, 24, 100] |
|
200 |
|
201 |
|
202 # Now remove the slice hooks to see if converting normal slices to slice |
|
203 # object works. |
|
204 |
|
205 del AllTests.__getslice__ |
|
206 del AllTests.__setslice__ |
|
207 del AllTests.__delslice__ |
|
208 |
|
209 import sys |
|
210 if sys.platform[:4] != 'java': |
|
211 testme[:42] |
|
212 testme[:42] = "The Answer" |
|
213 del testme[:42] |
|
214 else: |
|
215 # This works under Jython, but the actual slice values are |
|
216 # different. |
|
217 print "__getitem__: (slice(0, 42, None),)" |
|
218 print "__setitem__: (slice(0, 42, None), 'The Answer')" |
|
219 print "__delitem__: (slice(0, 42, None),)" |
|
220 |
|
221 # Unary operations |
|
222 |
|
223 -testme |
|
224 +testme |
|
225 abs(testme) |
|
226 int(testme) |
|
227 long(testme) |
|
228 float(testme) |
|
229 oct(testme) |
|
230 hex(testme) |
|
231 |
|
232 # And the rest... |
|
233 |
|
234 hash(testme) |
|
235 repr(testme) |
|
236 str(testme) |
|
237 |
|
238 testme == 1 |
|
239 testme < 1 |
|
240 testme > 1 |
|
241 testme <> 1 |
|
242 testme != 1 |
|
243 1 == testme |
|
244 1 < testme |
|
245 1 > testme |
|
246 1 <> testme |
|
247 1 != testme |
|
248 |
|
249 # This test has to be last (duh.) |
|
250 |
|
251 del testme |
|
252 if sys.platform[:4] == 'java': |
|
253 import java |
|
254 java.lang.System.gc() |
|
255 |
|
256 # Interfering tests |
|
257 |
|
258 class ExtraTests: |
|
259 def __getattr__(self, *args): |
|
260 print "__getattr__:", args |
|
261 return "SomeVal" |
|
262 |
|
263 def __setattr__(self, *args): |
|
264 print "__setattr__:", args |
|
265 |
|
266 def __delattr__(self, *args): |
|
267 print "__delattr__:", args |
|
268 |
|
269 testme = ExtraTests() |
|
270 testme.spam |
|
271 testme.eggs = "spam, spam, spam and ham" |
|
272 del testme.cardinal |
|
273 |
|
274 |
|
275 # return values of some method are type-checked |
|
276 class BadTypeClass: |
|
277 def __int__(self): |
|
278 return None |
|
279 __float__ = __int__ |
|
280 __long__ = __int__ |
|
281 __str__ = __int__ |
|
282 __repr__ = __int__ |
|
283 __oct__ = __int__ |
|
284 __hex__ = __int__ |
|
285 |
|
286 def check_exc(stmt, exception): |
|
287 """Raise TestFailed if executing 'stmt' does not raise 'exception' |
|
288 """ |
|
289 try: |
|
290 exec stmt |
|
291 except exception: |
|
292 pass |
|
293 else: |
|
294 raise TestFailed, "%s should raise %s" % (stmt, exception) |
|
295 |
|
296 check_exc("int(BadTypeClass())", TypeError) |
|
297 check_exc("float(BadTypeClass())", TypeError) |
|
298 check_exc("long(BadTypeClass())", TypeError) |
|
299 check_exc("str(BadTypeClass())", TypeError) |
|
300 check_exc("repr(BadTypeClass())", TypeError) |
|
301 check_exc("oct(BadTypeClass())", TypeError) |
|
302 check_exc("hex(BadTypeClass())", TypeError) |
|
303 |
|
304 # mixing up ints and longs is okay |
|
305 class IntLongMixClass: |
|
306 def __int__(self): |
|
307 return 0L |
|
308 |
|
309 def __long__(self): |
|
310 return 0 |
|
311 |
|
312 try: |
|
313 int(IntLongMixClass()) |
|
314 except TypeError: |
|
315 raise TestFailed, "TypeError should not be raised" |
|
316 |
|
317 try: |
|
318 long(IntLongMixClass()) |
|
319 except TypeError: |
|
320 raise TestFailed, "TypeError should not be raised" |
|
321 |
|
322 |
|
323 # Test correct errors from hash() on objects with comparisons but no __hash__ |
|
324 |
|
325 class C0: |
|
326 pass |
|
327 |
|
328 hash(C0()) # This should work; the next two should raise TypeError |
|
329 |
|
330 class C1: |
|
331 def __cmp__(self, other): return 0 |
|
332 |
|
333 check_exc("hash(C1())", TypeError) |
|
334 |
|
335 class C2: |
|
336 def __eq__(self, other): return 1 |
|
337 |
|
338 check_exc("hash(C2())", TypeError) |
|
339 |
|
340 # Test for SF bug 532646 |
|
341 |
|
342 class A: |
|
343 pass |
|
344 A.__call__ = A() |
|
345 a = A() |
|
346 try: |
|
347 a() # This should not segfault |
|
348 except RuntimeError: |
|
349 pass |
|
350 else: |
|
351 raise TestFailed, "how could this not have overflowed the stack?" |
|
352 |
|
353 |
|
354 # Tests for exceptions raised in instance_getattr2(). |
|
355 |
|
356 def booh(self): |
|
357 raise AttributeError, "booh" |
|
358 |
|
359 class A: |
|
360 a = property(booh) |
|
361 try: |
|
362 A().a # Raised AttributeError: A instance has no attribute 'a' |
|
363 except AttributeError, x: |
|
364 if str(x) != "booh": |
|
365 print "attribute error for A().a got masked:", str(x) |
|
366 |
|
367 class E: |
|
368 __eq__ = property(booh) |
|
369 E() == E() # In debug mode, caused a C-level assert() to fail |
|
370 |
|
371 class I: |
|
372 __init__ = property(booh) |
|
373 try: |
|
374 I() # In debug mode, printed XXX undetected error and raises AttributeError |
|
375 except AttributeError, x: |
|
376 pass |
|
377 else: |
|
378 print "attribute error for I.__init__ got masked" |
|
379 |
|
380 |
|
381 # Test comparison and hash of methods |
|
382 class A: |
|
383 def __init__(self, x): |
|
384 self.x = x |
|
385 def f(self): |
|
386 pass |
|
387 def g(self): |
|
388 pass |
|
389 def __eq__(self, other): |
|
390 return self.x == other.x |
|
391 def __hash__(self): |
|
392 return self.x |
|
393 class B(A): |
|
394 pass |
|
395 |
|
396 a1 = A(1) |
|
397 a2 = A(2) |
|
398 assert a1.f == a1.f |
|
399 assert a1.f != a2.f |
|
400 assert a1.f != a1.g |
|
401 assert a1.f == A(1).f |
|
402 assert hash(a1.f) == hash(a1.f) |
|
403 assert hash(a1.f) == hash(A(1).f) |
|
404 |
|
405 assert A.f != a1.f |
|
406 assert A.f != A.g |
|
407 assert B.f == A.f |
|
408 assert hash(B.f) == hash(A.f) |
|
409 |
|
410 # the following triggers a SystemError in 2.4 |
|
411 a = A(hash(A.f.im_func)^(-1)) |
|
412 hash(a.f) |