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