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 # confirm format options expected to fail on floats, such as integer 528 # presentation types 529 for format_spec in 'sbcdoxX': 530 self.assertRaises(ValueError, format, 0.0, format_spec) 531 self.assertRaises(ValueError, format, 1.0, format_spec) 532 self.assertRaises(ValueError, format, -1.0, format_spec) 533 self.assertRaises(ValueError, format, 1e100, format_spec) 534 self.assertRaises(ValueError, format, -1e100, format_spec) 535 self.assertRaises(ValueError, format, 1e-100, format_spec) 536 self.assertRaises(ValueError, format, -1e-100, format_spec) 537 538 # Alternate float formatting 539 test(1.0, '.0e', '1e+00') 540 test(1.0, '#.0e', '1.e+00') 541 test(1.0, '.0f', '1') 542 test(1.0, '#.0f', '1.') 543 test(1.1, 'g', '1.1') 544 test(1.1, '#g', '1.10000') 545 test(1.0, '.0%', '100%') 546 test(1.0, '#.0%', '100.%') 547 548 # Issue 7094: Alternate formatting (specified by #) 549 test(1.0, '0e', '1.000000e+00') 550 test(1.0, '#0e', '1.000000e+00') 551 test(1.0, '0f', '1.000000' ) 552 test(1.0, '#0f', '1.000000') 553 test(1.0, '.1e', '1.0e+00') 554 test(1.0, '#.1e', '1.0e+00') 555 test(1.0, '.1f', '1.0') 556 test(1.0, '#.1f', '1.0') 557 test(1.0, '.1%', '100.0%') 558 test(1.0, '#.1%', '100.0%') 559 560 # Issue 6902 561 test(12345.6, "0<20", '12345.60000000000000') 562 test(12345.6, "1<20", '12345.61111111111111') 563 test(12345.6, "*<20", '12345.6*************') 564 test(12345.6, "0>20", '000000000000012345.6') 565 test(12345.6, "1>20", '111111111111112345.6') 566 test(12345.6, "*>20", '*************12345.6') 567 test(12345.6, "0=20", '000000000000012345.6') 568 test(12345.6, "1=20", '111111111111112345.6') 569 test(12345.6, "*=20", '*************12345.6') 570 571 def test_format_spec_errors(self): 572 # int, float, and string all share the same format spec 573 # mini-language parser. 574 575 # Check that we can't ask for too many digits. This is 576 # probably a CPython specific test. It tries to put the width 577 # into a C long. 578 self.assertRaises(ValueError, format, 0, '1'*10000 + 'd') 579 580 # Similar with the precision. 581 self.assertRaises(ValueError, format, 0, '.' + '1'*10000 + 'd') 582 583 # And may as well test both. 584 self.assertRaises(ValueError, format, 0, '1'*1000 + '.' + '1'*10000 + 'd') 585 586 # Make sure commas aren't allowed with various type codes 587 for code in 'xXobns': 588 self.assertRaises(ValueError, format, 0, ',' + code) 589 590 def test_internal_sizes(self): 591 self.assertGreater(object.__basicsize__, 0) 592 self.assertGreater(tuple.__itemsize__, 0) 593 594 def test_slot_wrapper_types(self): 595 self.assertIsInstance(object.__init__, types.WrapperDescriptorType) 596 self.assertIsInstance(object.__str__, types.WrapperDescriptorType) 597 self.assertIsInstance(object.__lt__, types.WrapperDescriptorType) 598 self.assertIsInstance(int.__lt__, types.WrapperDescriptorType) 599 600 def test_dunder_get_signature(self): 601 sig = inspect.signature(object.__init__.__get__) 602 self.assertEqual(list(sig.parameters), ["instance", "owner"]) 603 # gh-93021: Second parameter is optional 604 self.assertIs(sig.parameters["owner"].default, None) 605 606 def test_method_wrapper_types(self): 607 self.assertIsInstance(object().__init__, types.MethodWrapperType) 608 self.assertIsInstance(object().__str__, types.MethodWrapperType) 609 self.assertIsInstance(object().__lt__, types.MethodWrapperType) 610 self.assertIsInstance((42).__lt__, types.MethodWrapperType) 611 612 def test_method_descriptor_types(self): 613 self.assertIsInstance(str.join, types.MethodDescriptorType) 614 self.assertIsInstance(list.append, types.MethodDescriptorType) 615 self.assertIsInstance(''.join, types.BuiltinMethodType) 616 self.assertIsInstance([].append, types.BuiltinMethodType) 617 618 self.assertIsInstance(int.__dict__['from_bytes'], types.ClassMethodDescriptorType) 619 self.assertIsInstance(int.from_bytes, types.BuiltinMethodType) 620 self.assertIsInstance(int.__new__, types.BuiltinMethodType) 621 622 def test_ellipsis_type(self): 623 self.assertIsInstance(Ellipsis, types.EllipsisType) 624 625 def test_notimplemented_type(self): 626 self.assertIsInstance(NotImplemented, types.NotImplementedType) 627 628 def test_none_type(self): 629 self.assertIsInstance(None, types.NoneType) 630 631 def test_traceback_and_frame_types(self): 632 try: 633 raise OSError 634 except OSError as e: 635 exc = e 636 self.assertIsInstance(exc.__traceback__, types.TracebackType) 637 self.assertIsInstance(exc.__traceback__.tb_frame, types.FrameType) 638 639 640class UnionTests(unittest.TestCase): 641 642 def test_or_types_operator(self): 643 self.assertEqual(int | str, typing.Union[int, str]) 644 self.assertNotEqual(int | list, typing.Union[int, str]) 645 self.assertEqual(str | int, typing.Union[int, str]) 646 self.assertEqual(int | None, typing.Union[int, None]) 647 self.assertEqual(None | int, typing.Union[int, None]) 648 self.assertEqual(int | type(None), int | None) 649 self.assertEqual(type(None) | int, None | int) 650 self.assertEqual(int | str | list, typing.Union[int, str, list]) 651 self.assertEqual(int | (str | list), typing.Union[int, str, list]) 652 self.assertEqual(str | (int | list), typing.Union[int, str, list]) 653 self.assertEqual(typing.List | typing.Tuple, typing.Union[typing.List, typing.Tuple]) 654 self.assertEqual(typing.List[int] | typing.Tuple[int], typing.Union[typing.List[int], typing.Tuple[int]]) 655 self.assertEqual(typing.List[int] | None, typing.Union[typing.List[int], None]) 656 self.assertEqual(None | typing.List[int], typing.Union[None, typing.List[int]]) 657 self.assertEqual(str | float | int | complex | int, (int | str) | (float | complex)) 658 self.assertEqual(typing.Union[str, int, typing.List[int]], str | int | typing.List[int]) 659 self.assertIs(int | int, int) 660 self.assertEqual( 661 BaseException | 662 bool | 663 bytes | 664 complex | 665 float | 666 int | 667 list | 668 map | 669 set, 670 typing.Union[ 671 BaseException, 672 bool, 673 bytes, 674 complex, 675 float, 676 int, 677 list, 678 map, 679 set, 680 ]) 681 with self.assertRaises(TypeError): 682 int | 3 683 with self.assertRaises(TypeError): 684 3 | int 685 with self.assertRaises(TypeError): 686 Example() | int 687 x = int | str 688 self.assertEqual(x, int | str) 689 self.assertEqual(x, str | int) 690 self.assertNotEqual(x, {}) # should not raise exception 691 with self.assertRaises(TypeError): 692 x < x 693 with self.assertRaises(TypeError): 694 x <= x 695 y = typing.Union[str, int] 696 with self.assertRaises(TypeError): 697 x < y 698 y = int | bool 699 with self.assertRaises(TypeError): 700 x < y 701 # Check that we don't crash if typing.Union does not have a tuple in __args__ 702 y = typing.Union[str, int] 703 y.__args__ = [str, int] 704 self.assertEqual(x, y) 705 706 def test_hash(self): 707 self.assertEqual(hash(int | str), hash(str | int)) 708 self.assertEqual(hash(int | str), hash(typing.Union[int, str])) 709 710 def test_instancecheck_and_subclasscheck(self): 711 for x in (int | str, typing.Union[int, str]): 712 with self.subTest(x=x): 713 self.assertIsInstance(1, x) 714 self.assertIsInstance(True, x) 715 self.assertIsInstance('a', x) 716 self.assertNotIsInstance(None, x) 717 self.assertTrue(issubclass(int, x)) 718 self.assertTrue(issubclass(bool, x)) 719 self.assertTrue(issubclass(str, x)) 720 self.assertFalse(issubclass(type(None), x)) 721 722 for x in (int | None, typing.Union[int, None]): 723 with self.subTest(x=x): 724 self.assertIsInstance(None, x) 725 self.assertTrue(issubclass(type(None), x)) 726 727 for x in ( 728 int | collections.abc.Mapping, 729 typing.Union[int, collections.abc.Mapping], 730 ): 731 with self.subTest(x=x): 732 self.assertIsInstance({}, x) 733 self.assertNotIsInstance((), x) 734 self.assertTrue(issubclass(dict, x)) 735 self.assertFalse(issubclass(list, x)) 736 737 def test_instancecheck_and_subclasscheck_order(self): 738 T = typing.TypeVar('T') 739 740 will_resolve = ( 741 int | T, 742 typing.Union[int, T], 743 ) 744 for x in will_resolve: 745 with self.subTest(x=x): 746 self.assertIsInstance(1, x) 747 self.assertTrue(issubclass(int, x)) 748 749 wont_resolve = ( 750 T | int, 751 typing.Union[T, int], 752 ) 753 for x in wont_resolve: 754 with self.subTest(x=x): 755 with self.assertRaises(TypeError): 756 issubclass(int, x) 757 with self.assertRaises(TypeError): 758 isinstance(1, x) 759 760 for x in (*will_resolve, *wont_resolve): 761 with self.subTest(x=x): 762 with self.assertRaises(TypeError): 763 issubclass(object, x) 764 with self.assertRaises(TypeError): 765 isinstance(object(), x) 766 767 def test_bad_instancecheck(self): 768 class BadMeta(type): 769 def __instancecheck__(cls, inst): 770 1/0 771 x = int | BadMeta('A', (), {}) 772 self.assertTrue(isinstance(1, x)) 773 self.assertRaises(ZeroDivisionError, isinstance, [], x) 774 775 def test_bad_subclasscheck(self): 776 class BadMeta(type): 777 def __subclasscheck__(cls, sub): 778 1/0 779 x = int | BadMeta('A', (), {}) 780 self.assertTrue(issubclass(int, x)) 781 self.assertRaises(ZeroDivisionError, issubclass, list, x) 782 783 def test_or_type_operator_with_TypeVar(self): 784 TV = typing.TypeVar('T') 785 assert TV | str == typing.Union[TV, str] 786 assert str | TV == typing.Union[str, TV] 787 self.assertIs((int | TV)[int], int) 788 self.assertIs((TV | int)[int], int) 789 790 def test_union_args(self): 791 def check(arg, expected): 792 clear_typing_caches() 793 self.assertEqual(arg.__args__, expected) 794 795 check(int | str, (int, str)) 796 check((int | str) | list, (int, str, list)) 797 check(int | (str | list), (int, str, list)) 798 check((int | str) | int, (int, str)) 799 check(int | (str | int), (int, str)) 800 check((int | str) | (str | int), (int, str)) 801 check(typing.Union[int, str] | list, (int, str, list)) 802 check(int | typing.Union[str, list], (int, str, list)) 803 check((int | str) | (list | int), (int, str, list)) 804 check((int | str) | typing.Union[list, int], (int, str, list)) 805 check(typing.Union[int, str] | (list | int), (int, str, list)) 806 check((str | int) | (int | list), (str, int, list)) 807 check((str | int) | typing.Union[int, list], (str, int, list)) 808 check(typing.Union[str, int] | (int | list), (str, int, list)) 809 check(int | type(None), (int, type(None))) 810 check(type(None) | int, (type(None), int)) 811 812 args = (int, list[int], typing.List[int], 813 typing.Tuple[int, int], typing.Callable[[int], int], 814 typing.Hashable, typing.TypeVar('T')) 815 for x in args: 816 with self.subTest(x): 817 check(x | None, (x, type(None))) 818 check(None | x, (type(None), x)) 819 820 def test_union_parameter_chaining(self): 821 T = typing.TypeVar("T") 822 S = typing.TypeVar("S") 823 824 self.assertEqual((float | list[T])[int], float | list[int]) 825 self.assertEqual(list[int | list[T]].__parameters__, (T,)) 826 self.assertEqual(list[int | list[T]][str], list[int | list[str]]) 827 self.assertEqual((list[T] | list[S]).__parameters__, (T, S)) 828 self.assertEqual((list[T] | list[S])[int, T], list[int] | list[T]) 829 self.assertEqual((list[T] | list[S])[int, int], list[int]) 830 831 def test_union_parameter_substitution(self): 832 def eq(actual, expected, typed=True): 833 self.assertEqual(actual, expected) 834 if typed: 835 self.assertIs(type(actual), type(expected)) 836 837 T = typing.TypeVar('T') 838 S = typing.TypeVar('S') 839 NT = typing.NewType('NT', str) 840 x = int | T | bytes 841 842 eq(x[str], int | str | bytes, typed=False) 843 eq(x[list[int]], int | list[int] | bytes, typed=False) 844 eq(x[typing.List], int | typing.List | bytes) 845 eq(x[typing.List[int]], int | typing.List[int] | bytes) 846 eq(x[typing.Hashable], int | typing.Hashable | bytes) 847 eq(x[collections.abc.Hashable], 848 int | collections.abc.Hashable | bytes, typed=False) 849 eq(x[typing.Callable[[int], str]], 850 int | typing.Callable[[int], str] | bytes) 851 eq(x[collections.abc.Callable[[int], str]], 852 int | collections.abc.Callable[[int], str] | bytes, typed=False) 853 eq(x[typing.Tuple[int, str]], int | typing.Tuple[int, str] | bytes) 854 eq(x[typing.Literal['none']], int | typing.Literal['none'] | bytes) 855 eq(x[str | list], int | str | list | bytes, typed=False) 856 eq(x[typing.Union[str, list]], typing.Union[int, str, list, bytes]) 857 eq(x[str | int], int | str | bytes, typed=False) 858 eq(x[typing.Union[str, int]], typing.Union[int, str, bytes]) 859 eq(x[NT], int | NT | bytes) 860 eq(x[S], int | S | bytes) 861 862 def test_union_pickle(self): 863 orig = list[T] | int 864 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 865 s = pickle.dumps(orig, proto) 866 loaded = pickle.loads(s) 867 self.assertEqual(loaded, orig) 868 self.assertEqual(loaded.__args__, orig.__args__) 869 self.assertEqual(loaded.__parameters__, orig.__parameters__) 870 871 def test_union_copy(self): 872 orig = list[T] | int 873 for copied in (copy.copy(orig), copy.deepcopy(orig)): 874 self.assertEqual(copied, orig) 875 self.assertEqual(copied.__args__, orig.__args__) 876 self.assertEqual(copied.__parameters__, orig.__parameters__) 877 878 def test_union_parameter_substitution_errors(self): 879 T = typing.TypeVar("T") 880 x = int | T 881 with self.assertRaises(TypeError): 882 x[int, str] 883 884 def test_or_type_operator_with_forward(self): 885 T = typing.TypeVar('T') 886 ForwardAfter = T | 'Forward' 887 ForwardBefore = 'Forward' | T 888 def forward_after(x: ForwardAfter[int]) -> None: ... 889 def forward_before(x: ForwardBefore[int]) -> None: ... 890 assert typing.get_args(typing.get_type_hints(forward_after)['x']) == (int, Forward) 891 assert typing.get_args(typing.get_type_hints(forward_before)['x']) == (int, Forward) 892 893 def test_or_type_operator_with_Protocol(self): 894 class Proto(typing.Protocol): 895 def meth(self) -> int: 896 ... 897 assert Proto | str == typing.Union[Proto, str] 898 899 def test_or_type_operator_with_Alias(self): 900 assert list | str == typing.Union[list, str] 901 assert typing.List | str == typing.Union[typing.List, str] 902 903 def test_or_type_operator_with_NamedTuple(self): 904 NT=namedtuple('A', ['B', 'C', 'D']) 905 assert NT | str == typing.Union[NT,str] 906 907 def test_or_type_operator_with_TypedDict(self): 908 class Point2D(typing.TypedDict): 909 x: int 910 y: int 911 label: str 912 assert Point2D | str == typing.Union[Point2D, str] 913 914 def test_or_type_operator_with_NewType(self): 915 UserId = typing.NewType('UserId', int) 916 assert UserId | str == typing.Union[UserId, str] 917 918 def test_or_type_operator_with_IO(self): 919 assert typing.IO | str == typing.Union[typing.IO, str] 920 921 def test_or_type_operator_with_SpecialForm(self): 922 assert typing.Any | str == typing.Union[typing.Any, str] 923 assert typing.NoReturn | str == typing.Union[typing.NoReturn, str] 924 assert typing.Optional[int] | str == typing.Union[typing.Optional[int], str] 925 assert typing.Optional[int] | str == typing.Union[int, str, None] 926 assert typing.Union[int, bool] | str == typing.Union[int, bool, str] 927 928 def test_or_type_operator_with_Literal(self): 929 Literal = typing.Literal 930 self.assertEqual((Literal[1] | Literal[2]).__args__, 931 (Literal[1], Literal[2])) 932 933 self.assertEqual((Literal[0] | Literal[False]).__args__, 934 (Literal[0], Literal[False])) 935 self.assertEqual((Literal[1] | Literal[True]).__args__, 936 (Literal[1], Literal[True])) 937 938 self.assertEqual(Literal[1] | Literal[1], Literal[1]) 939 self.assertEqual(Literal['a'] | Literal['a'], Literal['a']) 940 941 import enum 942 class Ints(enum.IntEnum): 943 A = 0 944 B = 1 945 946 self.assertEqual(Literal[Ints.A] | Literal[Ints.A], Literal[Ints.A]) 947 self.assertEqual(Literal[Ints.B] | Literal[Ints.B], Literal[Ints.B]) 948 949 self.assertEqual((Literal[Ints.B] | Literal[Ints.A]).__args__, 950 (Literal[Ints.B], Literal[Ints.A])) 951 952 self.assertEqual((Literal[0] | Literal[Ints.A]).__args__, 953 (Literal[0], Literal[Ints.A])) 954 self.assertEqual((Literal[1] | Literal[Ints.B]).__args__, 955 (Literal[1], Literal[Ints.B])) 956 957 def test_or_type_repr(self): 958 assert repr(int | str) == "int | str" 959 assert repr((int | str) | list) == "int | str | list" 960 assert repr(int | (str | list)) == "int | str | list" 961 assert repr(int | None) == "int | None" 962 assert repr(int | type(None)) == "int | None" 963 assert repr(int | typing.GenericAlias(list, int)) == "int | list[int]" 964 965 def test_or_type_operator_with_genericalias(self): 966 a = list[int] 967 b = list[str] 968 c = dict[float, str] 969 class SubClass(types.GenericAlias): ... 970 d = SubClass(list, float) 971 # equivalence with typing.Union 972 self.assertEqual(a | b | c | d, typing.Union[a, b, c, d]) 973 # de-duplicate 974 self.assertEqual(a | c | b | b | a | c | d | d, a | b | c | d) 975 # order shouldn't matter 976 self.assertEqual(a | b | d, b | a | d) 977 self.assertEqual(repr(a | b | c | d), 978 "list[int] | list[str] | dict[float, str] | list[float]") 979 980 class BadType(type): 981 def __eq__(self, other): 982 return 1 / 0 983 984 bt = BadType('bt', (), {}) 985 # Comparison should fail and errors should propagate out for bad types. 986 with self.assertRaises(ZeroDivisionError): 987 list[int] | list[bt] 988 989 union_ga = (list[str] | int, collections.abc.Callable[..., str] | int, 990 d | int) 991 # Raise error when isinstance(type, genericalias | type) 992 for type_ in union_ga: 993 with self.subTest(f"check isinstance/issubclass is invalid for {type_}"): 994 with self.assertRaises(TypeError): 995 isinstance(1, type_) 996 with self.assertRaises(TypeError): 997 issubclass(int, type_) 998 999 def test_or_type_operator_with_bad_module(self): 1000 class BadMeta(type): 1001 __qualname__ = 'TypeVar' 1002 @property 1003 def __module__(self): 1004 1 / 0 1005 TypeVar = BadMeta('TypeVar', (), {}) 1006 _SpecialForm = BadMeta('_SpecialForm', (), {}) 1007 # Crashes in Issue44483 1008 with self.assertRaises((TypeError, ZeroDivisionError)): 1009 str | TypeVar() 1010 with self.assertRaises((TypeError, ZeroDivisionError)): 1011 str | _SpecialForm() 1012 1013 @cpython_only 1014 def test_or_type_operator_reference_cycle(self): 1015 if not hasattr(sys, 'gettotalrefcount'): 1016 self.skipTest('Cannot get total reference count.') 1017 gc.collect() 1018 before = sys.gettotalrefcount() 1019 for _ in range(30): 1020 T = typing.TypeVar('T') 1021 U = int | list[T] 1022 T.blah = U 1023 del T 1024 del U 1025 gc.collect() 1026 leeway = 15 1027 self.assertLessEqual(sys.gettotalrefcount() - before, leeway, 1028 msg='Check for union reference leak.') 1029 1030 1031class MappingProxyTests(unittest.TestCase): 1032 mappingproxy = types.MappingProxyType 1033 1034 def test_constructor(self): 1035 class userdict(dict): 1036 pass 1037 1038 mapping = {'x': 1, 'y': 2} 1039 self.assertEqual(self.mappingproxy(mapping), mapping) 1040 mapping = userdict(x=1, y=2) 1041 self.assertEqual(self.mappingproxy(mapping), mapping) 1042 mapping = collections.ChainMap({'x': 1}, {'y': 2}) 1043 self.assertEqual(self.mappingproxy(mapping), mapping) 1044 1045 self.assertRaises(TypeError, self.mappingproxy, 10) 1046 self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple")) 1047 self.assertRaises(TypeError, self.mappingproxy, ["a", "list"]) 1048 1049 def test_methods(self): 1050 attrs = set(dir(self.mappingproxy({}))) - set(dir(object())) 1051 self.assertEqual(attrs, { 1052 '__contains__', 1053 '__getitem__', 1054 '__class_getitem__', 1055 '__ior__', 1056 '__iter__', 1057 '__len__', 1058 '__or__', 1059 '__reversed__', 1060 '__ror__', 1061 'copy', 1062 'get', 1063 'items', 1064 'keys', 1065 'values', 1066 }) 1067 1068 def test_get(self): 1069 view = self.mappingproxy({'a': 'A', 'b': 'B'}) 1070 self.assertEqual(view['a'], 'A') 1071 self.assertEqual(view['b'], 'B') 1072 self.assertRaises(KeyError, view.__getitem__, 'xxx') 1073 self.assertEqual(view.get('a'), 'A') 1074 self.assertIsNone(view.get('xxx')) 1075 self.assertEqual(view.get('xxx', 42), 42) 1076 1077 def test_missing(self): 1078 class dictmissing(dict): 1079 def __missing__(self, key): 1080 return "missing=%s" % key 1081 1082 view = self.mappingproxy(dictmissing(x=1)) 1083 self.assertEqual(view['x'], 1) 1084 self.assertEqual(view['y'], 'missing=y') 1085 self.assertEqual(view.get('x'), 1) 1086 self.assertEqual(view.get('y'), None) 1087 self.assertEqual(view.get('y', 42), 42) 1088 self.assertTrue('x' in view) 1089 self.assertFalse('y' in view) 1090 1091 def test_customdict(self): 1092 class customdict(dict): 1093 def __contains__(self, key): 1094 if key == 'magic': 1095 return True 1096 else: 1097 return dict.__contains__(self, key) 1098 1099 def __iter__(self): 1100 return iter(('iter',)) 1101 1102 def __len__(self): 1103 return 500 1104 1105 def copy(self): 1106 return 'copy' 1107 1108 def keys(self): 1109 return 'keys' 1110 1111 def items(self): 1112 return 'items' 1113 1114 def values(self): 1115 return 'values' 1116 1117 def __getitem__(self, key): 1118 return "getitem=%s" % dict.__getitem__(self, key) 1119 1120 def get(self, key, default=None): 1121 return "get=%s" % dict.get(self, key, 'default=%r' % default) 1122 1123 custom = customdict({'key': 'value'}) 1124 view = self.mappingproxy(custom) 1125 self.assertTrue('key' in view) 1126 self.assertTrue('magic' in view) 1127 self.assertFalse('xxx' in view) 1128 self.assertEqual(view['key'], 'getitem=value') 1129 self.assertRaises(KeyError, view.__getitem__, 'xxx') 1130 self.assertEqual(tuple(view), ('iter',)) 1131 self.assertEqual(len(view), 500) 1132 self.assertEqual(view.copy(), 'copy') 1133 self.assertEqual(view.get('key'), 'get=value') 1134 self.assertEqual(view.get('xxx'), 'get=default=None') 1135 self.assertEqual(view.items(), 'items') 1136 self.assertEqual(view.keys(), 'keys') 1137 self.assertEqual(view.values(), 'values') 1138 1139 def test_chainmap(self): 1140 d1 = {'x': 1} 1141 d2 = {'y': 2} 1142 mapping = collections.ChainMap(d1, d2) 1143 view = self.mappingproxy(mapping) 1144 self.assertTrue('x' in view) 1145 self.assertTrue('y' in view) 1146 self.assertFalse('z' in view) 1147 self.assertEqual(view['x'], 1) 1148 self.assertEqual(view['y'], 2) 1149 self.assertRaises(KeyError, view.__getitem__, 'z') 1150 self.assertEqual(tuple(sorted(view)), ('x', 'y')) 1151 self.assertEqual(len(view), 2) 1152 copy = view.copy() 1153 self.assertIsNot(copy, mapping) 1154 self.assertIsInstance(copy, collections.ChainMap) 1155 self.assertEqual(copy, mapping) 1156 self.assertEqual(view.get('x'), 1) 1157 self.assertEqual(view.get('y'), 2) 1158 self.assertIsNone(view.get('z')) 1159 self.assertEqual(tuple(sorted(view.items())), (('x', 1), ('y', 2))) 1160 self.assertEqual(tuple(sorted(view.keys())), ('x', 'y')) 1161 self.assertEqual(tuple(sorted(view.values())), (1, 2)) 1162 1163 def test_contains(self): 1164 view = self.mappingproxy(dict.fromkeys('abc')) 1165 self.assertTrue('a' in view) 1166 self.assertTrue('b' in view) 1167 self.assertTrue('c' in view) 1168 self.assertFalse('xxx' in view) 1169 1170 def test_views(self): 1171 mapping = {} 1172 view = self.mappingproxy(mapping) 1173 keys = view.keys() 1174 values = view.values() 1175 items = view.items() 1176 self.assertEqual(list(keys), []) 1177 self.assertEqual(list(values), []) 1178 self.assertEqual(list(items), []) 1179 mapping['key'] = 'value' 1180 self.assertEqual(list(keys), ['key']) 1181 self.assertEqual(list(values), ['value']) 1182 self.assertEqual(list(items), [('key', 'value')]) 1183 1184 def test_len(self): 1185 for expected in range(6): 1186 data = dict.fromkeys('abcde'[:expected]) 1187 self.assertEqual(len(data), expected) 1188 view = self.mappingproxy(data) 1189 self.assertEqual(len(view), expected) 1190 1191 def test_iterators(self): 1192 keys = ('x', 'y') 1193 values = (1, 2) 1194 items = tuple(zip(keys, values)) 1195 view = self.mappingproxy(dict(items)) 1196 self.assertEqual(set(view), set(keys)) 1197 self.assertEqual(set(view.keys()), set(keys)) 1198 self.assertEqual(set(view.values()), set(values)) 1199 self.assertEqual(set(view.items()), set(items)) 1200 1201 def test_reversed(self): 1202 d = {'a': 1, 'b': 2, 'foo': 0, 'c': 3, 'd': 4} 1203 mp = self.mappingproxy(d) 1204 del d['foo'] 1205 r = reversed(mp) 1206 self.assertEqual(list(r), list('dcba')) 1207 self.assertRaises(StopIteration, next, r) 1208 1209 def test_copy(self): 1210 original = {'key1': 27, 'key2': 51, 'key3': 93} 1211 view = self.mappingproxy(original) 1212 copy = view.copy() 1213 self.assertEqual(type(copy), dict) 1214 self.assertEqual(copy, original) 1215 original['key1'] = 70 1216 self.assertEqual(view['key1'], 70) 1217 self.assertEqual(copy['key1'], 27) 1218 1219 def test_union(self): 1220 mapping = {'a': 0, 'b': 1, 'c': 2} 1221 view = self.mappingproxy(mapping) 1222 with self.assertRaises(TypeError): 1223 view | [('r', 2), ('d', 2)] 1224 with self.assertRaises(TypeError): 1225 [('r', 2), ('d', 2)] | view 1226 with self.assertRaises(TypeError): 1227 view |= [('r', 2), ('d', 2)] 1228 other = {'c': 3, 'p': 0} 1229 self.assertDictEqual(view | other, {'a': 0, 'b': 1, 'c': 3, 'p': 0}) 1230 self.assertDictEqual(other | view, {'c': 2, 'p': 0, 'a': 0, 'b': 1}) 1231 self.assertEqual(view, {'a': 0, 'b': 1, 'c': 2}) 1232 self.assertDictEqual(mapping, {'a': 0, 'b': 1, 'c': 2}) 1233 self.assertDictEqual(other, {'c': 3, 'p': 0}) 1234 1235 1236class ClassCreationTests(unittest.TestCase): 1237 1238 class Meta(type): 1239 def __init__(cls, name, bases, ns, **kw): 1240 super().__init__(name, bases, ns) 1241 @staticmethod 1242 def __new__(mcls, name, bases, ns, **kw): 1243 return super().__new__(mcls, name, bases, ns) 1244 @classmethod 1245 def __prepare__(mcls, name, bases, **kw): 1246 ns = super().__prepare__(name, bases) 1247 ns["y"] = 1 1248 ns.update(kw) 1249 return ns 1250 1251 def test_new_class_basics(self): 1252 C = types.new_class("C") 1253 self.assertEqual(C.__name__, "C") 1254 self.assertEqual(C.__bases__, (object,)) 1255 1256 def test_new_class_subclass(self): 1257 C = types.new_class("C", (int,)) 1258 self.assertTrue(issubclass(C, int)) 1259 1260 def test_new_class_meta(self): 1261 Meta = self.Meta 1262 settings = {"metaclass": Meta, "z": 2} 1263 # We do this twice to make sure the passed in dict isn't mutated 1264 for i in range(2): 1265 C = types.new_class("C" + str(i), (), settings) 1266 self.assertIsInstance(C, Meta) 1267 self.assertEqual(C.y, 1) 1268 self.assertEqual(C.z, 2) 1269 1270 def test_new_class_exec_body(self): 1271 Meta = self.Meta 1272 def func(ns): 1273 ns["x"] = 0 1274 C = types.new_class("C", (), {"metaclass": Meta, "z": 2}, func) 1275 self.assertIsInstance(C, Meta) 1276 self.assertEqual(C.x, 0) 1277 self.assertEqual(C.y, 1) 1278 self.assertEqual(C.z, 2) 1279 1280 def test_new_class_metaclass_keywords(self): 1281 #Test that keywords are passed to the metaclass: 1282 def meta_func(name, bases, ns, **kw): 1283 return name, bases, ns, kw 1284 res = types.new_class("X", 1285 (int, object), 1286 dict(metaclass=meta_func, x=0)) 1287 self.assertEqual(res, ("X", (int, object), {}, {"x": 0})) 1288 1289 def test_new_class_defaults(self): 1290 # Test defaults/keywords: 1291 C = types.new_class("C", (), {}, None) 1292 self.assertEqual(C.__name__, "C") 1293 self.assertEqual(C.__bases__, (object,)) 1294 1295 def test_new_class_meta_with_base(self): 1296 Meta = self.Meta 1297 def func(ns): 1298 ns["x"] = 0 1299 C = types.new_class(name="C", 1300 bases=(int,), 1301 kwds=dict(metaclass=Meta, z=2), 1302 exec_body=func) 1303 self.assertTrue(issubclass(C, int)) 1304 self.assertIsInstance(C, Meta) 1305 self.assertEqual(C.x, 0) 1306 self.assertEqual(C.y, 1) 1307 self.assertEqual(C.z, 2) 1308 1309 def test_new_class_with_mro_entry(self): 1310 class A: pass 1311 class C: 1312 def __mro_entries__(self, bases): 1313 return (A,) 1314 c = C() 1315 D = types.new_class('D', (c,), {}) 1316 self.assertEqual(D.__bases__, (A,)) 1317 self.assertEqual(D.__orig_bases__, (c,)) 1318 self.assertEqual(D.__mro__, (D, A, object)) 1319 1320 def test_new_class_with_mro_entry_genericalias(self): 1321 L1 = types.new_class('L1', (typing.List[int],), {}) 1322 self.assertEqual(L1.__bases__, (list, typing.Generic)) 1323 self.assertEqual(L1.__orig_bases__, (typing.List[int],)) 1324 self.assertEqual(L1.__mro__, (L1, list, typing.Generic, object)) 1325 1326 L2 = types.new_class('L2', (list[int],), {}) 1327 self.assertEqual(L2.__bases__, (list,)) 1328 self.assertEqual(L2.__orig_bases__, (list[int],)) 1329 self.assertEqual(L2.__mro__, (L2, list, object)) 1330 1331 def test_new_class_with_mro_entry_none(self): 1332 class A: pass 1333 class B: pass 1334 class C: 1335 def __mro_entries__(self, bases): 1336 return () 1337 c = C() 1338 D = types.new_class('D', (A, c, B), {}) 1339 self.assertEqual(D.__bases__, (A, B)) 1340 self.assertEqual(D.__orig_bases__, (A, c, B)) 1341 self.assertEqual(D.__mro__, (D, A, B, object)) 1342 1343 def test_new_class_with_mro_entry_error(self): 1344 class A: pass 1345 class C: 1346 def __mro_entries__(self, bases): 1347 return A 1348 c = C() 1349 with self.assertRaises(TypeError): 1350 types.new_class('D', (c,), {}) 1351 1352 def test_new_class_with_mro_entry_multiple(self): 1353 class A1: pass 1354 class A2: pass 1355 class B1: pass 1356 class B2: pass 1357 class A: 1358 def __mro_entries__(self, bases): 1359 return (A1, A2) 1360 class B: 1361 def __mro_entries__(self, bases): 1362 return (B1, B2) 1363 D = types.new_class('D', (A(), B()), {}) 1364 self.assertEqual(D.__bases__, (A1, A2, B1, B2)) 1365 1366 def test_new_class_with_mro_entry_multiple_2(self): 1367 class A1: pass 1368 class A2: pass 1369 class A3: pass 1370 class B1: pass 1371 class B2: pass 1372 class A: 1373 def __mro_entries__(self, bases): 1374 return (A1, A2, A3) 1375 class B: 1376 def __mro_entries__(self, bases): 1377 return (B1, B2) 1378 class C: pass 1379 D = types.new_class('D', (A(), C, B()), {}) 1380 self.assertEqual(D.__bases__, (A1, A2, A3, C, B1, B2)) 1381 1382 # Many of the following tests are derived from test_descr.py 1383 def test_prepare_class(self): 1384 # Basic test of metaclass derivation 1385 expected_ns = {} 1386 class A(type): 1387 def __new__(*args, **kwargs): 1388 return type.__new__(*args, **kwargs) 1389 1390 def __prepare__(*args): 1391 return expected_ns 1392 1393 B = types.new_class("B", (object,)) 1394 C = types.new_class("C", (object,), {"metaclass": A}) 1395 1396 # The most derived metaclass of D is A rather than type. 1397 meta, ns, kwds = types.prepare_class("D", (B, C), {"metaclass": type}) 1398 self.assertIs(meta, A) 1399 self.assertIs(ns, expected_ns) 1400 self.assertEqual(len(kwds), 0) 1401 1402 def test_bad___prepare__(self): 1403 # __prepare__() must return a mapping. 1404 class BadMeta(type): 1405 @classmethod 1406 def __prepare__(*args): 1407 return None 1408 with self.assertRaisesRegex(TypeError, 1409 r'^BadMeta\.__prepare__\(\) must ' 1410 r'return a mapping, not NoneType$'): 1411 class Foo(metaclass=BadMeta): 1412 pass 1413 # Also test the case in which the metaclass is not a type. 1414 class BadMeta: 1415 @classmethod 1416 def __prepare__(*args): 1417 return None 1418 with self.assertRaisesRegex(TypeError, 1419 r'^<metaclass>\.__prepare__\(\) must ' 1420 r'return a mapping, not NoneType$'): 1421 class Bar(metaclass=BadMeta()): 1422 pass 1423 1424 def test_resolve_bases(self): 1425 class A: pass 1426 class B: pass 1427 class C: 1428 def __mro_entries__(self, bases): 1429 if A in bases: 1430 return () 1431 return (A,) 1432 c = C() 1433 self.assertEqual(types.resolve_bases(()), ()) 1434 self.assertEqual(types.resolve_bases((c,)), (A,)) 1435 self.assertEqual(types.resolve_bases((C,)), (C,)) 1436 self.assertEqual(types.resolve_bases((A, C)), (A, C)) 1437 self.assertEqual(types.resolve_bases((c, A)), (A,)) 1438 self.assertEqual(types.resolve_bases((A, c)), (A,)) 1439 x = (A,) 1440 y = (C,) 1441 z = (A, C) 1442 t = (A, C, B) 1443 for bases in [x, y, z, t]: 1444 self.assertIs(types.resolve_bases(bases), bases) 1445 1446 def test_resolve_bases_with_mro_entry(self): 1447 self.assertEqual(types.resolve_bases((typing.List[int],)), 1448 (list, typing.Generic)) 1449 self.assertEqual(types.resolve_bases((list[int],)), (list,)) 1450 1451 def test_metaclass_derivation(self): 1452 # issue1294232: correct metaclass calculation 1453 new_calls = [] # to check the order of __new__ calls 1454 class AMeta(type): 1455 def __new__(mcls, name, bases, ns): 1456 new_calls.append('AMeta') 1457 return super().__new__(mcls, name, bases, ns) 1458 @classmethod 1459 def __prepare__(mcls, name, bases): 1460 return {} 1461 1462 class BMeta(AMeta): 1463 def __new__(mcls, name, bases, ns): 1464 new_calls.append('BMeta') 1465 return super().__new__(mcls, name, bases, ns) 1466 @classmethod 1467 def __prepare__(mcls, name, bases): 1468 ns = super().__prepare__(name, bases) 1469 ns['BMeta_was_here'] = True 1470 return ns 1471 1472 A = types.new_class("A", (), {"metaclass": AMeta}) 1473 self.assertEqual(new_calls, ['AMeta']) 1474 new_calls.clear() 1475 1476 B = types.new_class("B", (), {"metaclass": BMeta}) 1477 # BMeta.__new__ calls AMeta.__new__ with super: 1478 self.assertEqual(new_calls, ['BMeta', 'AMeta']) 1479 new_calls.clear() 1480 1481 C = types.new_class("C", (A, B)) 1482 # The most derived metaclass is BMeta: 1483 self.assertEqual(new_calls, ['BMeta', 'AMeta']) 1484 new_calls.clear() 1485 # BMeta.__prepare__ should've been called: 1486 self.assertIn('BMeta_was_here', C.__dict__) 1487 1488 # The order of the bases shouldn't matter: 1489 C2 = types.new_class("C2", (B, A)) 1490 self.assertEqual(new_calls, ['BMeta', 'AMeta']) 1491 new_calls.clear() 1492 self.assertIn('BMeta_was_here', C2.__dict__) 1493 1494 # Check correct metaclass calculation when a metaclass is declared: 1495 D = types.new_class("D", (C,), {"metaclass": type}) 1496 self.assertEqual(new_calls, ['BMeta', 'AMeta']) 1497 new_calls.clear() 1498 self.assertIn('BMeta_was_here', D.__dict__) 1499 1500 E = types.new_class("E", (C,), {"metaclass": AMeta}) 1501 self.assertEqual(new_calls, ['BMeta', 'AMeta']) 1502 new_calls.clear() 1503 self.assertIn('BMeta_was_here', E.__dict__) 1504 1505 def test_metaclass_override_function(self): 1506 # Special case: the given metaclass isn't a class, 1507 # so there is no metaclass calculation. 1508 class A(metaclass=self.Meta): 1509 pass 1510 1511 marker = object() 1512 def func(*args, **kwargs): 1513 return marker 1514 1515 X = types.new_class("X", (), {"metaclass": func}) 1516 Y = types.new_class("Y", (object,), {"metaclass": func}) 1517 Z = types.new_class("Z", (A,), {"metaclass": func}) 1518 self.assertIs(marker, X) 1519 self.assertIs(marker, Y) 1520 self.assertIs(marker, Z) 1521 1522 def test_metaclass_override_callable(self): 1523 # The given metaclass is a class, 1524 # but not a descendant of type. 1525 new_calls = [] # to check the order of __new__ calls 1526 prepare_calls = [] # to track __prepare__ calls 1527 class ANotMeta: 1528 def __new__(mcls, *args, **kwargs): 1529 new_calls.append('ANotMeta') 1530 return super().__new__(mcls) 1531 @classmethod 1532 def __prepare__(mcls, name, bases): 1533 prepare_calls.append('ANotMeta') 1534 return {} 1535 1536 class BNotMeta(ANotMeta): 1537 def __new__(mcls, *args, **kwargs): 1538 new_calls.append('BNotMeta') 1539 return super().__new__(mcls) 1540 @classmethod 1541 def __prepare__(mcls, name, bases): 1542 prepare_calls.append('BNotMeta') 1543 return super().__prepare__(name, bases) 1544 1545 A = types.new_class("A", (), {"metaclass": ANotMeta}) 1546 self.assertIs(ANotMeta, type(A)) 1547 self.assertEqual(prepare_calls, ['ANotMeta']) 1548 prepare_calls.clear() 1549 self.assertEqual(new_calls, ['ANotMeta']) 1550 new_calls.clear() 1551 1552 B = types.new_class("B", (), {"metaclass": BNotMeta}) 1553 self.assertIs(BNotMeta, type(B)) 1554 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta']) 1555 prepare_calls.clear() 1556 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta']) 1557 new_calls.clear() 1558 1559 C = types.new_class("C", (A, B)) 1560 self.assertIs(BNotMeta, type(C)) 1561 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta']) 1562 prepare_calls.clear() 1563 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta']) 1564 new_calls.clear() 1565 1566 C2 = types.new_class("C2", (B, A)) 1567 self.assertIs(BNotMeta, type(C2)) 1568 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta']) 1569 prepare_calls.clear() 1570 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta']) 1571 new_calls.clear() 1572 1573 # This is a TypeError, because of a metaclass conflict: 1574 # BNotMeta is neither a subclass, nor a superclass of type 1575 with self.assertRaises(TypeError): 1576 D = types.new_class("D", (C,), {"metaclass": type}) 1577 1578 E = types.new_class("E", (C,), {"metaclass": ANotMeta}) 1579 self.assertIs(BNotMeta, type(E)) 1580 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta']) 1581 prepare_calls.clear() 1582 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta']) 1583 new_calls.clear() 1584 1585 F = types.new_class("F", (object(), C)) 1586 self.assertIs(BNotMeta, type(F)) 1587 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta']) 1588 prepare_calls.clear() 1589 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta']) 1590 new_calls.clear() 1591 1592 F2 = types.new_class("F2", (C, object())) 1593 self.assertIs(BNotMeta, type(F2)) 1594 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta']) 1595 prepare_calls.clear() 1596 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta']) 1597 new_calls.clear() 1598 1599 # TypeError: BNotMeta is neither a 1600 # subclass, nor a superclass of int 1601 with self.assertRaises(TypeError): 1602 X = types.new_class("X", (C, int())) 1603 with self.assertRaises(TypeError): 1604 X = types.new_class("X", (int(), C)) 1605 1606 def test_one_argument_type(self): 1607 expected_message = 'type.__new__() takes exactly 3 arguments (1 given)' 1608 1609 # Only type itself can use the one-argument form (#27157) 1610 self.assertIs(type(5), int) 1611 1612 class M(type): 1613 pass 1614 with self.assertRaises(TypeError) as cm: 1615 M(5) 1616 self.assertEqual(str(cm.exception), expected_message) 1617 1618 class N(type, metaclass=M): 1619 pass 1620 with self.assertRaises(TypeError) as cm: 1621 N(5) 1622 self.assertEqual(str(cm.exception), expected_message) 1623 1624 def test_metaclass_new_error(self): 1625 # bpo-44232: The C function type_new() must properly report the 1626 # exception when a metaclass constructor raises an exception and the 1627 # winner class is not the metaclass. 1628 class ModelBase(type): 1629 def __new__(cls, name, bases, attrs): 1630 super_new = super().__new__ 1631 new_class = super_new(cls, name, bases, {}) 1632 if name != "Model": 1633 raise RuntimeWarning(f"{name=}") 1634 return new_class 1635 1636 class Model(metaclass=ModelBase): 1637 pass 1638 1639 with self.assertRaises(RuntimeWarning): 1640 type("SouthPonies", (Model,), {}) 1641 1642 1643class SimpleNamespaceTests(unittest.TestCase): 1644 1645 def test_constructor(self): 1646 ns1 = types.SimpleNamespace() 1647 ns2 = types.SimpleNamespace(x=1, y=2) 1648 ns3 = types.SimpleNamespace(**dict(x=1, y=2)) 1649 1650 with self.assertRaises(TypeError): 1651 types.SimpleNamespace(1, 2, 3) 1652 with self.assertRaises(TypeError): 1653 types.SimpleNamespace(**{1: 2}) 1654 1655 self.assertEqual(len(ns1.__dict__), 0) 1656 self.assertEqual(vars(ns1), {}) 1657 self.assertEqual(len(ns2.__dict__), 2) 1658 self.assertEqual(vars(ns2), {'y': 2, 'x': 1}) 1659 self.assertEqual(len(ns3.__dict__), 2) 1660 self.assertEqual(vars(ns3), {'y': 2, 'x': 1}) 1661 1662 def test_unbound(self): 1663 ns1 = vars(types.SimpleNamespace()) 1664 ns2 = vars(types.SimpleNamespace(x=1, y=2)) 1665 1666 self.assertEqual(ns1, {}) 1667 self.assertEqual(ns2, {'y': 2, 'x': 1}) 1668 1669 def test_underlying_dict(self): 1670 ns1 = types.SimpleNamespace() 1671 ns2 = types.SimpleNamespace(x=1, y=2) 1672 ns3 = types.SimpleNamespace(a=True, b=False) 1673 mapping = ns3.__dict__ 1674 del ns3 1675 1676 self.assertEqual(ns1.__dict__, {}) 1677 self.assertEqual(ns2.__dict__, {'y': 2, 'x': 1}) 1678 self.assertEqual(mapping, dict(a=True, b=False)) 1679 1680 def test_attrget(self): 1681 ns = types.SimpleNamespace(x=1, y=2, w=3) 1682 1683 self.assertEqual(ns.x, 1) 1684 self.assertEqual(ns.y, 2) 1685 self.assertEqual(ns.w, 3) 1686 with self.assertRaises(AttributeError): 1687 ns.z 1688 1689 def test_attrset(self): 1690 ns1 = types.SimpleNamespace() 1691 ns2 = types.SimpleNamespace(x=1, y=2, w=3) 1692 ns1.a = 'spam' 1693 ns1.b = 'ham' 1694 ns2.z = 4 1695 ns2.theta = None 1696 1697 self.assertEqual(ns1.__dict__, dict(a='spam', b='ham')) 1698 self.assertEqual(ns2.__dict__, dict(x=1, y=2, w=3, z=4, theta=None)) 1699 1700 def test_attrdel(self): 1701 ns1 = types.SimpleNamespace() 1702 ns2 = types.SimpleNamespace(x=1, y=2, w=3) 1703 1704 with self.assertRaises(AttributeError): 1705 del ns1.spam 1706 with self.assertRaises(AttributeError): 1707 del ns2.spam 1708 1709 del ns2.y 1710 self.assertEqual(vars(ns2), dict(w=3, x=1)) 1711 ns2.y = 'spam' 1712 self.assertEqual(vars(ns2), dict(w=3, x=1, y='spam')) 1713 del ns2.y 1714 self.assertEqual(vars(ns2), dict(w=3, x=1)) 1715 1716 ns1.spam = 5 1717 self.assertEqual(vars(ns1), dict(spam=5)) 1718 del ns1.spam 1719 self.assertEqual(vars(ns1), {}) 1720 1721 def test_repr(self): 1722 ns1 = types.SimpleNamespace(x=1, y=2, w=3) 1723 ns2 = types.SimpleNamespace() 1724 ns2.x = "spam" 1725 ns2._y = 5 1726 name = "namespace" 1727 1728 self.assertEqual(repr(ns1), "{name}(x=1, y=2, w=3)".format(name=name)) 1729 self.assertEqual(repr(ns2), "{name}(x='spam', _y=5)".format(name=name)) 1730 1731 def test_equal(self): 1732 ns1 = types.SimpleNamespace(x=1) 1733 ns2 = types.SimpleNamespace() 1734 ns2.x = 1 1735 1736 self.assertEqual(types.SimpleNamespace(), types.SimpleNamespace()) 1737 self.assertEqual(ns1, ns2) 1738 self.assertNotEqual(ns2, types.SimpleNamespace()) 1739 1740 def test_nested(self): 1741 ns1 = types.SimpleNamespace(a=1, b=2) 1742 ns2 = types.SimpleNamespace() 1743 ns3 = types.SimpleNamespace(x=ns1) 1744 ns2.spam = ns1 1745 ns2.ham = '?' 1746 ns2.spam = ns3 1747 1748 self.assertEqual(vars(ns1), dict(a=1, b=2)) 1749 self.assertEqual(vars(ns2), dict(spam=ns3, ham='?')) 1750 self.assertEqual(ns2.spam, ns3) 1751 self.assertEqual(vars(ns3), dict(x=ns1)) 1752 self.assertEqual(ns3.x.a, 1) 1753 1754 def test_recursive(self): 1755 ns1 = types.SimpleNamespace(c='cookie') 1756 ns2 = types.SimpleNamespace() 1757 ns3 = types.SimpleNamespace(x=1) 1758 ns1.spam = ns1 1759 ns2.spam = ns3 1760 ns3.spam = ns2 1761 1762 self.assertEqual(ns1.spam, ns1) 1763 self.assertEqual(ns1.spam.spam, ns1) 1764 self.assertEqual(ns1.spam.spam, ns1.spam) 1765 self.assertEqual(ns2.spam, ns3) 1766 self.assertEqual(ns3.spam, ns2) 1767 self.assertEqual(ns2.spam.spam, ns2) 1768 1769 def test_recursive_repr(self): 1770 ns1 = types.SimpleNamespace(c='cookie') 1771 ns2 = types.SimpleNamespace() 1772 ns3 = types.SimpleNamespace(x=1) 1773 ns1.spam = ns1 1774 ns2.spam = ns3 1775 ns3.spam = ns2 1776 name = "namespace" 1777 repr1 = "{name}(c='cookie', spam={name}(...))".format(name=name) 1778 repr2 = "{name}(spam={name}(x=1, spam={name}(...)))".format(name=name) 1779 1780 self.assertEqual(repr(ns1), repr1) 1781 self.assertEqual(repr(ns2), repr2) 1782 1783 def test_as_dict(self): 1784 ns = types.SimpleNamespace(spam='spamspamspam') 1785 1786 with self.assertRaises(TypeError): 1787 len(ns) 1788 with self.assertRaises(TypeError): 1789 iter(ns) 1790 with self.assertRaises(TypeError): 1791 'spam' in ns 1792 with self.assertRaises(TypeError): 1793 ns['spam'] 1794 1795 def test_subclass(self): 1796 class Spam(types.SimpleNamespace): 1797 pass 1798 1799 spam = Spam(ham=8, eggs=9) 1800 1801 self.assertIs(type(spam), Spam) 1802 self.assertEqual(vars(spam), {'ham': 8, 'eggs': 9}) 1803 1804 def test_pickle(self): 1805 ns = types.SimpleNamespace(breakfast="spam", lunch="spam") 1806 1807 for protocol in range(pickle.HIGHEST_PROTOCOL + 1): 1808 pname = "protocol {}".format(protocol) 1809 try: 1810 ns_pickled = pickle.dumps(ns, protocol) 1811 except TypeError as e: 1812 raise TypeError(pname) from e 1813 ns_roundtrip = pickle.loads(ns_pickled) 1814 1815 self.assertEqual(ns, ns_roundtrip, pname) 1816 1817 def test_fake_namespace_compare(self): 1818 # Issue #24257: Incorrect use of PyObject_IsInstance() caused 1819 # SystemError. 1820 class FakeSimpleNamespace(str): 1821 __class__ = types.SimpleNamespace 1822 self.assertFalse(types.SimpleNamespace() == FakeSimpleNamespace()) 1823 self.assertTrue(types.SimpleNamespace() != FakeSimpleNamespace()) 1824 with self.assertRaises(TypeError): 1825 types.SimpleNamespace() < FakeSimpleNamespace() 1826 with self.assertRaises(TypeError): 1827 types.SimpleNamespace() <= FakeSimpleNamespace() 1828 with self.assertRaises(TypeError): 1829 types.SimpleNamespace() > FakeSimpleNamespace() 1830 with self.assertRaises(TypeError): 1831 types.SimpleNamespace() >= FakeSimpleNamespace() 1832 1833 1834class CoroutineTests(unittest.TestCase): 1835 def test_wrong_args(self): 1836 samples = [None, 1, object()] 1837 for sample in samples: 1838 with self.assertRaisesRegex(TypeError, 1839 'types.coroutine.*expects a callable'): 1840 types.coroutine(sample) 1841 1842 def test_non_gen_values(self): 1843 @types.coroutine 1844 def foo(): 1845 return 'spam' 1846 self.assertEqual(foo(), 'spam') 1847 1848 class Awaitable: 1849 def __await__(self): 1850 return () 1851 aw = Awaitable() 1852 @types.coroutine 1853 def foo(): 1854 return aw 1855 self.assertIs(aw, foo()) 1856 1857 # decorate foo second time 1858 foo = types.coroutine(foo) 1859 self.assertIs(aw, foo()) 1860 1861 def test_async_def(self): 1862 # Test that types.coroutine passes 'async def' coroutines 1863 # without modification 1864 1865 async def foo(): pass 1866 foo_code = foo.__code__ 1867 foo_flags = foo.__code__.co_flags 1868 decorated_foo = types.coroutine(foo) 1869 self.assertIs(foo, decorated_foo) 1870 self.assertEqual(foo.__code__.co_flags, foo_flags) 1871 self.assertIs(decorated_foo.__code__, foo_code) 1872 1873 foo_coro = foo() 1874 def bar(): return foo_coro 1875 for _ in range(2): 1876 bar = types.coroutine(bar) 1877 coro = bar() 1878 self.assertIs(foo_coro, coro) 1879 self.assertEqual(coro.cr_code.co_flags, foo_flags) 1880 coro.close() 1881 1882 def test_duck_coro(self): 1883 class CoroLike: 1884 def send(self): pass 1885 def throw(self): pass 1886 def close(self): pass 1887 def __await__(self): return self 1888 1889 coro = CoroLike() 1890 @types.coroutine 1891 def foo(): 1892 return coro 1893 self.assertIs(foo(), coro) 1894 self.assertIs(foo().__await__(), coro) 1895 1896 def test_duck_corogen(self): 1897 class CoroGenLike: 1898 def send(self): pass 1899 def throw(self): pass 1900 def close(self): pass 1901 def __await__(self): return self 1902 def __iter__(self): return self 1903 def __next__(self): pass 1904 1905 coro = CoroGenLike() 1906 @types.coroutine 1907 def foo(): 1908 return coro 1909 self.assertIs(foo(), coro) 1910 self.assertIs(foo().__await__(), coro) 1911 1912 def test_duck_gen(self): 1913 class GenLike: 1914 def send(self): pass 1915 def throw(self): pass 1916 def close(self): pass 1917 def __iter__(self): pass 1918 def __next__(self): pass 1919 1920 # Setup generator mock object 1921 gen = unittest.mock.MagicMock(GenLike) 1922 gen.__iter__ = lambda gen: gen 1923 gen.__name__ = 'gen' 1924 gen.__qualname__ = 'test.gen' 1925 self.assertIsInstance(gen, collections.abc.Generator) 1926 self.assertIs(gen, iter(gen)) 1927 1928 @types.coroutine 1929 def foo(): return gen 1930 1931 wrapper = foo() 1932 self.assertIsInstance(wrapper, types._GeneratorWrapper) 1933 self.assertIs(wrapper.__await__(), wrapper) 1934 # Wrapper proxies duck generators completely: 1935 self.assertIs(iter(wrapper), wrapper) 1936 1937 self.assertIsInstance(wrapper, collections.abc.Coroutine) 1938 self.assertIsInstance(wrapper, collections.abc.Awaitable) 1939 1940 self.assertIs(wrapper.__qualname__, gen.__qualname__) 1941 self.assertIs(wrapper.__name__, gen.__name__) 1942 1943 # Test AttributeErrors 1944 for name in {'gi_running', 'gi_frame', 'gi_code', 'gi_yieldfrom', 1945 'cr_running', 'cr_frame', 'cr_code', 'cr_await'}: 1946 with self.assertRaises(AttributeError): 1947 getattr(wrapper, name) 1948 1949 # Test attributes pass-through 1950 gen.gi_running = object() 1951 gen.gi_frame = object() 1952 gen.gi_code = object() 1953 gen.gi_yieldfrom = object() 1954 self.assertIs(wrapper.gi_running, gen.gi_running) 1955 self.assertIs(wrapper.gi_frame, gen.gi_frame) 1956 self.assertIs(wrapper.gi_code, gen.gi_code) 1957 self.assertIs(wrapper.gi_yieldfrom, gen.gi_yieldfrom) 1958 self.assertIs(wrapper.cr_running, gen.gi_running) 1959 self.assertIs(wrapper.cr_frame, gen.gi_frame) 1960 self.assertIs(wrapper.cr_code, gen.gi_code) 1961 self.assertIs(wrapper.cr_await, gen.gi_yieldfrom) 1962 1963 wrapper.close() 1964 gen.close.assert_called_once_with() 1965 1966 wrapper.send(1) 1967 gen.send.assert_called_once_with(1) 1968 gen.reset_mock() 1969 1970 next(wrapper) 1971 gen.__next__.assert_called_once_with() 1972 gen.reset_mock() 1973 1974 wrapper.throw(1, 2, 3) 1975 gen.throw.assert_called_once_with(1, 2, 3) 1976 gen.reset_mock() 1977 1978 wrapper.throw(1, 2) 1979 gen.throw.assert_called_once_with(1, 2) 1980 gen.reset_mock() 1981 1982 wrapper.throw(1) 1983 gen.throw.assert_called_once_with(1) 1984 gen.reset_mock() 1985 1986 # Test exceptions propagation 1987 error = Exception() 1988 gen.throw.side_effect = error 1989 try: 1990 wrapper.throw(1) 1991 except Exception as ex: 1992 self.assertIs(ex, error) 1993 else: 1994 self.fail('wrapper did not propagate an exception') 1995 1996 # Test invalid args 1997 gen.reset_mock() 1998 with self.assertRaises(TypeError): 1999 wrapper.throw() 2000 self.assertFalse(gen.throw.called) 2001 with self.assertRaises(TypeError): 2002 wrapper.close(1) 2003 self.assertFalse(gen.close.called) 2004 with self.assertRaises(TypeError): 2005 wrapper.send() 2006 self.assertFalse(gen.send.called) 2007 2008 # Test that we do not double wrap 2009 @types.coroutine 2010 def bar(): return wrapper 2011 self.assertIs(wrapper, bar()) 2012 2013 # Test weakrefs support 2014 ref = weakref.ref(wrapper) 2015 self.assertIs(ref(), wrapper) 2016 2017 def test_duck_functional_gen(self): 2018 class Generator: 2019 """Emulates the following generator (very clumsy): 2020 2021 def gen(fut): 2022 result = yield fut 2023 return result * 2 2024 """ 2025 def __init__(self, fut): 2026 self._i = 0 2027 self._fut = fut 2028 def __iter__(self): 2029 return self 2030 def __next__(self): 2031 return self.send(None) 2032 def send(self, v): 2033 try: 2034 if self._i == 0: 2035 assert v is None 2036 return self._fut 2037 if self._i == 1: 2038 raise StopIteration(v * 2) 2039 if self._i > 1: 2040 raise StopIteration 2041 finally: 2042 self._i += 1 2043 def throw(self, tp, *exc): 2044 self._i = 100 2045 if tp is not GeneratorExit: 2046 raise tp 2047 def close(self): 2048 self.throw(GeneratorExit) 2049 2050 @types.coroutine 2051 def foo(): return Generator('spam') 2052 2053 wrapper = foo() 2054 self.assertIsInstance(wrapper, types._GeneratorWrapper) 2055 2056 async def corofunc(): 2057 return await foo() + 100 2058 coro = corofunc() 2059 2060 self.assertEqual(coro.send(None), 'spam') 2061 try: 2062 coro.send(20) 2063 except StopIteration as ex: 2064 self.assertEqual(ex.args[0], 140) 2065 else: 2066 self.fail('StopIteration was expected') 2067 2068 def test_gen(self): 2069 def gen_func(): 2070 yield 1 2071 return (yield 2) 2072 gen = gen_func() 2073 @types.coroutine 2074 def foo(): return gen 2075 wrapper = foo() 2076 self.assertIsInstance(wrapper, types._GeneratorWrapper) 2077 self.assertIs(wrapper.__await__(), gen) 2078 2079 for name in ('__name__', '__qualname__', 'gi_code', 2080 'gi_running', 'gi_frame'): 2081 self.assertIs(getattr(foo(), name), 2082 getattr(gen, name)) 2083 self.assertIs(foo().cr_code, gen.gi_code) 2084 2085 self.assertEqual(next(wrapper), 1) 2086 self.assertEqual(wrapper.send(None), 2) 2087 with self.assertRaisesRegex(StopIteration, 'spam'): 2088 wrapper.send('spam') 2089 2090 gen = gen_func() 2091 wrapper = foo() 2092 wrapper.send(None) 2093 with self.assertRaisesRegex(Exception, 'ham'): 2094 wrapper.throw(Exception, Exception('ham')) 2095 2096 # decorate foo second time 2097 foo = types.coroutine(foo) 2098 self.assertIs(foo().__await__(), gen) 2099 2100 def test_returning_itercoro(self): 2101 @types.coroutine 2102 def gen(): 2103 yield 2104 2105 gencoro = gen() 2106 2107 @types.coroutine 2108 def foo(): 2109 return gencoro 2110 2111 self.assertIs(foo(), gencoro) 2112 2113 # decorate foo second time 2114 foo = types.coroutine(foo) 2115 self.assertIs(foo(), gencoro) 2116 2117 def test_genfunc(self): 2118 def gen(): yield 2119 self.assertIs(types.coroutine(gen), gen) 2120 self.assertIs(types.coroutine(types.coroutine(gen)), gen) 2121 2122 self.assertTrue(gen.__code__.co_flags & inspect.CO_ITERABLE_COROUTINE) 2123 self.assertFalse(gen.__code__.co_flags & inspect.CO_COROUTINE) 2124 2125 g = gen() 2126 self.assertTrue(g.gi_code.co_flags & inspect.CO_ITERABLE_COROUTINE) 2127 self.assertFalse(g.gi_code.co_flags & inspect.CO_COROUTINE) 2128 2129 self.assertIs(types.coroutine(gen), gen) 2130 2131 def test_wrapper_object(self): 2132 def gen(): 2133 yield 2134 @types.coroutine 2135 def coro(): 2136 return gen() 2137 2138 wrapper = coro() 2139 self.assertIn('GeneratorWrapper', repr(wrapper)) 2140 self.assertEqual(repr(wrapper), str(wrapper)) 2141 self.assertTrue(set(dir(wrapper)).issuperset({ 2142 '__await__', '__iter__', '__next__', 'cr_code', 'cr_running', 2143 'cr_frame', 'gi_code', 'gi_frame', 'gi_running', 'send', 2144 'close', 'throw'})) 2145 2146 2147if __name__ == '__main__': 2148 unittest.main() 2149