1"Test the functionality of Python classes implementing operators."
2
3import unittest
4
5
6testmeths = [
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
65callLst = []
66def trackCall(f):
67    def track(*args, **kwargs):
68        callLst.append((f.__name__, args))
69        return f(*args, **kwargs)
70    return track
71
72statictests = """
73@trackCall
74def __hash__(self, *args):
75    return hash(id(self))
76
77@trackCall
78def __str__(self, *args):
79    return "AllTests"
80
81@trackCall
82def __repr__(self, *args):
83    return "AllTests"
84
85@trackCall
86def __int__(self, *args):
87    return 1
88
89@trackCall
90def __index__(self, *args):
91    return 1
92
93@trackCall
94def __float__(self, *args):
95    return 1.0
96
97@trackCall
98def __eq__(self, *args):
99    return True
100
101@trackCall
102def __ne__(self, *args):
103    return False
104
105@trackCall
106def __lt__(self, *args):
107    return False
108
109@trackCall
110def __le__(self, *args):
111    return True
112
113@trackCall
114def __gt__(self, *args):
115    return False
116
117@trackCall
118def __ge__(self, *args):
119    return True
120"""
121
122# Synthesize all the other AllTests methods from the names in testmeths.
123
124method_template = """\
125@trackCall
126def __%s__(self, *args):
127    pass
128"""
129
130d = {}
131exec(statictests, globals(), d)
132for method in testmeths:
133    exec(method_template % method, globals(), d)
134AllTests = type("AllTests", (object,), d)
135del d, statictests, method, method_template
136
137class ClassTests(unittest.TestCase):
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 Empty: 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 ExtraTests(AllTests):
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 DelTest:
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 BadTypeClass:
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 C0:
483            pass
484
485        hash(C0()) # This should work; the next two should raise TypeError
486
487        class C2:
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 A:
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 A:
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 E:
523            __eq__ = property(booh)
524        E() == E() # In debug mode, caused a C-level assert() to fail
525
526        class I:
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 A:
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 B(A):
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 A:
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 A:
609            pass
610
611        with self.assertRaises(TypeError):
612            type.__setattr__(A, b'x', None)
613
614    def testConstructorErrorMessages(self):
615        # bpo-31506: Improves the error message logic for object_new & object_init
616
617        # Class without any method overrides
618        class C:
619            pass
620
621        error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
622
623        with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
624            C(42)
625
626        with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
627            C.__new__(C, 42)
628
629        with self.assertRaisesRegex(TypeError, error_msg):
630            C().__init__(42)
631
632        with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
633            object.__new__(C, 42)
634
635        with self.assertRaisesRegex(TypeError, error_msg):
636            object.__init__(C(), 42)
637
638        # Class with both `__init__` & `__new__` method overridden
639        class D:
640            def __new__(cls, *args, **kwargs):
641                super().__new__(cls, *args, **kwargs)
642            def __init__(self, *args, **kwargs):
643                super().__init__(*args, **kwargs)
644
645        error_msg =  r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
646
647        with self.assertRaisesRegex(TypeError, error_msg):
648            D(42)
649
650        with self.assertRaisesRegex(TypeError, error_msg):
651            D.__new__(D, 42)
652
653        with self.assertRaisesRegex(TypeError, error_msg):
654            object.__new__(D, 42)
655
656        # Class that only overrides __init__
657        class E:
658            def __init__(self, *args, **kwargs):
659                super().__init__(*args, **kwargs)
660
661        error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
662
663        with self.assertRaisesRegex(TypeError, error_msg):
664            E().__init__(42)
665
666        with self.assertRaisesRegex(TypeError, error_msg):
667            object.__init__(E(), 42)
668
669if __name__ == '__main__':
670    unittest.main()
671