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