• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Python test set -- part 6, built-in types
2
3from test.support import run_with_locale, cpython_only
4import collections.abc
5from collections import namedtuple
6import copy
7import gc
8import inspect
9import pickle
10import locale
11import sys
12import types
13import unittest.mock
14import weakref
15import typing
16
17
18T = typing.TypeVar("T")
19
20class Example:
21    pass
22
23class Forward: ...
24
25def clear_typing_caches():
26    for f in typing._cleanups:
27        f()
28
29
30class TypesTests(unittest.TestCase):
31
32    def test_truth_values(self):
33        if None: self.fail('None is true instead of false')
34        if 0: self.fail('0 is true instead of false')
35        if 0.0: self.fail('0.0 is true instead of false')
36        if '': self.fail('\'\' is true instead of false')
37        if not 1: self.fail('1 is false instead of true')
38        if not 1.0: self.fail('1.0 is false instead of true')
39        if not 'x': self.fail('\'x\' is false instead of true')
40        if not {'x': 1}: self.fail('{\'x\': 1} is false instead of true')
41        def f(): pass
42        class C: pass
43        x = C()
44        if not f: self.fail('f is false instead of true')
45        if not C: self.fail('C is false instead of true')
46        if not sys: self.fail('sys is false instead of true')
47        if not x: self.fail('x is false instead of true')
48
49    def test_boolean_ops(self):
50        if 0 or 0: self.fail('0 or 0 is true instead of false')
51        if 1 and 1: pass
52        else: self.fail('1 and 1 is false instead of true')
53        if not 1: self.fail('not 1 is true instead of false')
54
55    def test_comparisons(self):
56        if 0 < 1 <= 1 == 1 >= 1 > 0 != 1: pass
57        else: self.fail('int comparisons failed')
58        if 0.0 < 1.0 <= 1.0 == 1.0 >= 1.0 > 0.0 != 1.0: pass
59        else: self.fail('float comparisons failed')
60        if '' < 'a' <= 'a' == 'a' < 'abc' < 'abd' < 'b': pass
61        else: self.fail('string comparisons failed')
62        if None is None: pass
63        else: self.fail('identity test failed')
64
65    def test_float_constructor(self):
66        self.assertRaises(ValueError, float, '')
67        self.assertRaises(ValueError, float, '5\0')
68        self.assertRaises(ValueError, float, '5_5\0')
69
70    def test_zero_division(self):
71        try: 5.0 / 0.0
72        except ZeroDivisionError: pass
73        else: self.fail("5.0 / 0.0 didn't raise ZeroDivisionError")
74
75        try: 5.0 // 0.0
76        except ZeroDivisionError: pass
77        else: self.fail("5.0 // 0.0 didn't raise ZeroDivisionError")
78
79        try: 5.0 % 0.0
80        except ZeroDivisionError: pass
81        else: self.fail("5.0 % 0.0 didn't raise ZeroDivisionError")
82
83        try: 5 / 0
84        except ZeroDivisionError: pass
85        else: self.fail("5 / 0 didn't raise ZeroDivisionError")
86
87        try: 5 // 0
88        except ZeroDivisionError: pass
89        else: self.fail("5 // 0 didn't raise ZeroDivisionError")
90
91        try: 5 % 0
92        except ZeroDivisionError: pass
93        else: self.fail("5 % 0 didn't raise ZeroDivisionError")
94
95    def test_numeric_types(self):
96        if 0 != 0.0 or 1 != 1.0 or -1 != -1.0:
97            self.fail('int/float value not equal')
98        # calling built-in types without argument must return 0
99        if int() != 0: self.fail('int() does not return 0')
100        if float() != 0.0: self.fail('float() does not return 0.0')
101        if int(1.9) == 1 == int(1.1) and int(-1.1) == -1 == int(-1.9): pass
102        else: self.fail('int() does not round properly')
103        if float(1) == 1.0 and float(-1) == -1.0 and float(0) == 0.0: pass
104        else: self.fail('float() does not work properly')
105
106    def test_float_to_string(self):
107        def test(f, result):
108            self.assertEqual(f.__format__('e'), result)
109            self.assertEqual('%e' % f, result)
110
111        # test all 2 digit exponents, both with __format__ and with
112        #  '%' formatting
113        for i in range(-99, 100):
114            test(float('1.5e'+str(i)), '1.500000e{0:+03d}'.format(i))
115
116        # test some 3 digit exponents
117        self.assertEqual(1.5e100.__format__('e'), '1.500000e+100')
118        self.assertEqual('%e' % 1.5e100, '1.500000e+100')
119
120        self.assertEqual(1.5e101.__format__('e'), '1.500000e+101')
121        self.assertEqual('%e' % 1.5e101, '1.500000e+101')
122
123        self.assertEqual(1.5e-100.__format__('e'), '1.500000e-100')
124        self.assertEqual('%e' % 1.5e-100, '1.500000e-100')
125
126        self.assertEqual(1.5e-101.__format__('e'), '1.500000e-101')
127        self.assertEqual('%e' % 1.5e-101, '1.500000e-101')
128
129        self.assertEqual('%g' % 1.0, '1')
130        self.assertEqual('%#g' % 1.0, '1.00000')
131
132    def test_normal_integers(self):
133        # Ensure the first 256 integers are shared
134        a = 256
135        b = 128*2
136        if a is not b: self.fail('256 is not shared')
137        if 12 + 24 != 36: self.fail('int op')
138        if 12 + (-24) != -12: self.fail('int op')
139        if (-12) + 24 != 12: self.fail('int op')
140        if (-12) + (-24) != -36: self.fail('int op')
141        if not 12 < 24: self.fail('int op')
142        if not -24 < -12: self.fail('int op')
143        # Test for a particular bug in integer multiply
144        xsize, ysize, zsize = 238, 356, 4
145        if not (xsize*ysize*zsize == zsize*xsize*ysize == 338912):
146            self.fail('int mul commutativity')
147        # And another.
148        m = -sys.maxsize - 1
149        for divisor in 1, 2, 4, 8, 16, 32:
150            j = m // divisor
151            prod = divisor * j
152            if prod != m:
153                self.fail("%r * %r == %r != %r" % (divisor, j, prod, m))
154            if type(prod) is not int:
155                self.fail("expected type(prod) to be int, not %r" %
156                                   type(prod))
157        # Check for unified integral type
158        for divisor in 1, 2, 4, 8, 16, 32:
159            j = m // divisor - 1
160            prod = divisor * j
161            if type(prod) is not int:
162                self.fail("expected type(%r) to be int, not %r" %
163                                   (prod, type(prod)))
164        # Check for unified integral type
165        m = sys.maxsize
166        for divisor in 1, 2, 4, 8, 16, 32:
167            j = m // divisor + 1
168            prod = divisor * j
169            if type(prod) is not int:
170                self.fail("expected type(%r) to be int, not %r" %
171                                   (prod, type(prod)))
172
173        x = sys.maxsize
174        self.assertIsInstance(x + 1, int,
175                              "(sys.maxsize + 1) should have returned int")
176        self.assertIsInstance(-x - 1, int,
177                              "(-sys.maxsize - 1) should have returned int")
178        self.assertIsInstance(-x - 2, int,
179                              "(-sys.maxsize - 2) should have returned int")
180
181        try: 5 << -5
182        except ValueError: pass
183        else: self.fail('int negative shift <<')
184
185        try: 5 >> -5
186        except ValueError: pass
187        else: self.fail('int negative shift >>')
188
189    def test_floats(self):
190        if 12.0 + 24.0 != 36.0: self.fail('float op')
191        if 12.0 + (-24.0) != -12.0: self.fail('float op')
192        if (-12.0) + 24.0 != 12.0: self.fail('float op')
193        if (-12.0) + (-24.0) != -36.0: self.fail('float op')
194        if not 12.0 < 24.0: self.fail('float op')
195        if not -24.0 < -12.0: self.fail('float op')
196
197    def test_strings(self):
198        if len('') != 0: self.fail('len(\'\')')
199        if len('a') != 1: self.fail('len(\'a\')')
200        if len('abcdef') != 6: self.fail('len(\'abcdef\')')
201        if 'xyz' + 'abcde' != 'xyzabcde': self.fail('string concatenation')
202        if 'xyz'*3 != 'xyzxyzxyz': self.fail('string repetition *3')
203        if 0*'abcde' != '': self.fail('string repetition 0*')
204        if min('abc') != 'a' or max('abc') != 'c': self.fail('min/max string')
205        if 'a' in 'abc' and 'b' in 'abc' and 'c' in 'abc' and 'd' not in 'abc': pass
206        else: self.fail('in/not in string')
207        x = 'x'*103
208        if '%s!'%x != x+'!': self.fail('nasty string formatting bug')
209
210        #extended slices for strings
211        a = '0123456789'
212        self.assertEqual(a[::], a)
213        self.assertEqual(a[::2], '02468')
214        self.assertEqual(a[1::2], '13579')
215        self.assertEqual(a[::-1],'9876543210')
216        self.assertEqual(a[::-2], '97531')
217        self.assertEqual(a[3::-2], '31')
218        self.assertEqual(a[-100:100:], a)
219        self.assertEqual(a[100:-100:-1], a[::-1])
220        self.assertEqual(a[-100:100:2], '02468')
221
222    def test_type_function(self):
223        self.assertRaises(TypeError, type, 1, 2)
224        self.assertRaises(TypeError, type, 1, 2, 3, 4)
225
226    def test_int__format__(self):
227        def test(i, format_spec, result):
228            # just make sure we have the unified type for integers
229            assert type(i) == int
230            assert type(format_spec) == str
231            self.assertEqual(i.__format__(format_spec), result)
232
233        test(123456789, 'd', '123456789')
234        test(123456789, 'd', '123456789')
235
236        test(1, 'c', '\01')
237
238        # sign and aligning are interdependent
239        test(1, "-", '1')
240        test(-1, "-", '-1')
241        test(1, "-3", '  1')
242        test(-1, "-3", ' -1')
243        test(1, "+3", ' +1')
244        test(-1, "+3", ' -1')
245        test(1, " 3", '  1')
246        test(-1, " 3", ' -1')
247        test(1, " ", ' 1')
248        test(-1, " ", '-1')
249
250        # hex
251        test(3, "x", "3")
252        test(3, "X", "3")
253        test(1234, "x", "4d2")
254        test(-1234, "x", "-4d2")
255        test(1234, "8x", "     4d2")
256        test(-1234, "8x", "    -4d2")
257        test(1234, "x", "4d2")
258        test(-1234, "x", "-4d2")
259        test(-3, "x", "-3")
260        test(-3, "X", "-3")
261        test(int('be', 16), "x", "be")
262        test(int('be', 16), "X", "BE")
263        test(-int('be', 16), "x", "-be")
264        test(-int('be', 16), "X", "-BE")
265
266        # octal
267        test(3, "o", "3")
268        test(-3, "o", "-3")
269        test(65, "o", "101")
270        test(-65, "o", "-101")
271        test(1234, "o", "2322")
272        test(-1234, "o", "-2322")
273        test(1234, "-o", "2322")
274        test(-1234, "-o", "-2322")
275        test(1234, " o", " 2322")
276        test(-1234, " o", "-2322")
277        test(1234, "+o", "+2322")
278        test(-1234, "+o", "-2322")
279
280        # binary
281        test(3, "b", "11")
282        test(-3, "b", "-11")
283        test(1234, "b", "10011010010")
284        test(-1234, "b", "-10011010010")
285        test(1234, "-b", "10011010010")
286        test(-1234, "-b", "-10011010010")
287        test(1234, " b", " 10011010010")
288        test(-1234, " b", "-10011010010")
289        test(1234, "+b", "+10011010010")
290        test(-1234, "+b", "-10011010010")
291
292        # alternate (#) formatting
293        test(0, "#b", '0b0')
294        test(0, "-#b", '0b0')
295        test(1, "-#b", '0b1')
296        test(-1, "-#b", '-0b1')
297        test(-1, "-#5b", ' -0b1')
298        test(1, "+#5b", ' +0b1')
299        test(100, "+#b", '+0b1100100')
300        test(100, "#012b", '0b0001100100')
301        test(-100, "#012b", '-0b001100100')
302
303        test(0, "#o", '0o0')
304        test(0, "-#o", '0o0')
305        test(1, "-#o", '0o1')
306        test(-1, "-#o", '-0o1')
307        test(-1, "-#5o", ' -0o1')
308        test(1, "+#5o", ' +0o1')
309        test(100, "+#o", '+0o144')
310        test(100, "#012o", '0o0000000144')
311        test(-100, "#012o", '-0o000000144')
312
313        test(0, "#x", '0x0')
314        test(0, "-#x", '0x0')
315        test(1, "-#x", '0x1')
316        test(-1, "-#x", '-0x1')
317        test(-1, "-#5x", ' -0x1')
318        test(1, "+#5x", ' +0x1')
319        test(100, "+#x", '+0x64')
320        test(100, "#012x", '0x0000000064')
321        test(-100, "#012x", '-0x000000064')
322        test(123456, "#012x", '0x000001e240')
323        test(-123456, "#012x", '-0x00001e240')
324
325        test(0, "#X", '0X0')
326        test(0, "-#X", '0X0')
327        test(1, "-#X", '0X1')
328        test(-1, "-#X", '-0X1')
329        test(-1, "-#5X", ' -0X1')
330        test(1, "+#5X", ' +0X1')
331        test(100, "+#X", '+0X64')
332        test(100, "#012X", '0X0000000064')
333        test(-100, "#012X", '-0X000000064')
334        test(123456, "#012X", '0X000001E240')
335        test(-123456, "#012X", '-0X00001E240')
336
337        test(123, ',', '123')
338        test(-123, ',', '-123')
339        test(1234, ',', '1,234')
340        test(-1234, ',', '-1,234')
341        test(123456, ',', '123,456')
342        test(-123456, ',', '-123,456')
343        test(1234567, ',', '1,234,567')
344        test(-1234567, ',', '-1,234,567')
345
346        # issue 5782, commas with no specifier type
347        test(1234, '010,', '00,001,234')
348
349        # Unified type for integers
350        test(10**100, 'd', '1' + '0' * 100)
351        test(10**100+100, 'd', '1' + '0' * 97 + '100')
352
353        # make sure these are errors
354
355        # precision disallowed
356        self.assertRaises(ValueError, 3 .__format__, "1.3")
357        # sign not allowed with 'c'
358        self.assertRaises(ValueError, 3 .__format__, "+c")
359        # format spec must be string
360        self.assertRaises(TypeError, 3 .__format__, None)
361        self.assertRaises(TypeError, 3 .__format__, 0)
362        # can't have ',' with 'n'
363        self.assertRaises(ValueError, 3 .__format__, ",n")
364        # can't have ',' with 'c'
365        self.assertRaises(ValueError, 3 .__format__, ",c")
366        # can't have '#' with 'c'
367        self.assertRaises(ValueError, 3 .__format__, "#c")
368
369        # ensure that only int and float type specifiers work
370        for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
371                            [chr(x) for x in range(ord('A'), ord('Z')+1)]):
372            if not format_spec in 'bcdoxXeEfFgGn%':
373                self.assertRaises(ValueError, 0 .__format__, format_spec)
374                self.assertRaises(ValueError, 1 .__format__, format_spec)
375                self.assertRaises(ValueError, (-1) .__format__, format_spec)
376
377        # ensure that float type specifiers work; format converts
378        #  the int to a float
379        for format_spec in 'eEfFgG%':
380            for value in [0, 1, -1, 100, -100, 1234567890, -1234567890]:
381                self.assertEqual(value.__format__(format_spec),
382                                 float(value).__format__(format_spec))
383
384        # Issue 6902
385        test(123456, "0<20", '12345600000000000000')
386        test(123456, "1<20", '12345611111111111111')
387        test(123456, "*<20", '123456**************')
388        test(123456, "0>20", '00000000000000123456')
389        test(123456, "1>20", '11111111111111123456')
390        test(123456, "*>20", '**************123456')
391        test(123456, "0=20", '00000000000000123456')
392        test(123456, "1=20", '11111111111111123456')
393        test(123456, "*=20", '**************123456')
394
395    @run_with_locale('LC_NUMERIC', 'en_US.UTF8')
396    def test_float__format__locale(self):
397        # test locale support for __format__ code 'n'
398
399        for i in range(-10, 10):
400            x = 1234567890.0 * (10.0 ** i)
401            self.assertEqual(locale.format_string('%g', x, grouping=True), format(x, 'n'))
402            self.assertEqual(locale.format_string('%.10g', x, grouping=True), format(x, '.10n'))
403
404    @run_with_locale('LC_NUMERIC', 'en_US.UTF8')
405    def test_int__format__locale(self):
406        # test locale support for __format__ code 'n' for integers
407
408        x = 123456789012345678901234567890
409        for i in range(0, 30):
410            self.assertEqual(locale.format_string('%d', x, grouping=True), format(x, 'n'))
411
412            # move to the next integer to test
413            x = x // 10
414
415        rfmt = ">20n"
416        lfmt = "<20n"
417        cfmt = "^20n"
418        for x in (1234, 12345, 123456, 1234567, 12345678, 123456789, 1234567890, 12345678900):
419            self.assertEqual(len(format(0, rfmt)), len(format(x, rfmt)))
420            self.assertEqual(len(format(0, lfmt)), len(format(x, lfmt)))
421            self.assertEqual(len(format(0, cfmt)), len(format(x, cfmt)))
422
423    def test_float__format__(self):
424        def test(f, format_spec, result):
425            self.assertEqual(f.__format__(format_spec), result)
426            self.assertEqual(format(f, format_spec), result)
427
428        test(0.0, 'f', '0.000000')
429
430        # the default is 'g', except for empty format spec
431        test(0.0, '', '0.0')
432        test(0.01, '', '0.01')
433        test(0.01, 'g', '0.01')
434
435        # test for issue 3411
436        test(1.23, '1', '1.23')
437        test(-1.23, '1', '-1.23')
438        test(1.23, '1g', '1.23')
439        test(-1.23, '1g', '-1.23')
440
441        test( 1.0, ' g', ' 1')
442        test(-1.0, ' g', '-1')
443        test( 1.0, '+g', '+1')
444        test(-1.0, '+g', '-1')
445        test(1.1234e200, 'g', '1.1234e+200')
446        test(1.1234e200, 'G', '1.1234E+200')
447
448
449        test(1.0, 'f', '1.000000')
450
451        test(-1.0, 'f', '-1.000000')
452
453        test( 1.0, ' f', ' 1.000000')
454        test(-1.0, ' f', '-1.000000')
455        test( 1.0, '+f', '+1.000000')
456        test(-1.0, '+f', '-1.000000')
457
458        # Python versions <= 3.0 switched from 'f' to 'g' formatting for
459        # values larger than 1e50.  No longer.
460        f = 1.1234e90
461        for fmt in 'f', 'F':
462            # don't do a direct equality check, since on some
463            # platforms only the first few digits of dtoa
464            # will be reliable
465            result = f.__format__(fmt)
466            self.assertEqual(len(result), 98)
467            self.assertEqual(result[-7], '.')
468            self.assertIn(result[:12], ('112340000000', '112339999999'))
469        f = 1.1234e200
470        for fmt in 'f', 'F':
471            result = f.__format__(fmt)
472            self.assertEqual(len(result), 208)
473            self.assertEqual(result[-7], '.')
474            self.assertIn(result[:12], ('112340000000', '112339999999'))
475
476
477        test( 1.0, 'e', '1.000000e+00')
478        test(-1.0, 'e', '-1.000000e+00')
479        test( 1.0, 'E', '1.000000E+00')
480        test(-1.0, 'E', '-1.000000E+00')
481        test(1.1234e20, 'e', '1.123400e+20')
482        test(1.1234e20, 'E', '1.123400E+20')
483
484        # No format code means use g, but must have a decimal
485        # and a number after the decimal.  This is tricky, because
486        # a totally empty format specifier means something else.
487        # So, just use a sign flag
488        test(1e200, '+g', '+1e+200')
489        test(1e200, '+', '+1e+200')
490
491        test(1.1e200, '+g', '+1.1e+200')
492        test(1.1e200, '+', '+1.1e+200')
493
494        # 0 padding
495        test(1234., '010f', '1234.000000')
496        test(1234., '011f', '1234.000000')
497        test(1234., '012f', '01234.000000')
498        test(-1234., '011f', '-1234.000000')
499        test(-1234., '012f', '-1234.000000')
500        test(-1234., '013f', '-01234.000000')
501        test(-1234.12341234, '013f', '-01234.123412')
502        test(-123456.12341234, '011.2f', '-0123456.12')
503
504        # issue 5782, commas with no specifier type
505        test(1.2, '010,.2', '0,000,001.2')
506
507        # 0 padding with commas
508        test(1234., '011,f', '1,234.000000')
509        test(1234., '012,f', '1,234.000000')
510        test(1234., '013,f', '01,234.000000')
511        test(-1234., '012,f', '-1,234.000000')
512        test(-1234., '013,f', '-1,234.000000')
513        test(-1234., '014,f', '-01,234.000000')
514        test(-12345., '015,f', '-012,345.000000')
515        test(-123456., '016,f', '-0,123,456.000000')
516        test(-123456., '017,f', '-0,123,456.000000')
517        test(-123456.12341234, '017,f', '-0,123,456.123412')
518        test(-123456.12341234, '013,.2f', '-0,123,456.12')
519
520        # % formatting
521        test(-1.0, '%', '-100.000000%')
522
523        # format spec must be string
524        self.assertRaises(TypeError, 3.0.__format__, None)
525        self.assertRaises(TypeError, 3.0.__format__, 0)
526
527        # other format specifiers shouldn't work on floats,
528        #  in particular int specifiers
529        for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
530                            [chr(x) for x in range(ord('A'), ord('Z')+1)]):
531            if not format_spec in 'eEfFgGn%':
532                self.assertRaises(ValueError, format, 0.0, format_spec)
533                self.assertRaises(ValueError, format, 1.0, format_spec)
534                self.assertRaises(ValueError, format, -1.0, format_spec)
535                self.assertRaises(ValueError, format, 1e100, format_spec)
536                self.assertRaises(ValueError, format, -1e100, format_spec)
537                self.assertRaises(ValueError, format, 1e-100, format_spec)
538                self.assertRaises(ValueError, format, -1e-100, format_spec)
539
540        # Alternate float formatting
541        test(1.0, '.0e', '1e+00')
542        test(1.0, '#.0e', '1.e+00')
543        test(1.0, '.0f', '1')
544        test(1.0, '#.0f', '1.')
545        test(1.1, 'g', '1.1')
546        test(1.1, '#g', '1.10000')
547        test(1.0, '.0%', '100%')
548        test(1.0, '#.0%', '100.%')
549
550        # Issue 7094: Alternate formatting (specified by #)
551        test(1.0, '0e',  '1.000000e+00')
552        test(1.0, '#0e', '1.000000e+00')
553        test(1.0, '0f',  '1.000000' )
554        test(1.0, '#0f', '1.000000')
555        test(1.0, '.1e',  '1.0e+00')
556        test(1.0, '#.1e', '1.0e+00')
557        test(1.0, '.1f',  '1.0')
558        test(1.0, '#.1f', '1.0')
559        test(1.0, '.1%',  '100.0%')
560        test(1.0, '#.1%', '100.0%')
561
562        # Issue 6902
563        test(12345.6, "0<20", '12345.60000000000000')
564        test(12345.6, "1<20", '12345.61111111111111')
565        test(12345.6, "*<20", '12345.6*************')
566        test(12345.6, "0>20", '000000000000012345.6')
567        test(12345.6, "1>20", '111111111111112345.6')
568        test(12345.6, "*>20", '*************12345.6')
569        test(12345.6, "0=20", '000000000000012345.6')
570        test(12345.6, "1=20", '111111111111112345.6')
571        test(12345.6, "*=20", '*************12345.6')
572
573    def test_format_spec_errors(self):
574        # int, float, and string all share the same format spec
575        # mini-language parser.
576
577        # Check that we can't ask for too many digits. This is
578        # probably a CPython specific test. It tries to put the width
579        # into a C long.
580        self.assertRaises(ValueError, format, 0, '1'*10000 + 'd')
581
582        # Similar with the precision.
583        self.assertRaises(ValueError, format, 0, '.' + '1'*10000 + 'd')
584
585        # And may as well test both.
586        self.assertRaises(ValueError, format, 0, '1'*1000 + '.' + '1'*10000 + 'd')
587
588        # Make sure commas aren't allowed with various type codes
589        for code in 'xXobns':
590            self.assertRaises(ValueError, format, 0, ',' + code)
591
592    def test_internal_sizes(self):
593        self.assertGreater(object.__basicsize__, 0)
594        self.assertGreater(tuple.__itemsize__, 0)
595
596    def test_slot_wrapper_types(self):
597        self.assertIsInstance(object.__init__, types.WrapperDescriptorType)
598        self.assertIsInstance(object.__str__, types.WrapperDescriptorType)
599        self.assertIsInstance(object.__lt__, types.WrapperDescriptorType)
600        self.assertIsInstance(int.__lt__, types.WrapperDescriptorType)
601
602    def test_method_wrapper_types(self):
603        self.assertIsInstance(object().__init__, types.MethodWrapperType)
604        self.assertIsInstance(object().__str__, types.MethodWrapperType)
605        self.assertIsInstance(object().__lt__, types.MethodWrapperType)
606        self.assertIsInstance((42).__lt__, types.MethodWrapperType)
607
608    def test_method_descriptor_types(self):
609        self.assertIsInstance(str.join, types.MethodDescriptorType)
610        self.assertIsInstance(list.append, types.MethodDescriptorType)
611        self.assertIsInstance(''.join, types.BuiltinMethodType)
612        self.assertIsInstance([].append, types.BuiltinMethodType)
613
614        self.assertIsInstance(int.__dict__['from_bytes'], types.ClassMethodDescriptorType)
615        self.assertIsInstance(int.from_bytes, types.BuiltinMethodType)
616        self.assertIsInstance(int.__new__, types.BuiltinMethodType)
617
618    def test_ellipsis_type(self):
619        self.assertIsInstance(Ellipsis, types.EllipsisType)
620
621    def test_notimplemented_type(self):
622        self.assertIsInstance(NotImplemented, types.NotImplementedType)
623
624    def test_none_type(self):
625        self.assertIsInstance(None, types.NoneType)
626
627
628class UnionTests(unittest.TestCase):
629
630    def test_or_types_operator(self):
631        self.assertEqual(int | str, typing.Union[int, str])
632        self.assertNotEqual(int | list, typing.Union[int, str])
633        self.assertEqual(str | int, typing.Union[int, str])
634        self.assertEqual(int | None, typing.Union[int, None])
635        self.assertEqual(None | int, typing.Union[int, None])
636        self.assertEqual(int | type(None), int | None)
637        self.assertEqual(type(None) | int, None | int)
638        self.assertEqual(int | str | list, typing.Union[int, str, list])
639        self.assertEqual(int | (str | list), typing.Union[int, str, list])
640        self.assertEqual(str | (int | list), typing.Union[int, str, list])
641        self.assertEqual(typing.List | typing.Tuple, typing.Union[typing.List, typing.Tuple])
642        self.assertEqual(typing.List[int] | typing.Tuple[int], typing.Union[typing.List[int], typing.Tuple[int]])
643        self.assertEqual(typing.List[int] | None, typing.Union[typing.List[int], None])
644        self.assertEqual(None | typing.List[int], typing.Union[None, typing.List[int]])
645        self.assertEqual(str | float | int | complex | int, (int | str) | (float | complex))
646        self.assertEqual(typing.Union[str, int, typing.List[int]], str | int | typing.List[int])
647        self.assertIs(int | int, int)
648        self.assertEqual(
649            BaseException |
650            bool |
651            bytes |
652            complex |
653            float |
654            int |
655            list |
656            map |
657            set,
658            typing.Union[
659                BaseException,
660                bool,
661                bytes,
662                complex,
663                float,
664                int,
665                list,
666                map,
667                set,
668            ])
669        with self.assertRaises(TypeError):
670            int | 3
671        with self.assertRaises(TypeError):
672            3 | int
673        with self.assertRaises(TypeError):
674            Example() | int
675        x = int | str
676        self.assertEqual(x, int | str)
677        self.assertEqual(x, str | int)
678        self.assertNotEqual(x, {})  # should not raise exception
679        with self.assertRaises(TypeError):
680            x < x
681        with self.assertRaises(TypeError):
682            x <= x
683        y = typing.Union[str, int]
684        with self.assertRaises(TypeError):
685            x < y
686        y = int | bool
687        with self.assertRaises(TypeError):
688            x < y
689        # Check that we don't crash if typing.Union does not have a tuple in __args__
690        y = typing.Union[str, int]
691        y.__args__ = [str, int]
692        self.assertEqual(x, y)
693
694    def test_hash(self):
695        self.assertEqual(hash(int | str), hash(str | int))
696        self.assertEqual(hash(int | str), hash(typing.Union[int, str]))
697
698    def test_instancecheck(self):
699        x = int | str
700        self.assertIsInstance(1, x)
701        self.assertIsInstance(True, x)
702        self.assertIsInstance('a', x)
703        self.assertNotIsInstance(None, x)
704        self.assertTrue(issubclass(int, x))
705        self.assertTrue(issubclass(bool, x))
706        self.assertTrue(issubclass(str, x))
707        self.assertFalse(issubclass(type(None), x))
708        x = int | None
709        self.assertIsInstance(None, x)
710        self.assertTrue(issubclass(type(None), x))
711        x = int | collections.abc.Mapping
712        self.assertIsInstance({}, x)
713        self.assertTrue(issubclass(dict, x))
714
715    def test_bad_instancecheck(self):
716        class BadMeta(type):
717            def __instancecheck__(cls, inst):
718                1/0
719        x = int | BadMeta('A', (), {})
720        self.assertTrue(isinstance(1, x))
721        self.assertRaises(ZeroDivisionError, isinstance, [], x)
722
723    def test_bad_subclasscheck(self):
724        class BadMeta(type):
725            def __subclasscheck__(cls, sub):
726                1/0
727        x = int | BadMeta('A', (), {})
728        self.assertTrue(issubclass(int, x))
729        self.assertRaises(ZeroDivisionError, issubclass, list, x)
730
731    def test_or_type_operator_with_TypeVar(self):
732        TV = typing.TypeVar('T')
733        assert TV | str == typing.Union[TV, str]
734        assert str | TV == typing.Union[str, TV]
735        self.assertIs((int | TV)[int], int)
736        self.assertIs((TV | int)[int], int)
737
738    def test_union_args(self):
739        def check(arg, expected):
740            clear_typing_caches()
741            self.assertEqual(arg.__args__, expected)
742
743        check(int | str, (int, str))
744        check((int | str) | list, (int, str, list))
745        check(int | (str | list), (int, str, list))
746        check((int | str) | int, (int, str))
747        check(int | (str | int), (int, str))
748        check((int | str) | (str | int), (int, str))
749        check(typing.Union[int, str] | list, (int, str, list))
750        check(int | typing.Union[str, list], (int, str, list))
751        check((int | str) | (list | int), (int, str, list))
752        check((int | str) | typing.Union[list, int], (int, str, list))
753        check(typing.Union[int, str] | (list | int), (int, str, list))
754        check((str | int) | (int | list), (str, int, list))
755        check((str | int) | typing.Union[int, list], (str, int, list))
756        check(typing.Union[str, int] | (int | list), (str, int, list))
757        check(int | type(None), (int, type(None)))
758        check(type(None) | int, (type(None), int))
759
760        args = (int, list[int], typing.List[int],
761                typing.Tuple[int, int], typing.Callable[[int], int],
762                typing.Hashable, typing.TypeVar('T'))
763        for x in args:
764            with self.subTest(x):
765                check(x | None, (x, type(None)))
766                check(None | x, (type(None), x))
767
768    def test_union_parameter_chaining(self):
769        T = typing.TypeVar("T")
770        S = typing.TypeVar("S")
771
772        self.assertEqual((float | list[T])[int], float | list[int])
773        self.assertEqual(list[int | list[T]].__parameters__, (T,))
774        self.assertEqual(list[int | list[T]][str], list[int | list[str]])
775        self.assertEqual((list[T] | list[S]).__parameters__, (T, S))
776        self.assertEqual((list[T] | list[S])[int, T], list[int] | list[T])
777        self.assertEqual((list[T] | list[S])[int, int], list[int])
778
779    def test_union_parameter_substitution(self):
780        def eq(actual, expected, typed=True):
781            self.assertEqual(actual, expected)
782            if typed:
783                self.assertIs(type(actual), type(expected))
784
785        T = typing.TypeVar('T')
786        S = typing.TypeVar('S')
787        NT = typing.NewType('NT', str)
788        x = int | T | bytes
789
790        eq(x[str], int | str | bytes, typed=False)
791        eq(x[list[int]], int | list[int] | bytes, typed=False)
792        eq(x[typing.List], int | typing.List | bytes)
793        eq(x[typing.List[int]], int | typing.List[int] | bytes)
794        eq(x[typing.Hashable], int | typing.Hashable | bytes)
795        eq(x[collections.abc.Hashable],
796           int | collections.abc.Hashable | bytes, typed=False)
797        eq(x[typing.Callable[[int], str]],
798           int | typing.Callable[[int], str] | bytes)
799        eq(x[collections.abc.Callable[[int], str]],
800           int | collections.abc.Callable[[int], str] | bytes, typed=False)
801        eq(x[typing.Tuple[int, str]], int | typing.Tuple[int, str] | bytes)
802        eq(x[typing.Literal['none']], int | typing.Literal['none'] | bytes)
803        eq(x[str | list], int | str | list | bytes, typed=False)
804        eq(x[typing.Union[str, list]], typing.Union[int, str, list, bytes])
805        eq(x[str | int], int | str | bytes, typed=False)
806        eq(x[typing.Union[str, int]], typing.Union[int, str, bytes])
807        eq(x[NT], int | NT | bytes)
808        eq(x[S], int | S | bytes)
809
810    def test_union_pickle(self):
811        orig = list[T] | int
812        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
813            s = pickle.dumps(orig, proto)
814            loaded = pickle.loads(s)
815            self.assertEqual(loaded, orig)
816            self.assertEqual(loaded.__args__, orig.__args__)
817            self.assertEqual(loaded.__parameters__, orig.__parameters__)
818
819    def test_union_copy(self):
820        orig = list[T] | int
821        for copied in (copy.copy(orig), copy.deepcopy(orig)):
822            self.assertEqual(copied, orig)
823            self.assertEqual(copied.__args__, orig.__args__)
824            self.assertEqual(copied.__parameters__, orig.__parameters__)
825
826    def test_union_parameter_substitution_errors(self):
827        T = typing.TypeVar("T")
828        x = int | T
829        with self.assertRaises(TypeError):
830            x[42]
831
832    def test_or_type_operator_with_forward(self):
833        T = typing.TypeVar('T')
834        ForwardAfter = T | 'Forward'
835        ForwardBefore = 'Forward' | T
836        def forward_after(x: ForwardAfter[int]) -> None: ...
837        def forward_before(x: ForwardBefore[int]) -> None: ...
838        assert typing.get_args(typing.get_type_hints(forward_after)['x']) == (int, Forward)
839        assert typing.get_args(typing.get_type_hints(forward_before)['x']) == (int, Forward)
840
841    def test_or_type_operator_with_Protocol(self):
842        class Proto(typing.Protocol):
843            def meth(self) -> int:
844                ...
845        assert Proto | str == typing.Union[Proto, str]
846
847    def test_or_type_operator_with_Alias(self):
848        assert list | str == typing.Union[list, str]
849        assert typing.List | str == typing.Union[typing.List, str]
850
851    def test_or_type_operator_with_NamedTuple(self):
852        NT=namedtuple('A', ['B', 'C', 'D'])
853        assert NT | str == typing.Union[NT,str]
854
855    def test_or_type_operator_with_TypedDict(self):
856        class Point2D(typing.TypedDict):
857            x: int
858            y: int
859            label: str
860        assert Point2D | str == typing.Union[Point2D, str]
861
862    def test_or_type_operator_with_NewType(self):
863        UserId = typing.NewType('UserId', int)
864        assert UserId | str == typing.Union[UserId, str]
865
866    def test_or_type_operator_with_IO(self):
867        assert typing.IO | str == typing.Union[typing.IO, str]
868
869    def test_or_type_operator_with_SpecialForm(self):
870        assert typing.Any | str == typing.Union[typing.Any, str]
871        assert typing.NoReturn | str == typing.Union[typing.NoReturn, str]
872        assert typing.Optional[int] | str == typing.Union[typing.Optional[int], str]
873        assert typing.Optional[int] | str == typing.Union[int, str, None]
874        assert typing.Union[int, bool] | str == typing.Union[int, bool, str]
875
876    def test_or_type_repr(self):
877        assert repr(int | str) == "int | str"
878        assert repr((int | str) | list) == "int | str | list"
879        assert repr(int | (str | list)) == "int | str | list"
880        assert repr(int | None) == "int | None"
881        assert repr(int | type(None)) == "int | None"
882        assert repr(int | typing.GenericAlias(list, int)) == "int | list[int]"
883
884    def test_or_type_operator_with_genericalias(self):
885        a = list[int]
886        b = list[str]
887        c = dict[float, str]
888        class SubClass(types.GenericAlias): ...
889        d = SubClass(list, float)
890        # equivalence with typing.Union
891        self.assertEqual(a | b | c | d, typing.Union[a, b, c, d])
892        # de-duplicate
893        self.assertEqual(a | c | b | b | a | c | d | d, a | b | c | d)
894        # order shouldn't matter
895        self.assertEqual(a | b | d, b | a | d)
896        self.assertEqual(repr(a | b | c | d),
897                         "list[int] | list[str] | dict[float, str] | list[float]")
898
899        class BadType(type):
900            def __eq__(self, other):
901                return 1 / 0
902
903        bt = BadType('bt', (), {})
904        # Comparison should fail and errors should propagate out for bad types.
905        with self.assertRaises(ZeroDivisionError):
906            list[int] | list[bt]
907
908        union_ga = (int | list[str], int | collections.abc.Callable[..., str],
909                    int | d)
910        # Raise error when isinstance(type, type | genericalias)
911        for type_ in union_ga:
912            with self.subTest(f"check isinstance/issubclass is invalid for {type_}"):
913                with self.assertRaises(TypeError):
914                    isinstance(1, type_)
915                with self.assertRaises(TypeError):
916                    issubclass(int, type_)
917
918    def test_or_type_operator_with_bad_module(self):
919        class BadMeta(type):
920            __qualname__ = 'TypeVar'
921            @property
922            def __module__(self):
923                1 / 0
924        TypeVar = BadMeta('TypeVar', (), {})
925        _SpecialForm = BadMeta('_SpecialForm', (), {})
926        # Crashes in Issue44483
927        with self.assertRaises((TypeError, ZeroDivisionError)):
928            str | TypeVar()
929        with self.assertRaises((TypeError, ZeroDivisionError)):
930            str | _SpecialForm()
931
932    @cpython_only
933    def test_or_type_operator_reference_cycle(self):
934        if not hasattr(sys, 'gettotalrefcount'):
935            self.skipTest('Cannot get total reference count.')
936        gc.collect()
937        before = sys.gettotalrefcount()
938        for _ in range(30):
939            T = typing.TypeVar('T')
940            U = int | list[T]
941            T.blah = U
942            del T
943            del U
944        gc.collect()
945        leeway = 15
946        self.assertLessEqual(sys.gettotalrefcount() - before, leeway,
947                             msg='Check for union reference leak.')
948
949
950class MappingProxyTests(unittest.TestCase):
951    mappingproxy = types.MappingProxyType
952
953    def test_constructor(self):
954        class userdict(dict):
955            pass
956
957        mapping = {'x': 1, 'y': 2}
958        self.assertEqual(self.mappingproxy(mapping), mapping)
959        mapping = userdict(x=1, y=2)
960        self.assertEqual(self.mappingproxy(mapping), mapping)
961        mapping = collections.ChainMap({'x': 1}, {'y': 2})
962        self.assertEqual(self.mappingproxy(mapping), mapping)
963
964        self.assertRaises(TypeError, self.mappingproxy, 10)
965        self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple"))
966        self.assertRaises(TypeError, self.mappingproxy, ["a", "list"])
967
968    def test_methods(self):
969        attrs = set(dir(self.mappingproxy({}))) - set(dir(object()))
970        self.assertEqual(attrs, {
971             '__contains__',
972             '__getitem__',
973             '__class_getitem__',
974             '__ior__',
975             '__iter__',
976             '__len__',
977             '__or__',
978             '__reversed__',
979             '__ror__',
980             'copy',
981             'get',
982             'items',
983             'keys',
984             'values',
985        })
986
987    def test_get(self):
988        view = self.mappingproxy({'a': 'A', 'b': 'B'})
989        self.assertEqual(view['a'], 'A')
990        self.assertEqual(view['b'], 'B')
991        self.assertRaises(KeyError, view.__getitem__, 'xxx')
992        self.assertEqual(view.get('a'), 'A')
993        self.assertIsNone(view.get('xxx'))
994        self.assertEqual(view.get('xxx', 42), 42)
995
996    def test_missing(self):
997        class dictmissing(dict):
998            def __missing__(self, key):
999                return "missing=%s" % key
1000
1001        view = self.mappingproxy(dictmissing(x=1))
1002        self.assertEqual(view['x'], 1)
1003        self.assertEqual(view['y'], 'missing=y')
1004        self.assertEqual(view.get('x'), 1)
1005        self.assertEqual(view.get('y'), None)
1006        self.assertEqual(view.get('y', 42), 42)
1007        self.assertTrue('x' in view)
1008        self.assertFalse('y' in view)
1009
1010    def test_customdict(self):
1011        class customdict(dict):
1012            def __contains__(self, key):
1013                if key == 'magic':
1014                    return True
1015                else:
1016                    return dict.__contains__(self, key)
1017
1018            def __iter__(self):
1019                return iter(('iter',))
1020
1021            def __len__(self):
1022                return 500
1023
1024            def copy(self):
1025                return 'copy'
1026
1027            def keys(self):
1028                return 'keys'
1029
1030            def items(self):
1031                return 'items'
1032
1033            def values(self):
1034                return 'values'
1035
1036            def __getitem__(self, key):
1037                return "getitem=%s" % dict.__getitem__(self, key)
1038
1039            def get(self, key, default=None):
1040                return "get=%s" % dict.get(self, key, 'default=%r' % default)
1041
1042        custom = customdict({'key': 'value'})
1043        view = self.mappingproxy(custom)
1044        self.assertTrue('key' in view)
1045        self.assertTrue('magic' in view)
1046        self.assertFalse('xxx' in view)
1047        self.assertEqual(view['key'], 'getitem=value')
1048        self.assertRaises(KeyError, view.__getitem__, 'xxx')
1049        self.assertEqual(tuple(view), ('iter',))
1050        self.assertEqual(len(view), 500)
1051        self.assertEqual(view.copy(), 'copy')
1052        self.assertEqual(view.get('key'), 'get=value')
1053        self.assertEqual(view.get('xxx'), 'get=default=None')
1054        self.assertEqual(view.items(), 'items')
1055        self.assertEqual(view.keys(), 'keys')
1056        self.assertEqual(view.values(), 'values')
1057
1058    def test_chainmap(self):
1059        d1 = {'x': 1}
1060        d2 = {'y': 2}
1061        mapping = collections.ChainMap(d1, d2)
1062        view = self.mappingproxy(mapping)
1063        self.assertTrue('x' in view)
1064        self.assertTrue('y' in view)
1065        self.assertFalse('z' in view)
1066        self.assertEqual(view['x'], 1)
1067        self.assertEqual(view['y'], 2)
1068        self.assertRaises(KeyError, view.__getitem__, 'z')
1069        self.assertEqual(tuple(sorted(view)), ('x', 'y'))
1070        self.assertEqual(len(view), 2)
1071        copy = view.copy()
1072        self.assertIsNot(copy, mapping)
1073        self.assertIsInstance(copy, collections.ChainMap)
1074        self.assertEqual(copy, mapping)
1075        self.assertEqual(view.get('x'), 1)
1076        self.assertEqual(view.get('y'), 2)
1077        self.assertIsNone(view.get('z'))
1078        self.assertEqual(tuple(sorted(view.items())), (('x', 1), ('y', 2)))
1079        self.assertEqual(tuple(sorted(view.keys())), ('x', 'y'))
1080        self.assertEqual(tuple(sorted(view.values())), (1, 2))
1081
1082    def test_contains(self):
1083        view = self.mappingproxy(dict.fromkeys('abc'))
1084        self.assertTrue('a' in view)
1085        self.assertTrue('b' in view)
1086        self.assertTrue('c' in view)
1087        self.assertFalse('xxx' in view)
1088
1089    def test_views(self):
1090        mapping = {}
1091        view = self.mappingproxy(mapping)
1092        keys = view.keys()
1093        values = view.values()
1094        items = view.items()
1095        self.assertEqual(list(keys), [])
1096        self.assertEqual(list(values), [])
1097        self.assertEqual(list(items), [])
1098        mapping['key'] = 'value'
1099        self.assertEqual(list(keys), ['key'])
1100        self.assertEqual(list(values), ['value'])
1101        self.assertEqual(list(items), [('key', 'value')])
1102
1103    def test_len(self):
1104        for expected in range(6):
1105            data = dict.fromkeys('abcde'[:expected])
1106            self.assertEqual(len(data), expected)
1107            view = self.mappingproxy(data)
1108            self.assertEqual(len(view), expected)
1109
1110    def test_iterators(self):
1111        keys = ('x', 'y')
1112        values = (1, 2)
1113        items = tuple(zip(keys, values))
1114        view = self.mappingproxy(dict(items))
1115        self.assertEqual(set(view), set(keys))
1116        self.assertEqual(set(view.keys()), set(keys))
1117        self.assertEqual(set(view.values()), set(values))
1118        self.assertEqual(set(view.items()), set(items))
1119
1120    def test_reversed(self):
1121        d = {'a': 1, 'b': 2, 'foo': 0, 'c': 3, 'd': 4}
1122        mp = self.mappingproxy(d)
1123        del d['foo']
1124        r = reversed(mp)
1125        self.assertEqual(list(r), list('dcba'))
1126        self.assertRaises(StopIteration, next, r)
1127
1128    def test_copy(self):
1129        original = {'key1': 27, 'key2': 51, 'key3': 93}
1130        view = self.mappingproxy(original)
1131        copy = view.copy()
1132        self.assertEqual(type(copy), dict)
1133        self.assertEqual(copy, original)
1134        original['key1'] = 70
1135        self.assertEqual(view['key1'], 70)
1136        self.assertEqual(copy['key1'], 27)
1137
1138    def test_union(self):
1139        mapping = {'a': 0, 'b': 1, 'c': 2}
1140        view = self.mappingproxy(mapping)
1141        with self.assertRaises(TypeError):
1142            view | [('r', 2), ('d', 2)]
1143        with self.assertRaises(TypeError):
1144            [('r', 2), ('d', 2)] | view
1145        with self.assertRaises(TypeError):
1146            view |= [('r', 2), ('d', 2)]
1147        other = {'c': 3, 'p': 0}
1148        self.assertDictEqual(view | other, {'a': 0, 'b': 1, 'c': 3, 'p': 0})
1149        self.assertDictEqual(other | view, {'c': 2, 'p': 0, 'a': 0, 'b': 1})
1150        self.assertEqual(view, {'a': 0, 'b': 1, 'c': 2})
1151        self.assertDictEqual(mapping, {'a': 0, 'b': 1, 'c': 2})
1152        self.assertDictEqual(other, {'c': 3, 'p': 0})
1153
1154
1155class ClassCreationTests(unittest.TestCase):
1156
1157    class Meta(type):
1158        def __init__(cls, name, bases, ns, **kw):
1159            super().__init__(name, bases, ns)
1160        @staticmethod
1161        def __new__(mcls, name, bases, ns, **kw):
1162            return super().__new__(mcls, name, bases, ns)
1163        @classmethod
1164        def __prepare__(mcls, name, bases, **kw):
1165            ns = super().__prepare__(name, bases)
1166            ns["y"] = 1
1167            ns.update(kw)
1168            return ns
1169
1170    def test_new_class_basics(self):
1171        C = types.new_class("C")
1172        self.assertEqual(C.__name__, "C")
1173        self.assertEqual(C.__bases__, (object,))
1174
1175    def test_new_class_subclass(self):
1176        C = types.new_class("C", (int,))
1177        self.assertTrue(issubclass(C, int))
1178
1179    def test_new_class_meta(self):
1180        Meta = self.Meta
1181        settings = {"metaclass": Meta, "z": 2}
1182        # We do this twice to make sure the passed in dict isn't mutated
1183        for i in range(2):
1184            C = types.new_class("C" + str(i), (), settings)
1185            self.assertIsInstance(C, Meta)
1186            self.assertEqual(C.y, 1)
1187            self.assertEqual(C.z, 2)
1188
1189    def test_new_class_exec_body(self):
1190        Meta = self.Meta
1191        def func(ns):
1192            ns["x"] = 0
1193        C = types.new_class("C", (), {"metaclass": Meta, "z": 2}, func)
1194        self.assertIsInstance(C, Meta)
1195        self.assertEqual(C.x, 0)
1196        self.assertEqual(C.y, 1)
1197        self.assertEqual(C.z, 2)
1198
1199    def test_new_class_metaclass_keywords(self):
1200        #Test that keywords are passed to the metaclass:
1201        def meta_func(name, bases, ns, **kw):
1202            return name, bases, ns, kw
1203        res = types.new_class("X",
1204                              (int, object),
1205                              dict(metaclass=meta_func, x=0))
1206        self.assertEqual(res, ("X", (int, object), {}, {"x": 0}))
1207
1208    def test_new_class_defaults(self):
1209        # Test defaults/keywords:
1210        C = types.new_class("C", (), {}, None)
1211        self.assertEqual(C.__name__, "C")
1212        self.assertEqual(C.__bases__, (object,))
1213
1214    def test_new_class_meta_with_base(self):
1215        Meta = self.Meta
1216        def func(ns):
1217            ns["x"] = 0
1218        C = types.new_class(name="C",
1219                            bases=(int,),
1220                            kwds=dict(metaclass=Meta, z=2),
1221                            exec_body=func)
1222        self.assertTrue(issubclass(C, int))
1223        self.assertIsInstance(C, Meta)
1224        self.assertEqual(C.x, 0)
1225        self.assertEqual(C.y, 1)
1226        self.assertEqual(C.z, 2)
1227
1228    def test_new_class_with_mro_entry(self):
1229        class A: pass
1230        class C:
1231            def __mro_entries__(self, bases):
1232                return (A,)
1233        c = C()
1234        D = types.new_class('D', (c,), {})
1235        self.assertEqual(D.__bases__, (A,))
1236        self.assertEqual(D.__orig_bases__, (c,))
1237        self.assertEqual(D.__mro__, (D, A, object))
1238
1239    def test_new_class_with_mro_entry_genericalias(self):
1240        L1 = types.new_class('L1', (typing.List[int],), {})
1241        self.assertEqual(L1.__bases__, (list, typing.Generic))
1242        self.assertEqual(L1.__orig_bases__, (typing.List[int],))
1243        self.assertEqual(L1.__mro__, (L1, list, typing.Generic, object))
1244
1245        L2 = types.new_class('L2', (list[int],), {})
1246        self.assertEqual(L2.__bases__, (list,))
1247        self.assertEqual(L2.__orig_bases__, (list[int],))
1248        self.assertEqual(L2.__mro__, (L2, list, object))
1249
1250    def test_new_class_with_mro_entry_none(self):
1251        class A: pass
1252        class B: pass
1253        class C:
1254            def __mro_entries__(self, bases):
1255                return ()
1256        c = C()
1257        D = types.new_class('D', (A, c, B), {})
1258        self.assertEqual(D.__bases__, (A, B))
1259        self.assertEqual(D.__orig_bases__, (A, c, B))
1260        self.assertEqual(D.__mro__, (D, A, B, object))
1261
1262    def test_new_class_with_mro_entry_error(self):
1263        class A: pass
1264        class C:
1265            def __mro_entries__(self, bases):
1266                return A
1267        c = C()
1268        with self.assertRaises(TypeError):
1269            types.new_class('D', (c,), {})
1270
1271    def test_new_class_with_mro_entry_multiple(self):
1272        class A1: pass
1273        class A2: pass
1274        class B1: pass
1275        class B2: pass
1276        class A:
1277            def __mro_entries__(self, bases):
1278                return (A1, A2)
1279        class B:
1280            def __mro_entries__(self, bases):
1281                return (B1, B2)
1282        D = types.new_class('D', (A(), B()), {})
1283        self.assertEqual(D.__bases__, (A1, A2, B1, B2))
1284
1285    def test_new_class_with_mro_entry_multiple_2(self):
1286        class A1: pass
1287        class A2: pass
1288        class A3: pass
1289        class B1: pass
1290        class B2: pass
1291        class A:
1292            def __mro_entries__(self, bases):
1293                return (A1, A2, A3)
1294        class B:
1295            def __mro_entries__(self, bases):
1296                return (B1, B2)
1297        class C: pass
1298        D = types.new_class('D', (A(), C, B()), {})
1299        self.assertEqual(D.__bases__, (A1, A2, A3, C, B1, B2))
1300
1301    # Many of the following tests are derived from test_descr.py
1302    def test_prepare_class(self):
1303        # Basic test of metaclass derivation
1304        expected_ns = {}
1305        class A(type):
1306            def __new__(*args, **kwargs):
1307                return type.__new__(*args, **kwargs)
1308
1309            def __prepare__(*args):
1310                return expected_ns
1311
1312        B = types.new_class("B", (object,))
1313        C = types.new_class("C", (object,), {"metaclass": A})
1314
1315        # The most derived metaclass of D is A rather than type.
1316        meta, ns, kwds = types.prepare_class("D", (B, C), {"metaclass": type})
1317        self.assertIs(meta, A)
1318        self.assertIs(ns, expected_ns)
1319        self.assertEqual(len(kwds), 0)
1320
1321    def test_bad___prepare__(self):
1322        # __prepare__() must return a mapping.
1323        class BadMeta(type):
1324            @classmethod
1325            def __prepare__(*args):
1326                return None
1327        with self.assertRaisesRegex(TypeError,
1328                                    r'^BadMeta\.__prepare__\(\) must '
1329                                    r'return a mapping, not NoneType$'):
1330            class Foo(metaclass=BadMeta):
1331                pass
1332        # Also test the case in which the metaclass is not a type.
1333        class BadMeta:
1334            @classmethod
1335            def __prepare__(*args):
1336                return None
1337        with self.assertRaisesRegex(TypeError,
1338                                    r'^<metaclass>\.__prepare__\(\) must '
1339                                    r'return a mapping, not NoneType$'):
1340            class Bar(metaclass=BadMeta()):
1341                pass
1342
1343    def test_resolve_bases(self):
1344        class A: pass
1345        class B: pass
1346        class C:
1347            def __mro_entries__(self, bases):
1348                if A in bases:
1349                    return ()
1350                return (A,)
1351        c = C()
1352        self.assertEqual(types.resolve_bases(()), ())
1353        self.assertEqual(types.resolve_bases((c,)), (A,))
1354        self.assertEqual(types.resolve_bases((C,)), (C,))
1355        self.assertEqual(types.resolve_bases((A, C)), (A, C))
1356        self.assertEqual(types.resolve_bases((c, A)), (A,))
1357        self.assertEqual(types.resolve_bases((A, c)), (A,))
1358        x = (A,)
1359        y = (C,)
1360        z = (A, C)
1361        t = (A, C, B)
1362        for bases in [x, y, z, t]:
1363            self.assertIs(types.resolve_bases(bases), bases)
1364
1365    def test_resolve_bases_with_mro_entry(self):
1366        self.assertEqual(types.resolve_bases((typing.List[int],)),
1367                         (list, typing.Generic))
1368        self.assertEqual(types.resolve_bases((list[int],)), (list,))
1369
1370    def test_metaclass_derivation(self):
1371        # issue1294232: correct metaclass calculation
1372        new_calls = []  # to check the order of __new__ calls
1373        class AMeta(type):
1374            def __new__(mcls, name, bases, ns):
1375                new_calls.append('AMeta')
1376                return super().__new__(mcls, name, bases, ns)
1377            @classmethod
1378            def __prepare__(mcls, name, bases):
1379                return {}
1380
1381        class BMeta(AMeta):
1382            def __new__(mcls, name, bases, ns):
1383                new_calls.append('BMeta')
1384                return super().__new__(mcls, name, bases, ns)
1385            @classmethod
1386            def __prepare__(mcls, name, bases):
1387                ns = super().__prepare__(name, bases)
1388                ns['BMeta_was_here'] = True
1389                return ns
1390
1391        A = types.new_class("A", (), {"metaclass": AMeta})
1392        self.assertEqual(new_calls, ['AMeta'])
1393        new_calls.clear()
1394
1395        B = types.new_class("B", (), {"metaclass": BMeta})
1396        # BMeta.__new__ calls AMeta.__new__ with super:
1397        self.assertEqual(new_calls, ['BMeta', 'AMeta'])
1398        new_calls.clear()
1399
1400        C = types.new_class("C", (A, B))
1401        # The most derived metaclass is BMeta:
1402        self.assertEqual(new_calls, ['BMeta', 'AMeta'])
1403        new_calls.clear()
1404        # BMeta.__prepare__ should've been called:
1405        self.assertIn('BMeta_was_here', C.__dict__)
1406
1407        # The order of the bases shouldn't matter:
1408        C2 = types.new_class("C2", (B, A))
1409        self.assertEqual(new_calls, ['BMeta', 'AMeta'])
1410        new_calls.clear()
1411        self.assertIn('BMeta_was_here', C2.__dict__)
1412
1413        # Check correct metaclass calculation when a metaclass is declared:
1414        D = types.new_class("D", (C,), {"metaclass": type})
1415        self.assertEqual(new_calls, ['BMeta', 'AMeta'])
1416        new_calls.clear()
1417        self.assertIn('BMeta_was_here', D.__dict__)
1418
1419        E = types.new_class("E", (C,), {"metaclass": AMeta})
1420        self.assertEqual(new_calls, ['BMeta', 'AMeta'])
1421        new_calls.clear()
1422        self.assertIn('BMeta_was_here', E.__dict__)
1423
1424    def test_metaclass_override_function(self):
1425        # Special case: the given metaclass isn't a class,
1426        # so there is no metaclass calculation.
1427        class A(metaclass=self.Meta):
1428            pass
1429
1430        marker = object()
1431        def func(*args, **kwargs):
1432            return marker
1433
1434        X = types.new_class("X", (), {"metaclass": func})
1435        Y = types.new_class("Y", (object,), {"metaclass": func})
1436        Z = types.new_class("Z", (A,), {"metaclass": func})
1437        self.assertIs(marker, X)
1438        self.assertIs(marker, Y)
1439        self.assertIs(marker, Z)
1440
1441    def test_metaclass_override_callable(self):
1442        # The given metaclass is a class,
1443        # but not a descendant of type.
1444        new_calls = []  # to check the order of __new__ calls
1445        prepare_calls = []  # to track __prepare__ calls
1446        class ANotMeta:
1447            def __new__(mcls, *args, **kwargs):
1448                new_calls.append('ANotMeta')
1449                return super().__new__(mcls)
1450            @classmethod
1451            def __prepare__(mcls, name, bases):
1452                prepare_calls.append('ANotMeta')
1453                return {}
1454
1455        class BNotMeta(ANotMeta):
1456            def __new__(mcls, *args, **kwargs):
1457                new_calls.append('BNotMeta')
1458                return super().__new__(mcls)
1459            @classmethod
1460            def __prepare__(mcls, name, bases):
1461                prepare_calls.append('BNotMeta')
1462                return super().__prepare__(name, bases)
1463
1464        A = types.new_class("A", (), {"metaclass": ANotMeta})
1465        self.assertIs(ANotMeta, type(A))
1466        self.assertEqual(prepare_calls, ['ANotMeta'])
1467        prepare_calls.clear()
1468        self.assertEqual(new_calls, ['ANotMeta'])
1469        new_calls.clear()
1470
1471        B = types.new_class("B", (), {"metaclass": BNotMeta})
1472        self.assertIs(BNotMeta, type(B))
1473        self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
1474        prepare_calls.clear()
1475        self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
1476        new_calls.clear()
1477
1478        C = types.new_class("C", (A, B))
1479        self.assertIs(BNotMeta, type(C))
1480        self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
1481        prepare_calls.clear()
1482        self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
1483        new_calls.clear()
1484
1485        C2 = types.new_class("C2", (B, A))
1486        self.assertIs(BNotMeta, type(C2))
1487        self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
1488        prepare_calls.clear()
1489        self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
1490        new_calls.clear()
1491
1492        # This is a TypeError, because of a metaclass conflict:
1493        # BNotMeta is neither a subclass, nor a superclass of type
1494        with self.assertRaises(TypeError):
1495            D = types.new_class("D", (C,), {"metaclass": type})
1496
1497        E = types.new_class("E", (C,), {"metaclass": ANotMeta})
1498        self.assertIs(BNotMeta, type(E))
1499        self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
1500        prepare_calls.clear()
1501        self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
1502        new_calls.clear()
1503
1504        F = types.new_class("F", (object(), C))
1505        self.assertIs(BNotMeta, type(F))
1506        self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
1507        prepare_calls.clear()
1508        self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
1509        new_calls.clear()
1510
1511        F2 = types.new_class("F2", (C, object()))
1512        self.assertIs(BNotMeta, type(F2))
1513        self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
1514        prepare_calls.clear()
1515        self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
1516        new_calls.clear()
1517
1518        # TypeError: BNotMeta is neither a
1519        # subclass, nor a superclass of int
1520        with self.assertRaises(TypeError):
1521            X = types.new_class("X", (C, int()))
1522        with self.assertRaises(TypeError):
1523            X = types.new_class("X", (int(), C))
1524
1525    def test_one_argument_type(self):
1526        expected_message = 'type.__new__() takes exactly 3 arguments (1 given)'
1527
1528        # Only type itself can use the one-argument form (#27157)
1529        self.assertIs(type(5), int)
1530
1531        class M(type):
1532            pass
1533        with self.assertRaises(TypeError) as cm:
1534            M(5)
1535        self.assertEqual(str(cm.exception), expected_message)
1536
1537        class N(type, metaclass=M):
1538            pass
1539        with self.assertRaises(TypeError) as cm:
1540            N(5)
1541        self.assertEqual(str(cm.exception), expected_message)
1542
1543    def test_metaclass_new_error(self):
1544        # bpo-44232: The C function type_new() must properly report the
1545        # exception when a metaclass constructor raises an exception and the
1546        # winner class is not the metaclass.
1547        class ModelBase(type):
1548            def __new__(cls, name, bases, attrs):
1549                super_new = super().__new__
1550                new_class = super_new(cls, name, bases, {})
1551                if name != "Model":
1552                    raise RuntimeWarning(f"{name=}")
1553                return new_class
1554
1555        class Model(metaclass=ModelBase):
1556            pass
1557
1558        with self.assertRaises(RuntimeWarning):
1559            type("SouthPonies", (Model,), {})
1560
1561
1562class SimpleNamespaceTests(unittest.TestCase):
1563
1564    def test_constructor(self):
1565        ns1 = types.SimpleNamespace()
1566        ns2 = types.SimpleNamespace(x=1, y=2)
1567        ns3 = types.SimpleNamespace(**dict(x=1, y=2))
1568
1569        with self.assertRaises(TypeError):
1570            types.SimpleNamespace(1, 2, 3)
1571        with self.assertRaises(TypeError):
1572            types.SimpleNamespace(**{1: 2})
1573
1574        self.assertEqual(len(ns1.__dict__), 0)
1575        self.assertEqual(vars(ns1), {})
1576        self.assertEqual(len(ns2.__dict__), 2)
1577        self.assertEqual(vars(ns2), {'y': 2, 'x': 1})
1578        self.assertEqual(len(ns3.__dict__), 2)
1579        self.assertEqual(vars(ns3), {'y': 2, 'x': 1})
1580
1581    def test_unbound(self):
1582        ns1 = vars(types.SimpleNamespace())
1583        ns2 = vars(types.SimpleNamespace(x=1, y=2))
1584
1585        self.assertEqual(ns1, {})
1586        self.assertEqual(ns2, {'y': 2, 'x': 1})
1587
1588    def test_underlying_dict(self):
1589        ns1 = types.SimpleNamespace()
1590        ns2 = types.SimpleNamespace(x=1, y=2)
1591        ns3 = types.SimpleNamespace(a=True, b=False)
1592        mapping = ns3.__dict__
1593        del ns3
1594
1595        self.assertEqual(ns1.__dict__, {})
1596        self.assertEqual(ns2.__dict__, {'y': 2, 'x': 1})
1597        self.assertEqual(mapping, dict(a=True, b=False))
1598
1599    def test_attrget(self):
1600        ns = types.SimpleNamespace(x=1, y=2, w=3)
1601
1602        self.assertEqual(ns.x, 1)
1603        self.assertEqual(ns.y, 2)
1604        self.assertEqual(ns.w, 3)
1605        with self.assertRaises(AttributeError):
1606            ns.z
1607
1608    def test_attrset(self):
1609        ns1 = types.SimpleNamespace()
1610        ns2 = types.SimpleNamespace(x=1, y=2, w=3)
1611        ns1.a = 'spam'
1612        ns1.b = 'ham'
1613        ns2.z = 4
1614        ns2.theta = None
1615
1616        self.assertEqual(ns1.__dict__, dict(a='spam', b='ham'))
1617        self.assertEqual(ns2.__dict__, dict(x=1, y=2, w=3, z=4, theta=None))
1618
1619    def test_attrdel(self):
1620        ns1 = types.SimpleNamespace()
1621        ns2 = types.SimpleNamespace(x=1, y=2, w=3)
1622
1623        with self.assertRaises(AttributeError):
1624            del ns1.spam
1625        with self.assertRaises(AttributeError):
1626            del ns2.spam
1627
1628        del ns2.y
1629        self.assertEqual(vars(ns2), dict(w=3, x=1))
1630        ns2.y = 'spam'
1631        self.assertEqual(vars(ns2), dict(w=3, x=1, y='spam'))
1632        del ns2.y
1633        self.assertEqual(vars(ns2), dict(w=3, x=1))
1634
1635        ns1.spam = 5
1636        self.assertEqual(vars(ns1), dict(spam=5))
1637        del ns1.spam
1638        self.assertEqual(vars(ns1), {})
1639
1640    def test_repr(self):
1641        ns1 = types.SimpleNamespace(x=1, y=2, w=3)
1642        ns2 = types.SimpleNamespace()
1643        ns2.x = "spam"
1644        ns2._y = 5
1645        name = "namespace"
1646
1647        self.assertEqual(repr(ns1), "{name}(x=1, y=2, w=3)".format(name=name))
1648        self.assertEqual(repr(ns2), "{name}(x='spam', _y=5)".format(name=name))
1649
1650    def test_equal(self):
1651        ns1 = types.SimpleNamespace(x=1)
1652        ns2 = types.SimpleNamespace()
1653        ns2.x = 1
1654
1655        self.assertEqual(types.SimpleNamespace(), types.SimpleNamespace())
1656        self.assertEqual(ns1, ns2)
1657        self.assertNotEqual(ns2, types.SimpleNamespace())
1658
1659    def test_nested(self):
1660        ns1 = types.SimpleNamespace(a=1, b=2)
1661        ns2 = types.SimpleNamespace()
1662        ns3 = types.SimpleNamespace(x=ns1)
1663        ns2.spam = ns1
1664        ns2.ham = '?'
1665        ns2.spam = ns3
1666
1667        self.assertEqual(vars(ns1), dict(a=1, b=2))
1668        self.assertEqual(vars(ns2), dict(spam=ns3, ham='?'))
1669        self.assertEqual(ns2.spam, ns3)
1670        self.assertEqual(vars(ns3), dict(x=ns1))
1671        self.assertEqual(ns3.x.a, 1)
1672
1673    def test_recursive(self):
1674        ns1 = types.SimpleNamespace(c='cookie')
1675        ns2 = types.SimpleNamespace()
1676        ns3 = types.SimpleNamespace(x=1)
1677        ns1.spam = ns1
1678        ns2.spam = ns3
1679        ns3.spam = ns2
1680
1681        self.assertEqual(ns1.spam, ns1)
1682        self.assertEqual(ns1.spam.spam, ns1)
1683        self.assertEqual(ns1.spam.spam, ns1.spam)
1684        self.assertEqual(ns2.spam, ns3)
1685        self.assertEqual(ns3.spam, ns2)
1686        self.assertEqual(ns2.spam.spam, ns2)
1687
1688    def test_recursive_repr(self):
1689        ns1 = types.SimpleNamespace(c='cookie')
1690        ns2 = types.SimpleNamespace()
1691        ns3 = types.SimpleNamespace(x=1)
1692        ns1.spam = ns1
1693        ns2.spam = ns3
1694        ns3.spam = ns2
1695        name = "namespace"
1696        repr1 = "{name}(c='cookie', spam={name}(...))".format(name=name)
1697        repr2 = "{name}(spam={name}(x=1, spam={name}(...)))".format(name=name)
1698
1699        self.assertEqual(repr(ns1), repr1)
1700        self.assertEqual(repr(ns2), repr2)
1701
1702    def test_as_dict(self):
1703        ns = types.SimpleNamespace(spam='spamspamspam')
1704
1705        with self.assertRaises(TypeError):
1706            len(ns)
1707        with self.assertRaises(TypeError):
1708            iter(ns)
1709        with self.assertRaises(TypeError):
1710            'spam' in ns
1711        with self.assertRaises(TypeError):
1712            ns['spam']
1713
1714    def test_subclass(self):
1715        class Spam(types.SimpleNamespace):
1716            pass
1717
1718        spam = Spam(ham=8, eggs=9)
1719
1720        self.assertIs(type(spam), Spam)
1721        self.assertEqual(vars(spam), {'ham': 8, 'eggs': 9})
1722
1723    def test_pickle(self):
1724        ns = types.SimpleNamespace(breakfast="spam", lunch="spam")
1725
1726        for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1727            pname = "protocol {}".format(protocol)
1728            try:
1729                ns_pickled = pickle.dumps(ns, protocol)
1730            except TypeError as e:
1731                raise TypeError(pname) from e
1732            ns_roundtrip = pickle.loads(ns_pickled)
1733
1734            self.assertEqual(ns, ns_roundtrip, pname)
1735
1736    def test_fake_namespace_compare(self):
1737        # Issue #24257: Incorrect use of PyObject_IsInstance() caused
1738        # SystemError.
1739        class FakeSimpleNamespace(str):
1740            __class__ = types.SimpleNamespace
1741        self.assertFalse(types.SimpleNamespace() == FakeSimpleNamespace())
1742        self.assertTrue(types.SimpleNamespace() != FakeSimpleNamespace())
1743        with self.assertRaises(TypeError):
1744            types.SimpleNamespace() < FakeSimpleNamespace()
1745        with self.assertRaises(TypeError):
1746            types.SimpleNamespace() <= FakeSimpleNamespace()
1747        with self.assertRaises(TypeError):
1748            types.SimpleNamespace() > FakeSimpleNamespace()
1749        with self.assertRaises(TypeError):
1750            types.SimpleNamespace() >= FakeSimpleNamespace()
1751
1752
1753class CoroutineTests(unittest.TestCase):
1754    def test_wrong_args(self):
1755        samples = [None, 1, object()]
1756        for sample in samples:
1757            with self.assertRaisesRegex(TypeError,
1758                                        'types.coroutine.*expects a callable'):
1759                types.coroutine(sample)
1760
1761    def test_non_gen_values(self):
1762        @types.coroutine
1763        def foo():
1764            return 'spam'
1765        self.assertEqual(foo(), 'spam')
1766
1767        class Awaitable:
1768            def __await__(self):
1769                return ()
1770        aw = Awaitable()
1771        @types.coroutine
1772        def foo():
1773            return aw
1774        self.assertIs(aw, foo())
1775
1776        # decorate foo second time
1777        foo = types.coroutine(foo)
1778        self.assertIs(aw, foo())
1779
1780    def test_async_def(self):
1781        # Test that types.coroutine passes 'async def' coroutines
1782        # without modification
1783
1784        async def foo(): pass
1785        foo_code = foo.__code__
1786        foo_flags = foo.__code__.co_flags
1787        decorated_foo = types.coroutine(foo)
1788        self.assertIs(foo, decorated_foo)
1789        self.assertEqual(foo.__code__.co_flags, foo_flags)
1790        self.assertIs(decorated_foo.__code__, foo_code)
1791
1792        foo_coro = foo()
1793        def bar(): return foo_coro
1794        for _ in range(2):
1795            bar = types.coroutine(bar)
1796            coro = bar()
1797            self.assertIs(foo_coro, coro)
1798            self.assertEqual(coro.cr_code.co_flags, foo_flags)
1799            coro.close()
1800
1801    def test_duck_coro(self):
1802        class CoroLike:
1803            def send(self): pass
1804            def throw(self): pass
1805            def close(self): pass
1806            def __await__(self): return self
1807
1808        coro = CoroLike()
1809        @types.coroutine
1810        def foo():
1811            return coro
1812        self.assertIs(foo(), coro)
1813        self.assertIs(foo().__await__(), coro)
1814
1815    def test_duck_corogen(self):
1816        class CoroGenLike:
1817            def send(self): pass
1818            def throw(self): pass
1819            def close(self): pass
1820            def __await__(self): return self
1821            def __iter__(self): return self
1822            def __next__(self): pass
1823
1824        coro = CoroGenLike()
1825        @types.coroutine
1826        def foo():
1827            return coro
1828        self.assertIs(foo(), coro)
1829        self.assertIs(foo().__await__(), coro)
1830
1831    def test_duck_gen(self):
1832        class GenLike:
1833            def send(self): pass
1834            def throw(self): pass
1835            def close(self): pass
1836            def __iter__(self): pass
1837            def __next__(self): pass
1838
1839        # Setup generator mock object
1840        gen = unittest.mock.MagicMock(GenLike)
1841        gen.__iter__ = lambda gen: gen
1842        gen.__name__ = 'gen'
1843        gen.__qualname__ = 'test.gen'
1844        self.assertIsInstance(gen, collections.abc.Generator)
1845        self.assertIs(gen, iter(gen))
1846
1847        @types.coroutine
1848        def foo(): return gen
1849
1850        wrapper = foo()
1851        self.assertIsInstance(wrapper, types._GeneratorWrapper)
1852        self.assertIs(wrapper.__await__(), wrapper)
1853        # Wrapper proxies duck generators completely:
1854        self.assertIs(iter(wrapper), wrapper)
1855
1856        self.assertIsInstance(wrapper, collections.abc.Coroutine)
1857        self.assertIsInstance(wrapper, collections.abc.Awaitable)
1858
1859        self.assertIs(wrapper.__qualname__, gen.__qualname__)
1860        self.assertIs(wrapper.__name__, gen.__name__)
1861
1862        # Test AttributeErrors
1863        for name in {'gi_running', 'gi_frame', 'gi_code', 'gi_yieldfrom',
1864                     'cr_running', 'cr_frame', 'cr_code', 'cr_await'}:
1865            with self.assertRaises(AttributeError):
1866                getattr(wrapper, name)
1867
1868        # Test attributes pass-through
1869        gen.gi_running = object()
1870        gen.gi_frame = object()
1871        gen.gi_code = object()
1872        gen.gi_yieldfrom = object()
1873        self.assertIs(wrapper.gi_running, gen.gi_running)
1874        self.assertIs(wrapper.gi_frame, gen.gi_frame)
1875        self.assertIs(wrapper.gi_code, gen.gi_code)
1876        self.assertIs(wrapper.gi_yieldfrom, gen.gi_yieldfrom)
1877        self.assertIs(wrapper.cr_running, gen.gi_running)
1878        self.assertIs(wrapper.cr_frame, gen.gi_frame)
1879        self.assertIs(wrapper.cr_code, gen.gi_code)
1880        self.assertIs(wrapper.cr_await, gen.gi_yieldfrom)
1881
1882        wrapper.close()
1883        gen.close.assert_called_once_with()
1884
1885        wrapper.send(1)
1886        gen.send.assert_called_once_with(1)
1887        gen.reset_mock()
1888
1889        next(wrapper)
1890        gen.__next__.assert_called_once_with()
1891        gen.reset_mock()
1892
1893        wrapper.throw(1, 2, 3)
1894        gen.throw.assert_called_once_with(1, 2, 3)
1895        gen.reset_mock()
1896
1897        wrapper.throw(1, 2)
1898        gen.throw.assert_called_once_with(1, 2)
1899        gen.reset_mock()
1900
1901        wrapper.throw(1)
1902        gen.throw.assert_called_once_with(1)
1903        gen.reset_mock()
1904
1905        # Test exceptions propagation
1906        error = Exception()
1907        gen.throw.side_effect = error
1908        try:
1909            wrapper.throw(1)
1910        except Exception as ex:
1911            self.assertIs(ex, error)
1912        else:
1913            self.fail('wrapper did not propagate an exception')
1914
1915        # Test invalid args
1916        gen.reset_mock()
1917        with self.assertRaises(TypeError):
1918            wrapper.throw()
1919        self.assertFalse(gen.throw.called)
1920        with self.assertRaises(TypeError):
1921            wrapper.close(1)
1922        self.assertFalse(gen.close.called)
1923        with self.assertRaises(TypeError):
1924            wrapper.send()
1925        self.assertFalse(gen.send.called)
1926
1927        # Test that we do not double wrap
1928        @types.coroutine
1929        def bar(): return wrapper
1930        self.assertIs(wrapper, bar())
1931
1932        # Test weakrefs support
1933        ref = weakref.ref(wrapper)
1934        self.assertIs(ref(), wrapper)
1935
1936    def test_duck_functional_gen(self):
1937        class Generator:
1938            """Emulates the following generator (very clumsy):
1939
1940              def gen(fut):
1941                  result = yield fut
1942                  return result * 2
1943            """
1944            def __init__(self, fut):
1945                self._i = 0
1946                self._fut = fut
1947            def __iter__(self):
1948                return self
1949            def __next__(self):
1950                return self.send(None)
1951            def send(self, v):
1952                try:
1953                    if self._i == 0:
1954                        assert v is None
1955                        return self._fut
1956                    if self._i == 1:
1957                        raise StopIteration(v * 2)
1958                    if self._i > 1:
1959                        raise StopIteration
1960                finally:
1961                    self._i += 1
1962            def throw(self, tp, *exc):
1963                self._i = 100
1964                if tp is not GeneratorExit:
1965                    raise tp
1966            def close(self):
1967                self.throw(GeneratorExit)
1968
1969        @types.coroutine
1970        def foo(): return Generator('spam')
1971
1972        wrapper = foo()
1973        self.assertIsInstance(wrapper, types._GeneratorWrapper)
1974
1975        async def corofunc():
1976            return await foo() + 100
1977        coro = corofunc()
1978
1979        self.assertEqual(coro.send(None), 'spam')
1980        try:
1981            coro.send(20)
1982        except StopIteration as ex:
1983            self.assertEqual(ex.args[0], 140)
1984        else:
1985            self.fail('StopIteration was expected')
1986
1987    def test_gen(self):
1988        def gen_func():
1989            yield 1
1990            return (yield 2)
1991        gen = gen_func()
1992        @types.coroutine
1993        def foo(): return gen
1994        wrapper = foo()
1995        self.assertIsInstance(wrapper, types._GeneratorWrapper)
1996        self.assertIs(wrapper.__await__(), gen)
1997
1998        for name in ('__name__', '__qualname__', 'gi_code',
1999                     'gi_running', 'gi_frame'):
2000            self.assertIs(getattr(foo(), name),
2001                          getattr(gen, name))
2002        self.assertIs(foo().cr_code, gen.gi_code)
2003
2004        self.assertEqual(next(wrapper), 1)
2005        self.assertEqual(wrapper.send(None), 2)
2006        with self.assertRaisesRegex(StopIteration, 'spam'):
2007            wrapper.send('spam')
2008
2009        gen = gen_func()
2010        wrapper = foo()
2011        wrapper.send(None)
2012        with self.assertRaisesRegex(Exception, 'ham'):
2013            wrapper.throw(Exception, Exception('ham'))
2014
2015        # decorate foo second time
2016        foo = types.coroutine(foo)
2017        self.assertIs(foo().__await__(), gen)
2018
2019    def test_returning_itercoro(self):
2020        @types.coroutine
2021        def gen():
2022            yield
2023
2024        gencoro = gen()
2025
2026        @types.coroutine
2027        def foo():
2028            return gencoro
2029
2030        self.assertIs(foo(), gencoro)
2031
2032        # decorate foo second time
2033        foo = types.coroutine(foo)
2034        self.assertIs(foo(), gencoro)
2035
2036    def test_genfunc(self):
2037        def gen(): yield
2038        self.assertIs(types.coroutine(gen), gen)
2039        self.assertIs(types.coroutine(types.coroutine(gen)), gen)
2040
2041        self.assertTrue(gen.__code__.co_flags & inspect.CO_ITERABLE_COROUTINE)
2042        self.assertFalse(gen.__code__.co_flags & inspect.CO_COROUTINE)
2043
2044        g = gen()
2045        self.assertTrue(g.gi_code.co_flags & inspect.CO_ITERABLE_COROUTINE)
2046        self.assertFalse(g.gi_code.co_flags & inspect.CO_COROUTINE)
2047
2048        self.assertIs(types.coroutine(gen), gen)
2049
2050    def test_wrapper_object(self):
2051        def gen():
2052            yield
2053        @types.coroutine
2054        def coro():
2055            return gen()
2056
2057        wrapper = coro()
2058        self.assertIn('GeneratorWrapper', repr(wrapper))
2059        self.assertEqual(repr(wrapper), str(wrapper))
2060        self.assertTrue(set(dir(wrapper)).issuperset({
2061            '__await__', '__iter__', '__next__', 'cr_code', 'cr_running',
2062            'cr_frame', 'gi_code', 'gi_frame', 'gi_running', 'send',
2063            'close', 'throw'}))
2064
2065
2066if __name__ == '__main__':
2067    unittest.main()
2068