1 "Test the functionality of Python classes implementing operators."
2
3 import unittest
4
5
6 testmeths = [
7
8 # Binary operations
9 "add",
10 "radd",
11 "sub",
12 "rsub",
13 "mul",
14 "rmul",
15 "matmul",
16 "rmatmul",
17 "truediv",
18 "rtruediv",
19 "floordiv",
20 "rfloordiv",
21 "mod",
22 "rmod",
23 "divmod",
24 "rdivmod",
25 "pow",
26 "rpow",
27 "rshift",
28 "rrshift",
29 "lshift",
30 "rlshift",
31 "and",
32 "rand",
33 "or",
34 "ror",
35 "xor",
36 "rxor",
37
38 # List/dict operations
39 "contains",
40 "getitem",
41 "setitem",
42 "delitem",
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 # "hash",
55 # "str",
56 # "repr",
57 # "int",
58 # "float",
59
60 # These are separate because they can influence the test of other methods.
61 # "getattr",
62 # "setattr",
63 # "delattr",
64
65 callLst = []
66 def trackCall(f):
67 def track(*args, **kwargs):
68 callLst.append((f.__name__, args))
69 return f(*args, **kwargs)
70 return track
71
72 statictests = """
73 @trackCall
74 def __hash__(self, *args):
75 return hash(id(self))
76
77 @trackCall
78 def __str__(self, *args):
79 return "AllTests"
80
81 @trackCall
82 def __repr__(self, *args):
83 return "AllTests"
84
85 @trackCall
86 def __int__(self, *args):
87 return 1
88
89 @trackCall
90 def __index__(self, *args):
91 return 1
92
93 @trackCall
94 def __float__(self, *args):
95 return 1.0
96
97 @trackCall
98 def __eq__(self, *args):
99 return True
100
101 @trackCall
102 def __ne__(self, *args):
103 return False
104
105 @trackCall
106 def __lt__(self, *args):
107 return False
108
109 @trackCall
110 def __le__(self, *args):
111 return True
112
113 @trackCall
114 def __gt__(self, *args):
115 return False
116
117 @trackCall
118 def __ge__(self, *args):
119 return True
120 """
121
122 # Synthesize all the other AllTests methods from the names in testmeths.
123
124 method_template = """\
125 @trackCall
126 def __%s__(self, *args):
127 pass
128 """
129
130 d = {}
131 exec(statictests, globals(), d)
132 for method in testmeths:
133 exec(method_template % method, globals(), d)
134 AllTests = type("AllTests", (object,), d)
135 del d, statictests, method, method_template
136
137 class ESC[4;38;5;81mClassTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
138 def setUp(self):
139 callLst[:] = []
140
141 def assertCallStack(self, expected_calls):
142 actualCallList = callLst[:] # need to copy because the comparison below will add
143 # additional calls to callLst
144 if expected_calls != actualCallList:
145 self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
146 (expected_calls, actualCallList))
147
148 def testInit(self):
149 foo = AllTests()
150 self.assertCallStack([("__init__", (foo,))])
151
152 def testBinaryOps(self):
153 testme = AllTests()
154 # Binary operations
155
156 callLst[:] = []
157 testme + 1
158 self.assertCallStack([("__add__", (testme, 1))])
159
160 callLst[:] = []
161 1 + testme
162 self.assertCallStack([("__radd__", (testme, 1))])
163
164 callLst[:] = []
165 testme - 1
166 self.assertCallStack([("__sub__", (testme, 1))])
167
168 callLst[:] = []
169 1 - testme
170 self.assertCallStack([("__rsub__", (testme, 1))])
171
172 callLst[:] = []
173 testme * 1
174 self.assertCallStack([("__mul__", (testme, 1))])
175
176 callLst[:] = []
177 1 * testme
178 self.assertCallStack([("__rmul__", (testme, 1))])
179
180 callLst[:] = []
181 testme @ 1
182 self.assertCallStack([("__matmul__", (testme, 1))])
183
184 callLst[:] = []
185 1 @ testme
186 self.assertCallStack([("__rmatmul__", (testme, 1))])
187
188 callLst[:] = []
189 testme / 1
190 self.assertCallStack([("__truediv__", (testme, 1))])
191
192
193 callLst[:] = []
194 1 / testme
195 self.assertCallStack([("__rtruediv__", (testme, 1))])
196
197 callLst[:] = []
198 testme // 1
199 self.assertCallStack([("__floordiv__", (testme, 1))])
200
201
202 callLst[:] = []
203 1 // testme
204 self.assertCallStack([("__rfloordiv__", (testme, 1))])
205
206 callLst[:] = []
207 testme % 1
208 self.assertCallStack([("__mod__", (testme, 1))])
209
210 callLst[:] = []
211 1 % testme
212 self.assertCallStack([("__rmod__", (testme, 1))])
213
214
215 callLst[:] = []
216 divmod(testme,1)
217 self.assertCallStack([("__divmod__", (testme, 1))])
218
219 callLst[:] = []
220 divmod(1, testme)
221 self.assertCallStack([("__rdivmod__", (testme, 1))])
222
223 callLst[:] = []
224 testme ** 1
225 self.assertCallStack([("__pow__", (testme, 1))])
226
227 callLst[:] = []
228 1 ** testme
229 self.assertCallStack([("__rpow__", (testme, 1))])
230
231 callLst[:] = []
232 testme >> 1
233 self.assertCallStack([("__rshift__", (testme, 1))])
234
235 callLst[:] = []
236 1 >> testme
237 self.assertCallStack([("__rrshift__", (testme, 1))])
238
239 callLst[:] = []
240 testme << 1
241 self.assertCallStack([("__lshift__", (testme, 1))])
242
243 callLst[:] = []
244 1 << testme
245 self.assertCallStack([("__rlshift__", (testme, 1))])
246
247 callLst[:] = []
248 testme & 1
249 self.assertCallStack([("__and__", (testme, 1))])
250
251 callLst[:] = []
252 1 & testme
253 self.assertCallStack([("__rand__", (testme, 1))])
254
255 callLst[:] = []
256 testme | 1
257 self.assertCallStack([("__or__", (testme, 1))])
258
259 callLst[:] = []
260 1 | testme
261 self.assertCallStack([("__ror__", (testme, 1))])
262
263 callLst[:] = []
264 testme ^ 1
265 self.assertCallStack([("__xor__", (testme, 1))])
266
267 callLst[:] = []
268 1 ^ testme
269 self.assertCallStack([("__rxor__", (testme, 1))])
270
271 def testListAndDictOps(self):
272 testme = AllTests()
273
274 # List/dict operations
275
276 class ESC[4;38;5;81mEmpty: pass
277
278 try:
279 1 in Empty()
280 self.fail('failed, should have raised TypeError')
281 except TypeError:
282 pass
283
284 callLst[:] = []
285 1 in testme
286 self.assertCallStack([('__contains__', (testme, 1))])
287
288 callLst[:] = []
289 testme[1]
290 self.assertCallStack([('__getitem__', (testme, 1))])
291
292 callLst[:] = []
293 testme[1] = 1
294 self.assertCallStack([('__setitem__', (testme, 1, 1))])
295
296 callLst[:] = []
297 del testme[1]
298 self.assertCallStack([('__delitem__', (testme, 1))])
299
300 callLst[:] = []
301 testme[:42]
302 self.assertCallStack([('__getitem__', (testme, slice(None, 42)))])
303
304 callLst[:] = []
305 testme[:42] = "The Answer"
306 self.assertCallStack([('__setitem__', (testme, slice(None, 42),
307 "The Answer"))])
308
309 callLst[:] = []
310 del testme[:42]
311 self.assertCallStack([('__delitem__', (testme, slice(None, 42)))])
312
313 callLst[:] = []
314 testme[2:1024:10]
315 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
316
317 callLst[:] = []
318 testme[2:1024:10] = "A lot"
319 self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
320 "A lot"))])
321 callLst[:] = []
322 del testme[2:1024:10]
323 self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
324
325 callLst[:] = []
326 testme[:42, ..., :24:, 24, 100]
327 self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
328 Ellipsis,
329 slice(None, 24, None),
330 24, 100)))])
331 callLst[:] = []
332 testme[:42, ..., :24:, 24, 100] = "Strange"
333 self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
334 Ellipsis,
335 slice(None, 24, None),
336 24, 100), "Strange"))])
337 callLst[:] = []
338 del testme[:42, ..., :24:, 24, 100]
339 self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
340 Ellipsis,
341 slice(None, 24, None),
342 24, 100)))])
343
344 def testUnaryOps(self):
345 testme = AllTests()
346
347 callLst[:] = []
348 -testme
349 self.assertCallStack([('__neg__', (testme,))])
350 callLst[:] = []
351 +testme
352 self.assertCallStack([('__pos__', (testme,))])
353 callLst[:] = []
354 abs(testme)
355 self.assertCallStack([('__abs__', (testme,))])
356 callLst[:] = []
357 int(testme)
358 self.assertCallStack([('__int__', (testme,))])
359 callLst[:] = []
360 float(testme)
361 self.assertCallStack([('__float__', (testme,))])
362 callLst[:] = []
363 oct(testme)
364 self.assertCallStack([('__index__', (testme,))])
365 callLst[:] = []
366 hex(testme)
367 self.assertCallStack([('__index__', (testme,))])
368
369
370 def testMisc(self):
371 testme = AllTests()
372
373 callLst[:] = []
374 hash(testme)
375 self.assertCallStack([('__hash__', (testme,))])
376
377 callLst[:] = []
378 repr(testme)
379 self.assertCallStack([('__repr__', (testme,))])
380
381 callLst[:] = []
382 str(testme)
383 self.assertCallStack([('__str__', (testme,))])
384
385 callLst[:] = []
386 testme == 1
387 self.assertCallStack([('__eq__', (testme, 1))])
388
389 callLst[:] = []
390 testme < 1
391 self.assertCallStack([('__lt__', (testme, 1))])
392
393 callLst[:] = []
394 testme > 1
395 self.assertCallStack([('__gt__', (testme, 1))])
396
397 callLst[:] = []
398 testme != 1
399 self.assertCallStack([('__ne__', (testme, 1))])
400
401 callLst[:] = []
402 1 == testme
403 self.assertCallStack([('__eq__', (1, testme))])
404
405 callLst[:] = []
406 1 < testme
407 self.assertCallStack([('__gt__', (1, testme))])
408
409 callLst[:] = []
410 1 > testme
411 self.assertCallStack([('__lt__', (1, testme))])
412
413 callLst[:] = []
414 1 != testme
415 self.assertCallStack([('__ne__', (1, testme))])
416
417
418 def testGetSetAndDel(self):
419 # Interfering tests
420 class ESC[4;38;5;81mExtraTests(ESC[4;38;5;149mAllTests):
421 @trackCall
422 def __getattr__(self, *args):
423 return "SomeVal"
424
425 @trackCall
426 def __setattr__(self, *args):
427 pass
428
429 @trackCall
430 def __delattr__(self, *args):
431 pass
432
433 testme = ExtraTests()
434
435 callLst[:] = []
436 testme.spam
437 self.assertCallStack([('__getattr__', (testme, "spam"))])
438
439 callLst[:] = []
440 testme.eggs = "spam, spam, spam and ham"
441 self.assertCallStack([('__setattr__', (testme, "eggs",
442 "spam, spam, spam and ham"))])
443
444 callLst[:] = []
445 del testme.cardinal
446 self.assertCallStack([('__delattr__', (testme, "cardinal"))])
447
448 def testDel(self):
449 x = []
450
451 class ESC[4;38;5;81mDelTest:
452 def __del__(self):
453 x.append("crab people, crab people")
454 testme = DelTest()
455 del testme
456 import gc
457 gc.collect()
458 self.assertEqual(["crab people, crab people"], x)
459
460 def testBadTypeReturned(self):
461 # return values of some method are type-checked
462 class ESC[4;38;5;81mBadTypeClass:
463 def __int__(self):
464 return None
465 __float__ = __int__
466 __complex__ = __int__
467 __str__ = __int__
468 __repr__ = __int__
469 __bytes__ = __int__
470 __bool__ = __int__
471 __index__ = __int__
472 def index(x):
473 return [][x]
474
475 for f in [float, complex, str, repr, bytes, bin, oct, hex, bool, index]:
476 self.assertRaises(TypeError, f, BadTypeClass())
477
478 def testHashStuff(self):
479 # Test correct errors from hash() on objects with comparisons but
480 # no __hash__
481
482 class ESC[4;38;5;81mC0:
483 pass
484
485 hash(C0()) # This should work; the next two should raise TypeError
486
487 class ESC[4;38;5;81mC2:
488 def __eq__(self, other): return 1
489
490 self.assertRaises(TypeError, hash, C2())
491
492
493 def testSFBug532646(self):
494 # Test for SF bug 532646
495
496 class ESC[4;38;5;81mA:
497 pass
498 A.__call__ = A()
499 a = A()
500
501 try:
502 a() # This should not segfault
503 except RecursionError:
504 pass
505 else:
506 self.fail("Failed to raise RecursionError")
507
508 def testForExceptionsRaisedInInstanceGetattr2(self):
509 # Tests for exceptions raised in instance_getattr2().
510
511 def booh(self):
512 raise AttributeError("booh")
513
514 class ESC[4;38;5;81mA:
515 a = property(booh)
516 try:
517 A().a # Raised AttributeError: A instance has no attribute 'a'
518 except AttributeError as x:
519 if str(x) != "booh":
520 self.fail("attribute error for A().a got masked: %s" % x)
521
522 class ESC[4;38;5;81mE:
523 __eq__ = property(booh)
524 E() == E() # In debug mode, caused a C-level assert() to fail
525
526 class ESC[4;38;5;81mI:
527 __init__ = property(booh)
528 try:
529 # In debug mode, printed XXX undetected error and
530 # raises AttributeError
531 I()
532 except AttributeError:
533 pass
534 else:
535 self.fail("attribute error for I.__init__ got masked")
536
537 def assertNotOrderable(self, a, b):
538 with self.assertRaises(TypeError):
539 a < b
540 with self.assertRaises(TypeError):
541 a > b
542 with self.assertRaises(TypeError):
543 a <= b
544 with self.assertRaises(TypeError):
545 a >= b
546
547 def testHashComparisonOfMethods(self):
548 # Test comparison and hash of methods
549 class ESC[4;38;5;81mA:
550 def __init__(self, x):
551 self.x = x
552 def f(self):
553 pass
554 def g(self):
555 pass
556 def __eq__(self, other):
557 return True
558 def __hash__(self):
559 raise TypeError
560 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
561 pass
562
563 a1 = A(1)
564 a2 = A(1)
565 self.assertTrue(a1.f == a1.f)
566 self.assertFalse(a1.f != a1.f)
567 self.assertFalse(a1.f == a2.f)
568 self.assertTrue(a1.f != a2.f)
569 self.assertFalse(a1.f == a1.g)
570 self.assertTrue(a1.f != a1.g)
571 self.assertNotOrderable(a1.f, a1.f)
572 self.assertEqual(hash(a1.f), hash(a1.f))
573
574 self.assertFalse(A.f == a1.f)
575 self.assertTrue(A.f != a1.f)
576 self.assertFalse(A.f == A.g)
577 self.assertTrue(A.f != A.g)
578 self.assertTrue(B.f == A.f)
579 self.assertFalse(B.f != A.f)
580 self.assertNotOrderable(A.f, A.f)
581 self.assertEqual(hash(B.f), hash(A.f))
582
583 # the following triggers a SystemError in 2.4
584 a = A(hash(A.f)^(-1))
585 hash(a.f)
586
587 def testSetattrWrapperNameIntern(self):
588 # Issue #25794: __setattr__ should intern the attribute name
589 class ESC[4;38;5;81mA:
590 pass
591
592 def add(self, other):
593 return 'summa'
594
595 name = str(b'__add__', 'ascii') # shouldn't be optimized
596 self.assertIsNot(name, '__add__') # not interned
597 type.__setattr__(A, name, add)
598 self.assertEqual(A() + 1, 'summa')
599
600 name2 = str(b'__add__', 'ascii')
601 self.assertIsNot(name2, '__add__')
602 self.assertIsNot(name2, name)
603 type.__delattr__(A, name2)
604 with self.assertRaises(TypeError):
605 A() + 1
606
607 def testSetattrNonStringName(self):
608 class ESC[4;38;5;81mA:
609 pass
610
611 with self.assertRaises(TypeError):
612 type.__setattr__(A, b'x', None)
613
614 def testTypeAttributeAccessErrorMessages(self):
615 class ESC[4;38;5;81mA:
616 pass
617
618 error_msg = "type object 'A' has no attribute 'x'"
619 with self.assertRaisesRegex(AttributeError, error_msg):
620 A.x
621 with self.assertRaisesRegex(AttributeError, error_msg):
622 del A.x
623
624 def testObjectAttributeAccessErrorMessages(self):
625 class ESC[4;38;5;81mA:
626 pass
627 class ESC[4;38;5;81mB:
628 y = 0
629 __slots__ = ('z',)
630
631 error_msg = "'A' object has no attribute 'x'"
632 with self.assertRaisesRegex(AttributeError, error_msg):
633 A().x
634 with self.assertRaisesRegex(AttributeError, error_msg):
635 del A().x
636
637 error_msg = "'B' object has no attribute 'x'"
638 with self.assertRaisesRegex(AttributeError, error_msg):
639 B().x
640 with self.assertRaisesRegex(AttributeError, error_msg):
641 del B().x
642 with self.assertRaisesRegex(AttributeError, error_msg):
643 B().x = 0
644
645 error_msg = "'B' object attribute 'y' is read-only"
646 with self.assertRaisesRegex(AttributeError, error_msg):
647 del B().y
648 with self.assertRaisesRegex(AttributeError, error_msg):
649 B().y = 0
650
651 error_msg = 'z'
652 with self.assertRaisesRegex(AttributeError, error_msg):
653 B().z
654 with self.assertRaisesRegex(AttributeError, error_msg):
655 del B().z
656
657 def testConstructorErrorMessages(self):
658 # bpo-31506: Improves the error message logic for object_new & object_init
659
660 # Class without any method overrides
661 class ESC[4;38;5;81mC:
662 pass
663
664 error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
665
666 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
667 C(42)
668
669 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
670 C.__new__(C, 42)
671
672 with self.assertRaisesRegex(TypeError, error_msg):
673 C().__init__(42)
674
675 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
676 object.__new__(C, 42)
677
678 with self.assertRaisesRegex(TypeError, error_msg):
679 object.__init__(C(), 42)
680
681 # Class with both `__init__` & `__new__` method overridden
682 class ESC[4;38;5;81mD:
683 def __new__(cls, *args, **kwargs):
684 super().__new__(cls, *args, **kwargs)
685 def __init__(self, *args, **kwargs):
686 super().__init__(*args, **kwargs)
687
688 error_msg = r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
689
690 with self.assertRaisesRegex(TypeError, error_msg):
691 D(42)
692
693 with self.assertRaisesRegex(TypeError, error_msg):
694 D.__new__(D, 42)
695
696 with self.assertRaisesRegex(TypeError, error_msg):
697 object.__new__(D, 42)
698
699 # Class that only overrides __init__
700 class ESC[4;38;5;81mE:
701 def __init__(self, *args, **kwargs):
702 super().__init__(*args, **kwargs)
703
704 error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
705
706 with self.assertRaisesRegex(TypeError, error_msg):
707 E().__init__(42)
708
709 with self.assertRaisesRegex(TypeError, error_msg):
710 object.__init__(E(), 42)
711
712 def testClassWithExtCall(self):
713 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mint):
714 def __init__(*args, **kwargs):
715 pass
716
717 def __new__(cls, name, bases, attrs, **kwargs):
718 return bases, kwargs
719
720 d = {'metaclass': Meta}
721
722 class ESC[4;38;5;81mA(**ESC[4;38;5;149md): pass
723 self.assertEqual(A, ((), {}))
724 class ESC[4;38;5;81mA(0, 1, 2, 3, 4, 5, 6, 7, **ESC[4;38;5;149md): pass
725 self.assertEqual(A, (tuple(range(8)), {}))
726 class ESC[4;38;5;81mA(0, *ESC[4;38;5;149mrange(1, 8), **ESC[4;38;5;149md, foo='bar'): pass
727 self.assertEqual(A, (tuple(range(8)), {'foo': 'bar'}))
728
729
730 if __name__ == '__main__':
731 unittest.main()