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 testHasAttrString(self):
449 import sys
450 from test.support import import_helper
451 _testcapi = import_helper.import_module('_testcapi')
452
453 class ESC[4;38;5;81mA:
454 def __init__(self):
455 self.attr = 1
456
457 a = A()
458 self.assertEqual(_testcapi.object_hasattrstring(a, b"attr"), 1)
459 self.assertEqual(_testcapi.object_hasattrstring(a, b"noattr"), 0)
460 self.assertIsNone(sys.exception())
461
462 def testDel(self):
463 x = []
464
465 class ESC[4;38;5;81mDelTest:
466 def __del__(self):
467 x.append("crab people, crab people")
468 testme = DelTest()
469 del testme
470 import gc
471 gc.collect()
472 self.assertEqual(["crab people, crab people"], x)
473
474 def testBadTypeReturned(self):
475 # return values of some method are type-checked
476 class ESC[4;38;5;81mBadTypeClass:
477 def __int__(self):
478 return None
479 __float__ = __int__
480 __complex__ = __int__
481 __str__ = __int__
482 __repr__ = __int__
483 __bytes__ = __int__
484 __bool__ = __int__
485 __index__ = __int__
486 def index(x):
487 return [][x]
488
489 for f in [float, complex, str, repr, bytes, bin, oct, hex, bool, index]:
490 self.assertRaises(TypeError, f, BadTypeClass())
491
492 def testHashStuff(self):
493 # Test correct errors from hash() on objects with comparisons but
494 # no __hash__
495
496 class ESC[4;38;5;81mC0:
497 pass
498
499 hash(C0()) # This should work; the next two should raise TypeError
500
501 class ESC[4;38;5;81mC2:
502 def __eq__(self, other): return 1
503
504 self.assertRaises(TypeError, hash, C2())
505
506
507 def testSFBug532646(self):
508 # Test for SF bug 532646
509
510 class ESC[4;38;5;81mA:
511 pass
512 A.__call__ = A()
513 a = A()
514
515 try:
516 a() # This should not segfault
517 except RecursionError:
518 pass
519 else:
520 self.fail("Failed to raise RecursionError")
521
522 def testForExceptionsRaisedInInstanceGetattr2(self):
523 # Tests for exceptions raised in instance_getattr2().
524
525 def booh(self):
526 raise AttributeError("booh")
527
528 class ESC[4;38;5;81mA:
529 a = property(booh)
530 try:
531 A().a # Raised AttributeError: A instance has no attribute 'a'
532 except AttributeError as x:
533 if str(x) != "booh":
534 self.fail("attribute error for A().a got masked: %s" % x)
535
536 class ESC[4;38;5;81mE:
537 __eq__ = property(booh)
538 E() == E() # In debug mode, caused a C-level assert() to fail
539
540 class ESC[4;38;5;81mI:
541 __init__ = property(booh)
542 try:
543 # In debug mode, printed XXX undetected error and
544 # raises AttributeError
545 I()
546 except AttributeError:
547 pass
548 else:
549 self.fail("attribute error for I.__init__ got masked")
550
551 def assertNotOrderable(self, a, b):
552 with self.assertRaises(TypeError):
553 a < b
554 with self.assertRaises(TypeError):
555 a > b
556 with self.assertRaises(TypeError):
557 a <= b
558 with self.assertRaises(TypeError):
559 a >= b
560
561 def testHashComparisonOfMethods(self):
562 # Test comparison and hash of methods
563 class ESC[4;38;5;81mA:
564 def __init__(self, x):
565 self.x = x
566 def f(self):
567 pass
568 def g(self):
569 pass
570 def __eq__(self, other):
571 return True
572 def __hash__(self):
573 raise TypeError
574 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
575 pass
576
577 a1 = A(1)
578 a2 = A(1)
579 self.assertTrue(a1.f == a1.f)
580 self.assertFalse(a1.f != a1.f)
581 self.assertFalse(a1.f == a2.f)
582 self.assertTrue(a1.f != a2.f)
583 self.assertFalse(a1.f == a1.g)
584 self.assertTrue(a1.f != a1.g)
585 self.assertNotOrderable(a1.f, a1.f)
586 self.assertEqual(hash(a1.f), hash(a1.f))
587
588 self.assertFalse(A.f == a1.f)
589 self.assertTrue(A.f != a1.f)
590 self.assertFalse(A.f == A.g)
591 self.assertTrue(A.f != A.g)
592 self.assertTrue(B.f == A.f)
593 self.assertFalse(B.f != A.f)
594 self.assertNotOrderable(A.f, A.f)
595 self.assertEqual(hash(B.f), hash(A.f))
596
597 # the following triggers a SystemError in 2.4
598 a = A(hash(A.f)^(-1))
599 hash(a.f)
600
601 def testSetattrWrapperNameIntern(self):
602 # Issue #25794: __setattr__ should intern the attribute name
603 class ESC[4;38;5;81mA:
604 pass
605
606 def add(self, other):
607 return 'summa'
608
609 name = str(b'__add__', 'ascii') # shouldn't be optimized
610 self.assertIsNot(name, '__add__') # not interned
611 type.__setattr__(A, name, add)
612 self.assertEqual(A() + 1, 'summa')
613
614 name2 = str(b'__add__', 'ascii')
615 self.assertIsNot(name2, '__add__')
616 self.assertIsNot(name2, name)
617 type.__delattr__(A, name2)
618 with self.assertRaises(TypeError):
619 A() + 1
620
621 def testSetattrNonStringName(self):
622 class ESC[4;38;5;81mA:
623 pass
624
625 with self.assertRaises(TypeError):
626 type.__setattr__(A, b'x', None)
627
628 def testTypeAttributeAccessErrorMessages(self):
629 class ESC[4;38;5;81mA:
630 pass
631
632 error_msg = "type object 'A' has no attribute 'x'"
633 with self.assertRaisesRegex(AttributeError, error_msg):
634 A.x
635 with self.assertRaisesRegex(AttributeError, error_msg):
636 del A.x
637
638 def testObjectAttributeAccessErrorMessages(self):
639 class ESC[4;38;5;81mA:
640 pass
641 class ESC[4;38;5;81mB:
642 y = 0
643 __slots__ = ('z',)
644
645 error_msg = "'A' object has no attribute 'x'"
646 with self.assertRaisesRegex(AttributeError, error_msg):
647 A().x
648 with self.assertRaisesRegex(AttributeError, error_msg):
649 del A().x
650
651 error_msg = "'B' object has no attribute 'x'"
652 with self.assertRaisesRegex(AttributeError, error_msg):
653 B().x
654 with self.assertRaisesRegex(AttributeError, error_msg):
655 del B().x
656 with self.assertRaisesRegex(AttributeError, error_msg):
657 B().x = 0
658
659 error_msg = "'B' object attribute 'y' is read-only"
660 with self.assertRaisesRegex(AttributeError, error_msg):
661 del B().y
662 with self.assertRaisesRegex(AttributeError, error_msg):
663 B().y = 0
664
665 error_msg = 'z'
666 with self.assertRaisesRegex(AttributeError, error_msg):
667 B().z
668 with self.assertRaisesRegex(AttributeError, error_msg):
669 del B().z
670
671 def testConstructorErrorMessages(self):
672 # bpo-31506: Improves the error message logic for object_new & object_init
673
674 # Class without any method overrides
675 class ESC[4;38;5;81mC:
676 pass
677
678 error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
679
680 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
681 C(42)
682
683 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
684 C.__new__(C, 42)
685
686 with self.assertRaisesRegex(TypeError, error_msg):
687 C().__init__(42)
688
689 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
690 object.__new__(C, 42)
691
692 with self.assertRaisesRegex(TypeError, error_msg):
693 object.__init__(C(), 42)
694
695 # Class with both `__init__` & `__new__` method overridden
696 class ESC[4;38;5;81mD:
697 def __new__(cls, *args, **kwargs):
698 super().__new__(cls, *args, **kwargs)
699 def __init__(self, *args, **kwargs):
700 super().__init__(*args, **kwargs)
701
702 error_msg = r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
703
704 with self.assertRaisesRegex(TypeError, error_msg):
705 D(42)
706
707 with self.assertRaisesRegex(TypeError, error_msg):
708 D.__new__(D, 42)
709
710 with self.assertRaisesRegex(TypeError, error_msg):
711 object.__new__(D, 42)
712
713 # Class that only overrides __init__
714 class ESC[4;38;5;81mE:
715 def __init__(self, *args, **kwargs):
716 super().__init__(*args, **kwargs)
717
718 error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
719
720 with self.assertRaisesRegex(TypeError, error_msg):
721 E().__init__(42)
722
723 with self.assertRaisesRegex(TypeError, error_msg):
724 object.__init__(E(), 42)
725
726 def testClassWithExtCall(self):
727 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mint):
728 def __init__(*args, **kwargs):
729 pass
730
731 def __new__(cls, name, bases, attrs, **kwargs):
732 return bases, kwargs
733
734 d = {'metaclass': Meta}
735
736 class ESC[4;38;5;81mA(**ESC[4;38;5;149md): pass
737 self.assertEqual(A, ((), {}))
738 class ESC[4;38;5;81mA(0, 1, 2, 3, 4, 5, 6, 7, **ESC[4;38;5;149md): pass
739 self.assertEqual(A, (tuple(range(8)), {}))
740 class ESC[4;38;5;81mA(0, *ESC[4;38;5;149mrange(1, 8), **ESC[4;38;5;149md, foo='bar'): pass
741 self.assertEqual(A, (tuple(range(8)), {'foo': 'bar'}))
742
743
744 if __name__ == '__main__':
745 unittest.main()