1 | "Test the functionality of Python classes implementing operators."
|
---|
2 |
|
---|
3 | import unittest
|
---|
4 |
|
---|
5 | from test import test_support
|
---|
6 |
|
---|
7 | testmeths = [
|
---|
8 |
|
---|
9 | # Binary operations
|
---|
10 | "add",
|
---|
11 | "radd",
|
---|
12 | "sub",
|
---|
13 | "rsub",
|
---|
14 | "mul",
|
---|
15 | "rmul",
|
---|
16 | "div",
|
---|
17 | "rdiv",
|
---|
18 | "mod",
|
---|
19 | "rmod",
|
---|
20 | "divmod",
|
---|
21 | "rdivmod",
|
---|
22 | "pow",
|
---|
23 | "rpow",
|
---|
24 | "rshift",
|
---|
25 | "rrshift",
|
---|
26 | "lshift",
|
---|
27 | "rlshift",
|
---|
28 | "and",
|
---|
29 | "rand",
|
---|
30 | "or",
|
---|
31 | "ror",
|
---|
32 | "xor",
|
---|
33 | "rxor",
|
---|
34 |
|
---|
35 | # List/dict operations
|
---|
36 | "contains",
|
---|
37 | "getitem",
|
---|
38 | "getslice",
|
---|
39 | "setitem",
|
---|
40 | "setslice",
|
---|
41 | "delitem",
|
---|
42 | "delslice",
|
---|
43 |
|
---|
44 | # Unary operations
|
---|
45 | "neg",
|
---|
46 | "pos",
|
---|
47 | "abs",
|
---|
48 |
|
---|
49 | # generic operations
|
---|
50 | "init",
|
---|
51 | ]
|
---|
52 |
|
---|
53 | # These need to return something other than None
|
---|
54 | # "coerce",
|
---|
55 | # "hash",
|
---|
56 | # "str",
|
---|
57 | # "repr",
|
---|
58 | # "int",
|
---|
59 | # "long",
|
---|
60 | # "float",
|
---|
61 | # "oct",
|
---|
62 | # "hex",
|
---|
63 |
|
---|
64 | # These are separate because they can influence the test of other methods.
|
---|
65 | # "getattr",
|
---|
66 | # "setattr",
|
---|
67 | # "delattr",
|
---|
68 |
|
---|
69 | callLst = []
|
---|
70 | def trackCall(f):
|
---|
71 | def track(*args, **kwargs):
|
---|
72 | callLst.append((f.__name__, args))
|
---|
73 | return f(*args, **kwargs)
|
---|
74 | return track
|
---|
75 |
|
---|
76 | class AllTests:
|
---|
77 | trackCall = trackCall
|
---|
78 |
|
---|
79 | @trackCall
|
---|
80 | def __coerce__(self, *args):
|
---|
81 | return (self,) + args
|
---|
82 |
|
---|
83 | @trackCall
|
---|
84 | def __hash__(self, *args):
|
---|
85 | return hash(id(self))
|
---|
86 |
|
---|
87 | @trackCall
|
---|
88 | def __str__(self, *args):
|
---|
89 | return "AllTests"
|
---|
90 |
|
---|
91 | @trackCall
|
---|
92 | def __repr__(self, *args):
|
---|
93 | return "AllTests"
|
---|
94 |
|
---|
95 | @trackCall
|
---|
96 | def __int__(self, *args):
|
---|
97 | return 1
|
---|
98 |
|
---|
99 | @trackCall
|
---|
100 | def __float__(self, *args):
|
---|
101 | return 1.0
|
---|
102 |
|
---|
103 | @trackCall
|
---|
104 | def __long__(self, *args):
|
---|
105 | return 1L
|
---|
106 |
|
---|
107 | @trackCall
|
---|
108 | def __oct__(self, *args):
|
---|
109 | return '01'
|
---|
110 |
|
---|
111 | @trackCall
|
---|
112 | def __hex__(self, *args):
|
---|
113 | return '0x1'
|
---|
114 |
|
---|
115 | @trackCall
|
---|
116 | def __cmp__(self, *args):
|
---|
117 | return 0
|
---|
118 |
|
---|
119 | # Synthesize all the other AllTests methods from the names in testmeths.
|
---|
120 |
|
---|
121 | method_template = """\
|
---|
122 | @trackCall
|
---|
123 | def __%(method)s__(self, *args):
|
---|
124 | pass
|
---|
125 | """
|
---|
126 |
|
---|
127 | for method in testmeths:
|
---|
128 | exec method_template % locals() in AllTests.__dict__
|
---|
129 |
|
---|
130 | del method, method_template
|
---|
131 |
|
---|
132 | class ClassTests(unittest.TestCase):
|
---|
133 | def setUp(self):
|
---|
134 | callLst[:] = []
|
---|
135 |
|
---|
136 | def assertCallStack(self, expected_calls):
|
---|
137 | actualCallList = callLst[:] # need to copy because the comparison below will add
|
---|
138 | # additional calls to callLst
|
---|
139 | if expected_calls != actualCallList:
|
---|
140 | self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
|
---|
141 | (expected_calls, actualCallList))
|
---|
142 |
|
---|
143 | def testInit(self):
|
---|
144 | foo = AllTests()
|
---|
145 | self.assertCallStack([("__init__", (foo,))])
|
---|
146 |
|
---|
147 | def testBinaryOps(self):
|
---|
148 | testme = AllTests()
|
---|
149 | # Binary operations
|
---|
150 |
|
---|
151 | callLst[:] = []
|
---|
152 | testme + 1
|
---|
153 | self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))])
|
---|
154 |
|
---|
155 | callLst[:] = []
|
---|
156 | 1 + testme
|
---|
157 | self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))])
|
---|
158 |
|
---|
159 | callLst[:] = []
|
---|
160 | testme - 1
|
---|
161 | self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))])
|
---|
162 |
|
---|
163 | callLst[:] = []
|
---|
164 | 1 - testme
|
---|
165 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))])
|
---|
166 |
|
---|
167 | callLst[:] = []
|
---|
168 | testme * 1
|
---|
169 | self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))])
|
---|
170 |
|
---|
171 | callLst[:] = []
|
---|
172 | 1 * testme
|
---|
173 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))])
|
---|
174 |
|
---|
175 | if 1/2 == 0:
|
---|
176 | callLst[:] = []
|
---|
177 | testme / 1
|
---|
178 | self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))])
|
---|
179 |
|
---|
180 |
|
---|
181 | callLst[:] = []
|
---|
182 | 1 / testme
|
---|
183 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))])
|
---|
184 |
|
---|
185 | callLst[:] = []
|
---|
186 | testme % 1
|
---|
187 | self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))])
|
---|
188 |
|
---|
189 | callLst[:] = []
|
---|
190 | 1 % testme
|
---|
191 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))])
|
---|
192 |
|
---|
193 |
|
---|
194 | callLst[:] = []
|
---|
195 | divmod(testme,1)
|
---|
196 | self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))])
|
---|
197 |
|
---|
198 | callLst[:] = []
|
---|
199 | divmod(1, testme)
|
---|
200 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))])
|
---|
201 |
|
---|
202 | callLst[:] = []
|
---|
203 | testme ** 1
|
---|
204 | self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))])
|
---|
205 |
|
---|
206 | callLst[:] = []
|
---|
207 | 1 ** testme
|
---|
208 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))])
|
---|
209 |
|
---|
210 | callLst[:] = []
|
---|
211 | testme >> 1
|
---|
212 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))])
|
---|
213 |
|
---|
214 | callLst[:] = []
|
---|
215 | 1 >> testme
|
---|
216 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))])
|
---|
217 |
|
---|
218 | callLst[:] = []
|
---|
219 | testme << 1
|
---|
220 | self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))])
|
---|
221 |
|
---|
222 | callLst[:] = []
|
---|
223 | 1 << testme
|
---|
224 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))])
|
---|
225 |
|
---|
226 | callLst[:] = []
|
---|
227 | testme & 1
|
---|
228 | self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))])
|
---|
229 |
|
---|
230 | callLst[:] = []
|
---|
231 | 1 & testme
|
---|
232 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))])
|
---|
233 |
|
---|
234 | callLst[:] = []
|
---|
235 | testme | 1
|
---|
236 | self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))])
|
---|
237 |
|
---|
238 | callLst[:] = []
|
---|
239 | 1 | testme
|
---|
240 | self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))])
|
---|
241 |
|
---|
242 | callLst[:] = []
|
---|
243 | testme ^ 1
|
---|
244 | self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))])
|
---|
245 |
|
---|
246 | callLst[:] = []
|
---|
247 | 1 ^ testme
|
---|
248 | self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))])
|
---|
249 |
|
---|
250 | def testListAndDictOps(self):
|
---|
251 | testme = AllTests()
|
---|
252 |
|
---|
253 | # List/dict operations
|
---|
254 |
|
---|
255 | class Empty: pass
|
---|
256 |
|
---|
257 | try:
|
---|
258 | 1 in Empty()
|
---|
259 | self.fail('failed, should have raised TypeError')
|
---|
260 | except TypeError:
|
---|
261 | pass
|
---|
262 |
|
---|
263 | callLst[:] = []
|
---|
264 | 1 in testme
|
---|
265 | self.assertCallStack([('__contains__', (testme, 1))])
|
---|
266 |
|
---|
267 | callLst[:] = []
|
---|
268 | testme[1]
|
---|
269 | self.assertCallStack([('__getitem__', (testme, 1))])
|
---|
270 |
|
---|
271 | callLst[:] = []
|
---|
272 | testme[1] = 1
|
---|
273 | self.assertCallStack([('__setitem__', (testme, 1, 1))])
|
---|
274 |
|
---|
275 | callLst[:] = []
|
---|
276 | del testme[1]
|
---|
277 | self.assertCallStack([('__delitem__', (testme, 1))])
|
---|
278 |
|
---|
279 | callLst[:] = []
|
---|
280 | testme[:42]
|
---|
281 | self.assertCallStack([('__getslice__', (testme, 0, 42))])
|
---|
282 |
|
---|
283 | callLst[:] = []
|
---|
284 | testme[:42] = "The Answer"
|
---|
285 | self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])
|
---|
286 |
|
---|
287 | callLst[:] = []
|
---|
288 | del testme[:42]
|
---|
289 | self.assertCallStack([('__delslice__', (testme, 0, 42))])
|
---|
290 |
|
---|
291 | callLst[:] = []
|
---|
292 | testme[2:1024:10]
|
---|
293 | self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
|
---|
294 |
|
---|
295 | callLst[:] = []
|
---|
296 | testme[2:1024:10] = "A lot"
|
---|
297 | self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
|
---|
298 | "A lot"))])
|
---|
299 | callLst[:] = []
|
---|
300 | del testme[2:1024:10]
|
---|
301 | self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
|
---|
302 |
|
---|
303 | callLst[:] = []
|
---|
304 | testme[:42, ..., :24:, 24, 100]
|
---|
305 | self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
|
---|
306 | Ellipsis,
|
---|
307 | slice(None, 24, None),
|
---|
308 | 24, 100)))])
|
---|
309 | callLst[:] = []
|
---|
310 | testme[:42, ..., :24:, 24, 100] = "Strange"
|
---|
311 | self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
|
---|
312 | Ellipsis,
|
---|
313 | slice(None, 24, None),
|
---|
314 | 24, 100), "Strange"))])
|
---|
315 | callLst[:] = []
|
---|
316 | del testme[:42, ..., :24:, 24, 100]
|
---|
317 | self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
|
---|
318 | Ellipsis,
|
---|
319 | slice(None, 24, None),
|
---|
320 | 24, 100)))])
|
---|
321 |
|
---|
322 | # Now remove the slice hooks to see if converting normal slices to
|
---|
323 | # slice object works.
|
---|
324 |
|
---|
325 | getslice = AllTests.__getslice__
|
---|
326 | del AllTests.__getslice__
|
---|
327 | setslice = AllTests.__setslice__
|
---|
328 | del AllTests.__setslice__
|
---|
329 | delslice = AllTests.__delslice__
|
---|
330 | del AllTests.__delslice__
|
---|
331 |
|
---|
332 | # XXX when using new-style classes the slice testme[:42] produces
|
---|
333 | # slice(None, 42, None) instead of slice(0, 42, None). py3k will have
|
---|
334 | # to change this test.
|
---|
335 | callLst[:] = []
|
---|
336 | testme[:42]
|
---|
337 | self.assertCallStack([('__getitem__', (testme, slice(0, 42, None)))])
|
---|
338 |
|
---|
339 | callLst[:] = []
|
---|
340 | testme[:42] = "The Answer"
|
---|
341 | self.assertCallStack([('__setitem__', (testme, slice(0, 42, None),
|
---|
342 | "The Answer"))])
|
---|
343 | callLst[:] = []
|
---|
344 | del testme[:42]
|
---|
345 | self.assertCallStack([('__delitem__', (testme, slice(0, 42, None)))])
|
---|
346 |
|
---|
347 | # Restore the slice methods, or the tests will fail with regrtest -R.
|
---|
348 | AllTests.__getslice__ = getslice
|
---|
349 | AllTests.__setslice__ = setslice
|
---|
350 | AllTests.__delslice__ = delslice
|
---|
351 |
|
---|
352 |
|
---|
353 | @test_support.cpython_only
|
---|
354 | def testDelItem(self):
|
---|
355 | class A:
|
---|
356 | ok = False
|
---|
357 | def __delitem__(self, key):
|
---|
358 | self.ok = True
|
---|
359 | a = A()
|
---|
360 | # Subtle: we need to call PySequence_SetItem, not PyMapping_SetItem.
|
---|
361 | from _testcapi import sequence_delitem
|
---|
362 | sequence_delitem(a, 2)
|
---|
363 | self.assertTrue(a.ok)
|
---|
364 |
|
---|
365 |
|
---|
366 | def testUnaryOps(self):
|
---|
367 | testme = AllTests()
|
---|
368 |
|
---|
369 | callLst[:] = []
|
---|
370 | -testme
|
---|
371 | self.assertCallStack([('__neg__', (testme,))])
|
---|
372 | callLst[:] = []
|
---|
373 | +testme
|
---|
374 | self.assertCallStack([('__pos__', (testme,))])
|
---|
375 | callLst[:] = []
|
---|
376 | abs(testme)
|
---|
377 | self.assertCallStack([('__abs__', (testme,))])
|
---|
378 | callLst[:] = []
|
---|
379 | int(testme)
|
---|
380 | self.assertCallStack([('__int__', (testme,))])
|
---|
381 | callLst[:] = []
|
---|
382 | long(testme)
|
---|
383 | self.assertCallStack([('__long__', (testme,))])
|
---|
384 | callLst[:] = []
|
---|
385 | float(testme)
|
---|
386 | self.assertCallStack([('__float__', (testme,))])
|
---|
387 | callLst[:] = []
|
---|
388 | oct(testme)
|
---|
389 | self.assertCallStack([('__oct__', (testme,))])
|
---|
390 | callLst[:] = []
|
---|
391 | hex(testme)
|
---|
392 | self.assertCallStack([('__hex__', (testme,))])
|
---|
393 |
|
---|
394 |
|
---|
395 | def testMisc(self):
|
---|
396 | testme = AllTests()
|
---|
397 |
|
---|
398 | callLst[:] = []
|
---|
399 | hash(testme)
|
---|
400 | self.assertCallStack([('__hash__', (testme,))])
|
---|
401 |
|
---|
402 | callLst[:] = []
|
---|
403 | repr(testme)
|
---|
404 | self.assertCallStack([('__repr__', (testme,))])
|
---|
405 |
|
---|
406 | callLst[:] = []
|
---|
407 | str(testme)
|
---|
408 | self.assertCallStack([('__str__', (testme,))])
|
---|
409 |
|
---|
410 | callLst[:] = []
|
---|
411 | testme == 1
|
---|
412 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
|
---|
413 |
|
---|
414 | callLst[:] = []
|
---|
415 | testme < 1
|
---|
416 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
|
---|
417 |
|
---|
418 | callLst[:] = []
|
---|
419 | testme > 1
|
---|
420 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
|
---|
421 |
|
---|
422 | callLst[:] = []
|
---|
423 | eval('testme <> 1') # XXX kill this in py3k
|
---|
424 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
|
---|
425 |
|
---|
426 | callLst[:] = []
|
---|
427 | testme != 1
|
---|
428 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
|
---|
429 |
|
---|
430 | callLst[:] = []
|
---|
431 | 1 == testme
|
---|
432 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
|
---|
433 |
|
---|
434 | callLst[:] = []
|
---|
435 | 1 < testme
|
---|
436 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
|
---|
437 |
|
---|
438 | callLst[:] = []
|
---|
439 | 1 > testme
|
---|
440 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
|
---|
441 |
|
---|
442 | callLst[:] = []
|
---|
443 | eval('1 <> testme')
|
---|
444 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
|
---|
445 |
|
---|
446 | callLst[:] = []
|
---|
447 | 1 != testme
|
---|
448 | self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
|
---|
449 |
|
---|
450 |
|
---|
451 | def testGetSetAndDel(self):
|
---|
452 | # Interfering tests
|
---|
453 | class ExtraTests(AllTests):
|
---|
454 | @trackCall
|
---|
455 | def __getattr__(self, *args):
|
---|
456 | return "SomeVal"
|
---|
457 |
|
---|
458 | @trackCall
|
---|
459 | def __setattr__(self, *args):
|
---|
460 | pass
|
---|
461 |
|
---|
462 | @trackCall
|
---|
463 | def __delattr__(self, *args):
|
---|
464 | pass
|
---|
465 |
|
---|
466 | testme = ExtraTests()
|
---|
467 |
|
---|
468 | callLst[:] = []
|
---|
469 | testme.spam
|
---|
470 | self.assertCallStack([('__getattr__', (testme, "spam"))])
|
---|
471 |
|
---|
472 | callLst[:] = []
|
---|
473 | testme.eggs = "spam, spam, spam and ham"
|
---|
474 | self.assertCallStack([('__setattr__', (testme, "eggs",
|
---|
475 | "spam, spam, spam and ham"))])
|
---|
476 |
|
---|
477 | callLst[:] = []
|
---|
478 | del testme.cardinal
|
---|
479 | self.assertCallStack([('__delattr__', (testme, "cardinal"))])
|
---|
480 |
|
---|
481 | def testDel(self):
|
---|
482 | x = []
|
---|
483 |
|
---|
484 | class DelTest:
|
---|
485 | def __del__(self):
|
---|
486 | x.append("crab people, crab people")
|
---|
487 | testme = DelTest()
|
---|
488 | del testme
|
---|
489 | import gc
|
---|
490 | gc.collect()
|
---|
491 | self.assertEqual(["crab people, crab people"], x)
|
---|
492 |
|
---|
493 | def testBadTypeReturned(self):
|
---|
494 | # return values of some method are type-checked
|
---|
495 | class BadTypeClass:
|
---|
496 | def __int__(self):
|
---|
497 | return None
|
---|
498 | __float__ = __int__
|
---|
499 | __long__ = __int__
|
---|
500 | __str__ = __int__
|
---|
501 | __repr__ = __int__
|
---|
502 | __oct__ = __int__
|
---|
503 | __hex__ = __int__
|
---|
504 |
|
---|
505 | for f in [int, float, long, str, repr, oct, hex]:
|
---|
506 | self.assertRaises(TypeError, f, BadTypeClass())
|
---|
507 |
|
---|
508 | def testMixIntsAndLongs(self):
|
---|
509 | # mixing up ints and longs is okay
|
---|
510 | class IntLongMixClass:
|
---|
511 | @trackCall
|
---|
512 | def __int__(self):
|
---|
513 | return 42L
|
---|
514 |
|
---|
515 | @trackCall
|
---|
516 | def __long__(self):
|
---|
517 | return 64
|
---|
518 |
|
---|
519 | mixIntAndLong = IntLongMixClass()
|
---|
520 |
|
---|
521 | callLst[:] = []
|
---|
522 | as_int = int(mixIntAndLong)
|
---|
523 | self.assertEqual(type(as_int), long)
|
---|
524 | self.assertEqual(as_int, 42L)
|
---|
525 | self.assertCallStack([('__int__', (mixIntAndLong,))])
|
---|
526 |
|
---|
527 | callLst[:] = []
|
---|
528 | as_long = long(mixIntAndLong)
|
---|
529 | self.assertEqual(type(as_long), long)
|
---|
530 | self.assertEqual(as_long, 64)
|
---|
531 | self.assertCallStack([('__long__', (mixIntAndLong,))])
|
---|
532 |
|
---|
533 | def testHashStuff(self):
|
---|
534 | # Test correct errors from hash() on objects with comparisons but
|
---|
535 | # no __hash__
|
---|
536 |
|
---|
537 | class C0:
|
---|
538 | pass
|
---|
539 |
|
---|
540 | hash(C0()) # This should work; the next two should raise TypeError
|
---|
541 |
|
---|
542 | class C1:
|
---|
543 | def __cmp__(self, other): return 0
|
---|
544 |
|
---|
545 | self.assertRaises(TypeError, hash, C1())
|
---|
546 |
|
---|
547 | class C2:
|
---|
548 | def __eq__(self, other): return 1
|
---|
549 |
|
---|
550 | self.assertRaises(TypeError, hash, C2())
|
---|
551 |
|
---|
552 |
|
---|
553 | def testSFBug532646(self):
|
---|
554 | # Test for SF bug 532646
|
---|
555 |
|
---|
556 | class A:
|
---|
557 | pass
|
---|
558 | A.__call__ = A()
|
---|
559 | a = A()
|
---|
560 |
|
---|
561 | try:
|
---|
562 | a() # This should not segfault
|
---|
563 | except RuntimeError:
|
---|
564 | pass
|
---|
565 | else:
|
---|
566 | self.fail("Failed to raise RuntimeError")
|
---|
567 |
|
---|
568 | def testForExceptionsRaisedInInstanceGetattr2(self):
|
---|
569 | # Tests for exceptions raised in instance_getattr2().
|
---|
570 |
|
---|
571 | def booh(self):
|
---|
572 | raise AttributeError("booh")
|
---|
573 |
|
---|
574 | class A:
|
---|
575 | a = property(booh)
|
---|
576 | try:
|
---|
577 | A().a # Raised AttributeError: A instance has no attribute 'a'
|
---|
578 | except AttributeError, x:
|
---|
579 | if str(x) != "booh":
|
---|
580 | self.fail("attribute error for A().a got masked: %s" % x)
|
---|
581 |
|
---|
582 | class E:
|
---|
583 | __eq__ = property(booh)
|
---|
584 | E() == E() # In debug mode, caused a C-level assert() to fail
|
---|
585 |
|
---|
586 | class I:
|
---|
587 | __init__ = property(booh)
|
---|
588 | try:
|
---|
589 | # In debug mode, printed XXX undetected error and
|
---|
590 | # raises AttributeError
|
---|
591 | I()
|
---|
592 | except AttributeError, x:
|
---|
593 | pass
|
---|
594 | else:
|
---|
595 | self.fail("attribute error for I.__init__ got masked")
|
---|
596 |
|
---|
597 | def testHashComparisonOfMethods(self):
|
---|
598 | # Test comparison and hash of methods
|
---|
599 | class A:
|
---|
600 | def __init__(self, x):
|
---|
601 | self.x = x
|
---|
602 | def f(self):
|
---|
603 | pass
|
---|
604 | def g(self):
|
---|
605 | pass
|
---|
606 | def __eq__(self, other):
|
---|
607 | return self.x == other.x
|
---|
608 | def __hash__(self):
|
---|
609 | return self.x
|
---|
610 | class B(A):
|
---|
611 | pass
|
---|
612 |
|
---|
613 | a1 = A(1)
|
---|
614 | a2 = A(2)
|
---|
615 | self.assertEqual(a1.f, a1.f)
|
---|
616 | self.assertNotEqual(a1.f, a2.f)
|
---|
617 | self.assertNotEqual(a1.f, a1.g)
|
---|
618 | self.assertEqual(a1.f, A(1).f)
|
---|
619 | self.assertEqual(hash(a1.f), hash(a1.f))
|
---|
620 | self.assertEqual(hash(a1.f), hash(A(1).f))
|
---|
621 |
|
---|
622 | self.assertNotEqual(A.f, a1.f)
|
---|
623 | self.assertNotEqual(A.f, A.g)
|
---|
624 | self.assertEqual(B.f, A.f)
|
---|
625 | self.assertEqual(hash(B.f), hash(A.f))
|
---|
626 |
|
---|
627 | # the following triggers a SystemError in 2.4
|
---|
628 | a = A(hash(A.f.im_func)^(-1))
|
---|
629 | hash(a.f)
|
---|
630 |
|
---|
631 | def testAttrSlots(self):
|
---|
632 | class C:
|
---|
633 | pass
|
---|
634 | for c in C, C():
|
---|
635 | self.assertRaises(TypeError, type(c).__getattribute__, c, [])
|
---|
636 | self.assertRaises(TypeError, type(c).__setattr__, c, [], [])
|
---|
637 |
|
---|
638 | def test_main():
|
---|
639 | with test_support.check_py3k_warnings(
|
---|
640 | (".+__(get|set|del)slice__ has been removed", DeprecationWarning),
|
---|
641 | ("classic int division", DeprecationWarning),
|
---|
642 | ("<> not supported", DeprecationWarning)):
|
---|
643 | test_support.run_unittest(ClassTests)
|
---|
644 |
|
---|
645 | if __name__=='__main__':
|
---|
646 | test_main()
|
---|