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