1# Augmented assignment test.
2
3import unittest
4
5
6class AugAssignTest(unittest.TestCase):
7    def testBasic(self):
8        x = 2
9        x += 1
10        x *= 2
11        x **= 2
12        x -= 8
13        x //= 5
14        x %= 3
15        x &= 2
16        x |= 5
17        x ^= 1
18        x /= 2
19        self.assertEqual(x, 3.0)
20
21    def test_with_unpacking(self):
22        self.assertRaises(SyntaxError, compile, "x, b += 3", "<test>", "exec")
23
24    def testInList(self):
25        x = [2]
26        x[0] += 1
27        x[0] *= 2
28        x[0] **= 2
29        x[0] -= 8
30        x[0] //= 5
31        x[0] %= 3
32        x[0] &= 2
33        x[0] |= 5
34        x[0] ^= 1
35        x[0] /= 2
36        self.assertEqual(x[0], 3.0)
37
38    def testInDict(self):
39        x = {0: 2}
40        x[0] += 1
41        x[0] *= 2
42        x[0] **= 2
43        x[0] -= 8
44        x[0] //= 5
45        x[0] %= 3
46        x[0] &= 2
47        x[0] |= 5
48        x[0] ^= 1
49        x[0] /= 2
50        self.assertEqual(x[0], 3.0)
51
52    def testSequences(self):
53        x = [1,2]
54        x += [3,4]
55        x *= 2
56
57        self.assertEqual(x, [1, 2, 3, 4, 1, 2, 3, 4])
58
59        x = [1, 2, 3]
60        y = x
61        x[1:2] *= 2
62        y[1:2] += [1]
63
64        self.assertEqual(x, [1, 2, 1, 2, 3])
65        self.assertTrue(x is y)
66
67    def testCustomMethods1(self):
68
69        class aug_test:
70            def __init__(self, value):
71                self.val = value
72            def __radd__(self, val):
73                return self.val + val
74            def __add__(self, val):
75                return aug_test(self.val + val)
76
77        class aug_test2(aug_test):
78            def __iadd__(self, val):
79                self.val = self.val + val
80                return self
81
82        class aug_test3(aug_test):
83            def __iadd__(self, val):
84                return aug_test3(self.val + val)
85
86        class aug_test4(aug_test3):
87            """Blocks inheritance, and fallback to __add__"""
88            __iadd__ = None
89
90        x = aug_test(1)
91        y = x
92        x += 10
93
94        self.assertIsInstance(x, aug_test)
95        self.assertTrue(y is not x)
96        self.assertEqual(x.val, 11)
97
98        x = aug_test2(2)
99        y = x
100        x += 10
101
102        self.assertTrue(y is x)
103        self.assertEqual(x.val, 12)
104
105        x = aug_test3(3)
106        y = x
107        x += 10
108
109        self.assertIsInstance(x, aug_test3)
110        self.assertTrue(y is not x)
111        self.assertEqual(x.val, 13)
112
113        x = aug_test4(4)
114        with self.assertRaises(TypeError):
115            x += 10
116
117
118    def testCustomMethods2(test_self):
119        output = []
120
121        class testall:
122            def __add__(self, val):
123                output.append("__add__ called")
124            def __radd__(self, val):
125                output.append("__radd__ called")
126            def __iadd__(self, val):
127                output.append("__iadd__ called")
128                return self
129
130            def __sub__(self, val):
131                output.append("__sub__ called")
132            def __rsub__(self, val):
133                output.append("__rsub__ called")
134            def __isub__(self, val):
135                output.append("__isub__ called")
136                return self
137
138            def __mul__(self, val):
139                output.append("__mul__ called")
140            def __rmul__(self, val):
141                output.append("__rmul__ called")
142            def __imul__(self, val):
143                output.append("__imul__ called")
144                return self
145
146            def __matmul__(self, val):
147                output.append("__matmul__ called")
148            def __rmatmul__(self, val):
149                output.append("__rmatmul__ called")
150            def __imatmul__(self, val):
151                output.append("__imatmul__ called")
152                return self
153
154            def __floordiv__(self, val):
155                output.append("__floordiv__ called")
156                return self
157            def __ifloordiv__(self, val):
158                output.append("__ifloordiv__ called")
159                return self
160            def __rfloordiv__(self, val):
161                output.append("__rfloordiv__ called")
162                return self
163
164            def __truediv__(self, val):
165                output.append("__truediv__ called")
166                return self
167            def __rtruediv__(self, val):
168                output.append("__rtruediv__ called")
169                return self
170            def __itruediv__(self, val):
171                output.append("__itruediv__ called")
172                return self
173
174            def __mod__(self, val):
175                output.append("__mod__ called")
176            def __rmod__(self, val):
177                output.append("__rmod__ called")
178            def __imod__(self, val):
179                output.append("__imod__ called")
180                return self
181
182            def __pow__(self, val):
183                output.append("__pow__ called")
184            def __rpow__(self, val):
185                output.append("__rpow__ called")
186            def __ipow__(self, val):
187                output.append("__ipow__ called")
188                return self
189
190            def __or__(self, val):
191                output.append("__or__ called")
192            def __ror__(self, val):
193                output.append("__ror__ called")
194            def __ior__(self, val):
195                output.append("__ior__ called")
196                return self
197
198            def __and__(self, val):
199                output.append("__and__ called")
200            def __rand__(self, val):
201                output.append("__rand__ called")
202            def __iand__(self, val):
203                output.append("__iand__ called")
204                return self
205
206            def __xor__(self, val):
207                output.append("__xor__ called")
208            def __rxor__(self, val):
209                output.append("__rxor__ called")
210            def __ixor__(self, val):
211                output.append("__ixor__ called")
212                return self
213
214            def __rshift__(self, val):
215                output.append("__rshift__ called")
216            def __rrshift__(self, val):
217                output.append("__rrshift__ called")
218            def __irshift__(self, val):
219                output.append("__irshift__ called")
220                return self
221
222            def __lshift__(self, val):
223                output.append("__lshift__ called")
224            def __rlshift__(self, val):
225                output.append("__rlshift__ called")
226            def __ilshift__(self, val):
227                output.append("__ilshift__ called")
228                return self
229
230        x = testall()
231        x + 1
232        1 + x
233        x += 1
234
235        x - 1
236        1 - x
237        x -= 1
238
239        x * 1
240        1 * x
241        x *= 1
242
243        x @ 1
244        1 @ x
245        x @= 1
246
247        x / 1
248        1 / x
249        x /= 1
250
251        x // 1
252        1 // x
253        x //= 1
254
255        x % 1
256        1 % x
257        x %= 1
258
259        x ** 1
260        1 ** x
261        x **= 1
262
263        x | 1
264        1 | x
265        x |= 1
266
267        x & 1
268        1 & x
269        x &= 1
270
271        x ^ 1
272        1 ^ x
273        x ^= 1
274
275        x >> 1
276        1 >> x
277        x >>= 1
278
279        x << 1
280        1 << x
281        x <<= 1
282
283        test_self.assertEqual(output, '''\
284__add__ called
285__radd__ called
286__iadd__ called
287__sub__ called
288__rsub__ called
289__isub__ called
290__mul__ called
291__rmul__ called
292__imul__ called
293__matmul__ called
294__rmatmul__ called
295__imatmul__ called
296__truediv__ called
297__rtruediv__ called
298__itruediv__ called
299__floordiv__ called
300__rfloordiv__ called
301__ifloordiv__ called
302__mod__ called
303__rmod__ called
304__imod__ called
305__pow__ called
306__rpow__ called
307__ipow__ called
308__or__ called
309__ror__ called
310__ior__ called
311__and__ called
312__rand__ called
313__iand__ called
314__xor__ called
315__rxor__ called
316__ixor__ called
317__rshift__ called
318__rrshift__ called
319__irshift__ called
320__lshift__ called
321__rlshift__ called
322__ilshift__ called
323'''.splitlines())
324
325if __name__ == '__main__':
326    unittest.main()
327