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