1from test import support 2from test.support.script_helper import assert_python_ok, assert_python_failure 3import builtins 4import codecs 5import gc 6import locale 7import operator 8import os 9import struct 10import subprocess 11import sys 12import sysconfig 13import test.support 14import textwrap 15import unittest 16import warnings 17 18 19# count the number of test runs, used to create unique 20# strings to intern in test_intern() 21INTERN_NUMRUNS = 0 22 23 24class DisplayHookTest(unittest.TestCase): 25 26 def test_original_displayhook(self): 27 dh = sys.__displayhook__ 28 29 with support.captured_stdout() as out: 30 dh(42) 31 32 self.assertEqual(out.getvalue(), "42\n") 33 self.assertEqual(builtins._, 42) 34 35 del builtins._ 36 37 with support.captured_stdout() as out: 38 dh(None) 39 40 self.assertEqual(out.getvalue(), "") 41 self.assertTrue(not hasattr(builtins, "_")) 42 43 # sys.displayhook() requires arguments 44 self.assertRaises(TypeError, dh) 45 46 stdout = sys.stdout 47 try: 48 del sys.stdout 49 self.assertRaises(RuntimeError, dh, 42) 50 finally: 51 sys.stdout = stdout 52 53 def test_lost_displayhook(self): 54 displayhook = sys.displayhook 55 try: 56 del sys.displayhook 57 code = compile("42", "<string>", "single") 58 self.assertRaises(RuntimeError, eval, code) 59 finally: 60 sys.displayhook = displayhook 61 62 def test_custom_displayhook(self): 63 def baddisplayhook(obj): 64 raise ValueError 65 66 with support.swap_attr(sys, 'displayhook', baddisplayhook): 67 code = compile("42", "<string>", "single") 68 self.assertRaises(ValueError, eval, code) 69 70 71class ExceptHookTest(unittest.TestCase): 72 73 def test_original_excepthook(self): 74 try: 75 raise ValueError(42) 76 except ValueError as exc: 77 with support.captured_stderr() as err: 78 sys.__excepthook__(*sys.exc_info()) 79 80 self.assertTrue(err.getvalue().endswith("ValueError: 42\n")) 81 82 self.assertRaises(TypeError, sys.__excepthook__) 83 84 def test_excepthook_bytes_filename(self): 85 # bpo-37467: sys.excepthook() must not crash if a filename 86 # is a bytes string 87 with warnings.catch_warnings(): 88 warnings.simplefilter('ignore', BytesWarning) 89 90 try: 91 raise SyntaxError("msg", (b"bytes_filename", 123, 0, "text")) 92 except SyntaxError as exc: 93 with support.captured_stderr() as err: 94 sys.__excepthook__(*sys.exc_info()) 95 96 err = err.getvalue() 97 self.assertIn(""" File "b'bytes_filename'", line 123\n""", err) 98 self.assertIn(""" text\n""", err) 99 self.assertTrue(err.endswith("SyntaxError: msg\n")) 100 101 def test_excepthook(self): 102 with test.support.captured_output("stderr") as stderr: 103 sys.excepthook(1, '1', 1) 104 self.assertTrue("TypeError: print_exception(): Exception expected for " \ 105 "value, str found" in stderr.getvalue()) 106 107 # FIXME: testing the code for a lost or replaced excepthook in 108 # Python/pythonrun.c::PyErr_PrintEx() is tricky. 109 110 111class SysModuleTest(unittest.TestCase): 112 113 def tearDown(self): 114 test.support.reap_children() 115 116 def test_exit(self): 117 # call with two arguments 118 self.assertRaises(TypeError, sys.exit, 42, 42) 119 120 # call without argument 121 with self.assertRaises(SystemExit) as cm: 122 sys.exit() 123 self.assertIsNone(cm.exception.code) 124 125 rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') 126 self.assertEqual(rc, 0) 127 self.assertEqual(out, b'') 128 self.assertEqual(err, b'') 129 130 # call with integer argument 131 with self.assertRaises(SystemExit) as cm: 132 sys.exit(42) 133 self.assertEqual(cm.exception.code, 42) 134 135 # call with tuple argument with one entry 136 # entry will be unpacked 137 with self.assertRaises(SystemExit) as cm: 138 sys.exit((42,)) 139 self.assertEqual(cm.exception.code, 42) 140 141 # call with string argument 142 with self.assertRaises(SystemExit) as cm: 143 sys.exit("exit") 144 self.assertEqual(cm.exception.code, "exit") 145 146 # call with tuple argument with two entries 147 with self.assertRaises(SystemExit) as cm: 148 sys.exit((17, 23)) 149 self.assertEqual(cm.exception.code, (17, 23)) 150 151 # test that the exit machinery handles SystemExits properly 152 rc, out, err = assert_python_failure('-c', 'raise SystemExit(47)') 153 self.assertEqual(rc, 47) 154 self.assertEqual(out, b'') 155 self.assertEqual(err, b'') 156 157 def check_exit_message(code, expected, **env_vars): 158 rc, out, err = assert_python_failure('-c', code, **env_vars) 159 self.assertEqual(rc, 1) 160 self.assertEqual(out, b'') 161 self.assertTrue(err.startswith(expected), 162 "%s doesn't start with %s" % (ascii(err), ascii(expected))) 163 164 # test that stderr buffer is flushed before the exit message is written 165 # into stderr 166 check_exit_message( 167 r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")', 168 b"unflushed,message") 169 170 # test that the exit message is written with backslashreplace error 171 # handler to stderr 172 check_exit_message( 173 r'import sys; sys.exit("surrogates:\uDCFF")', 174 b"surrogates:\\udcff") 175 176 # test that the unicode message is encoded to the stderr encoding 177 # instead of the default encoding (utf8) 178 check_exit_message( 179 r'import sys; sys.exit("h\xe9")', 180 b"h\xe9", PYTHONIOENCODING='latin-1') 181 182 def test_getdefaultencoding(self): 183 self.assertRaises(TypeError, sys.getdefaultencoding, 42) 184 # can't check more than the type, as the user might have changed it 185 self.assertIsInstance(sys.getdefaultencoding(), str) 186 187 # testing sys.settrace() is done in test_sys_settrace.py 188 # testing sys.setprofile() is done in test_sys_setprofile.py 189 190 def test_setcheckinterval(self): 191 with warnings.catch_warnings(): 192 warnings.simplefilter("ignore") 193 self.assertRaises(TypeError, sys.setcheckinterval) 194 orig = sys.getcheckinterval() 195 for n in 0, 100, 120, orig: # orig last to restore starting state 196 sys.setcheckinterval(n) 197 self.assertEqual(sys.getcheckinterval(), n) 198 199 def test_switchinterval(self): 200 self.assertRaises(TypeError, sys.setswitchinterval) 201 self.assertRaises(TypeError, sys.setswitchinterval, "a") 202 self.assertRaises(ValueError, sys.setswitchinterval, -1.0) 203 self.assertRaises(ValueError, sys.setswitchinterval, 0.0) 204 orig = sys.getswitchinterval() 205 # sanity check 206 self.assertTrue(orig < 0.5, orig) 207 try: 208 for n in 0.00001, 0.05, 3.0, orig: 209 sys.setswitchinterval(n) 210 self.assertAlmostEqual(sys.getswitchinterval(), n) 211 finally: 212 sys.setswitchinterval(orig) 213 214 def test_recursionlimit(self): 215 self.assertRaises(TypeError, sys.getrecursionlimit, 42) 216 oldlimit = sys.getrecursionlimit() 217 self.assertRaises(TypeError, sys.setrecursionlimit) 218 self.assertRaises(ValueError, sys.setrecursionlimit, -42) 219 sys.setrecursionlimit(10000) 220 self.assertEqual(sys.getrecursionlimit(), 10000) 221 sys.setrecursionlimit(oldlimit) 222 223 def test_recursionlimit_recovery(self): 224 if hasattr(sys, 'gettrace') and sys.gettrace(): 225 self.skipTest('fatal error if run with a trace function') 226 227 oldlimit = sys.getrecursionlimit() 228 def f(): 229 f() 230 try: 231 for depth in (10, 25, 50, 75, 100, 250, 1000): 232 try: 233 sys.setrecursionlimit(depth) 234 except RecursionError: 235 # Issue #25274: The recursion limit is too low at the 236 # current recursion depth 237 continue 238 239 # Issue #5392: test stack overflow after hitting recursion 240 # limit twice 241 self.assertRaises(RecursionError, f) 242 self.assertRaises(RecursionError, f) 243 finally: 244 sys.setrecursionlimit(oldlimit) 245 246 @test.support.cpython_only 247 def test_setrecursionlimit_recursion_depth(self): 248 # Issue #25274: Setting a low recursion limit must be blocked if the 249 # current recursion depth is already higher than the "lower-water 250 # mark". Otherwise, it may not be possible anymore to 251 # reset the overflowed flag to 0. 252 253 from _testcapi import get_recursion_depth 254 255 def set_recursion_limit_at_depth(depth, limit): 256 recursion_depth = get_recursion_depth() 257 if recursion_depth >= depth: 258 with self.assertRaises(RecursionError) as cm: 259 sys.setrecursionlimit(limit) 260 self.assertRegex(str(cm.exception), 261 "cannot set the recursion limit to [0-9]+ " 262 "at the recursion depth [0-9]+: " 263 "the limit is too low") 264 else: 265 set_recursion_limit_at_depth(depth, limit) 266 267 oldlimit = sys.getrecursionlimit() 268 try: 269 sys.setrecursionlimit(1000) 270 271 for limit in (10, 25, 50, 75, 100, 150, 200): 272 # formula extracted from _Py_RecursionLimitLowerWaterMark() 273 if limit > 200: 274 depth = limit - 50 275 else: 276 depth = limit * 3 // 4 277 set_recursion_limit_at_depth(depth, limit) 278 finally: 279 sys.setrecursionlimit(oldlimit) 280 281 def test_recursionlimit_fatalerror(self): 282 # A fatal error occurs if a second recursion limit is hit when recovering 283 # from a first one. 284 code = textwrap.dedent(""" 285 import sys 286 287 def f(): 288 try: 289 f() 290 except RecursionError: 291 f() 292 293 sys.setrecursionlimit(%d) 294 f()""") 295 with test.support.SuppressCrashReport(): 296 for i in (50, 1000): 297 sub = subprocess.Popen([sys.executable, '-c', code % i], 298 stderr=subprocess.PIPE) 299 err = sub.communicate()[1] 300 self.assertTrue(sub.returncode, sub.returncode) 301 self.assertIn( 302 b"Fatal Python error: Cannot recover from stack overflow", 303 err) 304 305 def test_getwindowsversion(self): 306 # Raise SkipTest if sys doesn't have getwindowsversion attribute 307 test.support.get_attribute(sys, "getwindowsversion") 308 v = sys.getwindowsversion() 309 self.assertEqual(len(v), 5) 310 self.assertIsInstance(v[0], int) 311 self.assertIsInstance(v[1], int) 312 self.assertIsInstance(v[2], int) 313 self.assertIsInstance(v[3], int) 314 self.assertIsInstance(v[4], str) 315 self.assertRaises(IndexError, operator.getitem, v, 5) 316 self.assertIsInstance(v.major, int) 317 self.assertIsInstance(v.minor, int) 318 self.assertIsInstance(v.build, int) 319 self.assertIsInstance(v.platform, int) 320 self.assertIsInstance(v.service_pack, str) 321 self.assertIsInstance(v.service_pack_minor, int) 322 self.assertIsInstance(v.service_pack_major, int) 323 self.assertIsInstance(v.suite_mask, int) 324 self.assertIsInstance(v.product_type, int) 325 self.assertEqual(v[0], v.major) 326 self.assertEqual(v[1], v.minor) 327 self.assertEqual(v[2], v.build) 328 self.assertEqual(v[3], v.platform) 329 self.assertEqual(v[4], v.service_pack) 330 331 # This is how platform.py calls it. Make sure tuple 332 # still has 5 elements 333 maj, min, buildno, plat, csd = sys.getwindowsversion() 334 335 def test_call_tracing(self): 336 self.assertRaises(TypeError, sys.call_tracing, type, 2) 337 338 @unittest.skipUnless(hasattr(sys, "setdlopenflags"), 339 'test needs sys.setdlopenflags()') 340 def test_dlopenflags(self): 341 self.assertTrue(hasattr(sys, "getdlopenflags")) 342 self.assertRaises(TypeError, sys.getdlopenflags, 42) 343 oldflags = sys.getdlopenflags() 344 self.assertRaises(TypeError, sys.setdlopenflags) 345 sys.setdlopenflags(oldflags+1) 346 self.assertEqual(sys.getdlopenflags(), oldflags+1) 347 sys.setdlopenflags(oldflags) 348 349 @test.support.refcount_test 350 def test_refcount(self): 351 # n here must be a global in order for this test to pass while 352 # tracing with a python function. Tracing calls PyFrame_FastToLocals 353 # which will add a copy of any locals to the frame object, causing 354 # the reference count to increase by 2 instead of 1. 355 global n 356 self.assertRaises(TypeError, sys.getrefcount) 357 c = sys.getrefcount(None) 358 n = None 359 self.assertEqual(sys.getrefcount(None), c+1) 360 del n 361 self.assertEqual(sys.getrefcount(None), c) 362 if hasattr(sys, "gettotalrefcount"): 363 self.assertIsInstance(sys.gettotalrefcount(), int) 364 365 def test_getframe(self): 366 self.assertRaises(TypeError, sys._getframe, 42, 42) 367 self.assertRaises(ValueError, sys._getframe, 2000000000) 368 self.assertTrue( 369 SysModuleTest.test_getframe.__code__ \ 370 is sys._getframe().f_code 371 ) 372 373 # sys._current_frames() is a CPython-only gimmick. 374 @test.support.reap_threads 375 def test_current_frames(self): 376 import threading 377 import traceback 378 379 # Spawn a thread that blocks at a known place. Then the main 380 # thread does sys._current_frames(), and verifies that the frames 381 # returned make sense. 382 entered_g = threading.Event() 383 leave_g = threading.Event() 384 thread_info = [] # the thread's id 385 386 def f123(): 387 g456() 388 389 def g456(): 390 thread_info.append(threading.get_ident()) 391 entered_g.set() 392 leave_g.wait() 393 394 t = threading.Thread(target=f123) 395 t.start() 396 entered_g.wait() 397 398 # At this point, t has finished its entered_g.set(), although it's 399 # impossible to guess whether it's still on that line or has moved on 400 # to its leave_g.wait(). 401 self.assertEqual(len(thread_info), 1) 402 thread_id = thread_info[0] 403 404 d = sys._current_frames() 405 for tid in d: 406 self.assertIsInstance(tid, int) 407 self.assertGreater(tid, 0) 408 409 main_id = threading.get_ident() 410 self.assertIn(main_id, d) 411 self.assertIn(thread_id, d) 412 413 # Verify that the captured main-thread frame is _this_ frame. 414 frame = d.pop(main_id) 415 self.assertTrue(frame is sys._getframe()) 416 417 # Verify that the captured thread frame is blocked in g456, called 418 # from f123. This is a litte tricky, since various bits of 419 # threading.py are also in the thread's call stack. 420 frame = d.pop(thread_id) 421 stack = traceback.extract_stack(frame) 422 for i, (filename, lineno, funcname, sourceline) in enumerate(stack): 423 if funcname == "f123": 424 break 425 else: 426 self.fail("didn't find f123() on thread's call stack") 427 428 self.assertEqual(sourceline, "g456()") 429 430 # And the next record must be for g456(). 431 filename, lineno, funcname, sourceline = stack[i+1] 432 self.assertEqual(funcname, "g456") 433 self.assertIn(sourceline, ["leave_g.wait()", "entered_g.set()"]) 434 435 # Reap the spawned thread. 436 leave_g.set() 437 t.join() 438 439 def test_attributes(self): 440 self.assertIsInstance(sys.api_version, int) 441 self.assertIsInstance(sys.argv, list) 442 self.assertIn(sys.byteorder, ("little", "big")) 443 self.assertIsInstance(sys.builtin_module_names, tuple) 444 self.assertIsInstance(sys.copyright, str) 445 self.assertIsInstance(sys.exec_prefix, str) 446 self.assertIsInstance(sys.base_exec_prefix, str) 447 self.assertIsInstance(sys.executable, str) 448 self.assertEqual(len(sys.float_info), 11) 449 self.assertEqual(sys.float_info.radix, 2) 450 self.assertEqual(len(sys.int_info), 2) 451 self.assertTrue(sys.int_info.bits_per_digit % 5 == 0) 452 self.assertTrue(sys.int_info.sizeof_digit >= 1) 453 self.assertEqual(type(sys.int_info.bits_per_digit), int) 454 self.assertEqual(type(sys.int_info.sizeof_digit), int) 455 self.assertIsInstance(sys.hexversion, int) 456 457 self.assertEqual(len(sys.hash_info), 9) 458 self.assertLess(sys.hash_info.modulus, 2**sys.hash_info.width) 459 # sys.hash_info.modulus should be a prime; we do a quick 460 # probable primality test (doesn't exclude the possibility of 461 # a Carmichael number) 462 for x in range(1, 100): 463 self.assertEqual( 464 pow(x, sys.hash_info.modulus-1, sys.hash_info.modulus), 465 1, 466 "sys.hash_info.modulus {} is a non-prime".format( 467 sys.hash_info.modulus) 468 ) 469 self.assertIsInstance(sys.hash_info.inf, int) 470 self.assertIsInstance(sys.hash_info.nan, int) 471 self.assertIsInstance(sys.hash_info.imag, int) 472 algo = sysconfig.get_config_var("Py_HASH_ALGORITHM") 473 if sys.hash_info.algorithm in {"fnv", "siphash24"}: 474 self.assertIn(sys.hash_info.hash_bits, {32, 64}) 475 self.assertIn(sys.hash_info.seed_bits, {32, 64, 128}) 476 477 if algo == 1: 478 self.assertEqual(sys.hash_info.algorithm, "siphash24") 479 elif algo == 2: 480 self.assertEqual(sys.hash_info.algorithm, "fnv") 481 else: 482 self.assertIn(sys.hash_info.algorithm, {"fnv", "siphash24"}) 483 else: 484 # PY_HASH_EXTERNAL 485 self.assertEqual(algo, 0) 486 self.assertGreaterEqual(sys.hash_info.cutoff, 0) 487 self.assertLess(sys.hash_info.cutoff, 8) 488 489 self.assertIsInstance(sys.maxsize, int) 490 self.assertIsInstance(sys.maxunicode, int) 491 self.assertEqual(sys.maxunicode, 0x10FFFF) 492 self.assertIsInstance(sys.platform, str) 493 self.assertIsInstance(sys.prefix, str) 494 self.assertIsInstance(sys.base_prefix, str) 495 self.assertIsInstance(sys.version, str) 496 vi = sys.version_info 497 self.assertIsInstance(vi[:], tuple) 498 self.assertEqual(len(vi), 5) 499 self.assertIsInstance(vi[0], int) 500 self.assertIsInstance(vi[1], int) 501 self.assertIsInstance(vi[2], int) 502 self.assertIn(vi[3], ("alpha", "beta", "candidate", "final")) 503 self.assertIsInstance(vi[4], int) 504 self.assertIsInstance(vi.major, int) 505 self.assertIsInstance(vi.minor, int) 506 self.assertIsInstance(vi.micro, int) 507 self.assertIn(vi.releaselevel, ("alpha", "beta", "candidate", "final")) 508 self.assertIsInstance(vi.serial, int) 509 self.assertEqual(vi[0], vi.major) 510 self.assertEqual(vi[1], vi.minor) 511 self.assertEqual(vi[2], vi.micro) 512 self.assertEqual(vi[3], vi.releaselevel) 513 self.assertEqual(vi[4], vi.serial) 514 self.assertTrue(vi > (1,0,0)) 515 self.assertIsInstance(sys.float_repr_style, str) 516 self.assertIn(sys.float_repr_style, ('short', 'legacy')) 517 if not sys.platform.startswith('win'): 518 self.assertIsInstance(sys.abiflags, str) 519 520 def test_thread_info(self): 521 info = sys.thread_info 522 self.assertEqual(len(info), 3) 523 self.assertIn(info.name, ('nt', 'pthread', 'solaris', None)) 524 self.assertIn(info.lock, ('semaphore', 'mutex+cond', None)) 525 526 def test_43581(self): 527 # Can't use sys.stdout, as this is a StringIO object when 528 # the test runs under regrtest. 529 self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding) 530 531 def test_intern(self): 532 global INTERN_NUMRUNS 533 INTERN_NUMRUNS += 1 534 self.assertRaises(TypeError, sys.intern) 535 s = "never interned before" + str(INTERN_NUMRUNS) 536 self.assertTrue(sys.intern(s) is s) 537 s2 = s.swapcase().swapcase() 538 self.assertTrue(sys.intern(s2) is s) 539 540 # Subclasses of string can't be interned, because they 541 # provide too much opportunity for insane things to happen. 542 # We don't want them in the interned dict and if they aren't 543 # actually interned, we don't want to create the appearance 544 # that they are by allowing intern() to succeed. 545 class S(str): 546 def __hash__(self): 547 return 123 548 549 self.assertRaises(TypeError, sys.intern, S("abc")) 550 551 def test_sys_flags(self): 552 self.assertTrue(sys.flags) 553 attrs = ("debug", 554 "inspect", "interactive", "optimize", "dont_write_bytecode", 555 "no_user_site", "no_site", "ignore_environment", "verbose", 556 "bytes_warning", "quiet", "hash_randomization", "isolated", 557 "dev_mode", "utf8_mode") 558 for attr in attrs: 559 self.assertTrue(hasattr(sys.flags, attr), attr) 560 attr_type = bool if attr == "dev_mode" else int 561 self.assertEqual(type(getattr(sys.flags, attr)), attr_type, attr) 562 self.assertTrue(repr(sys.flags)) 563 self.assertEqual(len(sys.flags), len(attrs)) 564 565 self.assertIn(sys.flags.utf8_mode, {0, 1, 2}) 566 567 def assert_raise_on_new_sys_type(self, sys_attr): 568 # Users are intentionally prevented from creating new instances of 569 # sys.flags, sys.version_info, and sys.getwindowsversion. 570 attr_type = type(sys_attr) 571 with self.assertRaises(TypeError): 572 attr_type() 573 with self.assertRaises(TypeError): 574 attr_type.__new__(attr_type) 575 576 def test_sys_flags_no_instantiation(self): 577 self.assert_raise_on_new_sys_type(sys.flags) 578 579 def test_sys_version_info_no_instantiation(self): 580 self.assert_raise_on_new_sys_type(sys.version_info) 581 582 def test_sys_getwindowsversion_no_instantiation(self): 583 # Skip if not being run on Windows. 584 test.support.get_attribute(sys, "getwindowsversion") 585 self.assert_raise_on_new_sys_type(sys.getwindowsversion()) 586 587 @test.support.cpython_only 588 def test_clear_type_cache(self): 589 sys._clear_type_cache() 590 591 def test_ioencoding(self): 592 env = dict(os.environ) 593 594 # Test character: cent sign, encoded as 0x4A (ASCII J) in CP424, 595 # not representable in ASCII. 596 597 env["PYTHONIOENCODING"] = "cp424" 598 p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xa2))'], 599 stdout = subprocess.PIPE, env=env) 600 out = p.communicate()[0].strip() 601 expected = ("\xa2" + os.linesep).encode("cp424") 602 self.assertEqual(out, expected) 603 604 env["PYTHONIOENCODING"] = "ascii:replace" 605 p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xa2))'], 606 stdout = subprocess.PIPE, env=env) 607 out = p.communicate()[0].strip() 608 self.assertEqual(out, b'?') 609 610 env["PYTHONIOENCODING"] = "ascii" 611 p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xa2))'], 612 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 613 env=env) 614 out, err = p.communicate() 615 self.assertEqual(out, b'') 616 self.assertIn(b'UnicodeEncodeError:', err) 617 self.assertIn(rb"'\xa2'", err) 618 619 env["PYTHONIOENCODING"] = "ascii:" 620 p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xa2))'], 621 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 622 env=env) 623 out, err = p.communicate() 624 self.assertEqual(out, b'') 625 self.assertIn(b'UnicodeEncodeError:', err) 626 self.assertIn(rb"'\xa2'", err) 627 628 env["PYTHONIOENCODING"] = ":surrogateescape" 629 p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xdcbd))'], 630 stdout=subprocess.PIPE, env=env) 631 out = p.communicate()[0].strip() 632 self.assertEqual(out, b'\xbd') 633 634 @unittest.skipUnless(test.support.FS_NONASCII, 635 'requires OS support of non-ASCII encodings') 636 @unittest.skipUnless(sys.getfilesystemencoding() == locale.getpreferredencoding(False), 637 'requires FS encoding to match locale') 638 def test_ioencoding_nonascii(self): 639 env = dict(os.environ) 640 641 env["PYTHONIOENCODING"] = "" 642 p = subprocess.Popen([sys.executable, "-c", 643 'print(%a)' % test.support.FS_NONASCII], 644 stdout=subprocess.PIPE, env=env) 645 out = p.communicate()[0].strip() 646 self.assertEqual(out, os.fsencode(test.support.FS_NONASCII)) 647 648 @unittest.skipIf(sys.base_prefix != sys.prefix, 649 'Test is not venv-compatible') 650 def test_executable(self): 651 # sys.executable should be absolute 652 self.assertEqual(os.path.abspath(sys.executable), sys.executable) 653 654 # Issue #7774: Ensure that sys.executable is an empty string if argv[0] 655 # has been set to a non existent program name and Python is unable to 656 # retrieve the real program name 657 658 # For a normal installation, it should work without 'cwd' 659 # argument. For test runs in the build directory, see #7774. 660 python_dir = os.path.dirname(os.path.realpath(sys.executable)) 661 p = subprocess.Popen( 662 ["nonexistent", "-c", 663 'import sys; print(sys.executable.encode("ascii", "backslashreplace"))'], 664 executable=sys.executable, stdout=subprocess.PIPE, cwd=python_dir) 665 stdout = p.communicate()[0] 666 executable = stdout.strip().decode("ASCII") 667 p.wait() 668 self.assertIn(executable, ["b''", repr(sys.executable.encode("ascii", "backslashreplace"))]) 669 670 def check_fsencoding(self, fs_encoding, expected=None): 671 self.assertIsNotNone(fs_encoding) 672 codecs.lookup(fs_encoding) 673 if expected: 674 self.assertEqual(fs_encoding, expected) 675 676 def test_getfilesystemencoding(self): 677 fs_encoding = sys.getfilesystemencoding() 678 if sys.platform == 'darwin': 679 expected = 'utf-8' 680 else: 681 expected = None 682 self.check_fsencoding(fs_encoding, expected) 683 684 def c_locale_get_error_handler(self, locale, isolated=False, encoding=None): 685 # Force the POSIX locale 686 env = os.environ.copy() 687 env["LC_ALL"] = locale 688 env["PYTHONCOERCECLOCALE"] = "0" 689 code = '\n'.join(( 690 'import sys', 691 'def dump(name):', 692 ' std = getattr(sys, name)', 693 ' print("%s: %s" % (name, std.errors))', 694 'dump("stdin")', 695 'dump("stdout")', 696 'dump("stderr")', 697 )) 698 args = [sys.executable, "-c", code] 699 if isolated: 700 args.append("-I") 701 if encoding is not None: 702 env['PYTHONIOENCODING'] = encoding 703 else: 704 env.pop('PYTHONIOENCODING', None) 705 p = subprocess.Popen(args, 706 stdout=subprocess.PIPE, 707 stderr=subprocess.STDOUT, 708 env=env, 709 universal_newlines=True) 710 stdout, stderr = p.communicate() 711 return stdout 712 713 def check_locale_surrogateescape(self, locale): 714 out = self.c_locale_get_error_handler(locale, isolated=True) 715 self.assertEqual(out, 716 'stdin: surrogateescape\n' 717 'stdout: surrogateescape\n' 718 'stderr: backslashreplace\n') 719 720 # replace the default error handler 721 out = self.c_locale_get_error_handler(locale, encoding=':ignore') 722 self.assertEqual(out, 723 'stdin: ignore\n' 724 'stdout: ignore\n' 725 'stderr: backslashreplace\n') 726 727 # force the encoding 728 out = self.c_locale_get_error_handler(locale, encoding='iso8859-1') 729 self.assertEqual(out, 730 'stdin: strict\n' 731 'stdout: strict\n' 732 'stderr: backslashreplace\n') 733 out = self.c_locale_get_error_handler(locale, encoding='iso8859-1:') 734 self.assertEqual(out, 735 'stdin: strict\n' 736 'stdout: strict\n' 737 'stderr: backslashreplace\n') 738 739 # have no any effect 740 out = self.c_locale_get_error_handler(locale, encoding=':') 741 self.assertEqual(out, 742 'stdin: surrogateescape\n' 743 'stdout: surrogateescape\n' 744 'stderr: backslashreplace\n') 745 out = self.c_locale_get_error_handler(locale, encoding='') 746 self.assertEqual(out, 747 'stdin: surrogateescape\n' 748 'stdout: surrogateescape\n' 749 'stderr: backslashreplace\n') 750 751 def test_c_locale_surrogateescape(self): 752 self.check_locale_surrogateescape('C') 753 754 def test_posix_locale_surrogateescape(self): 755 self.check_locale_surrogateescape('POSIX') 756 757 def test_implementation(self): 758 # This test applies to all implementations equally. 759 760 levels = {'alpha': 0xA, 'beta': 0xB, 'candidate': 0xC, 'final': 0xF} 761 762 self.assertTrue(hasattr(sys.implementation, 'name')) 763 self.assertTrue(hasattr(sys.implementation, 'version')) 764 self.assertTrue(hasattr(sys.implementation, 'hexversion')) 765 self.assertTrue(hasattr(sys.implementation, 'cache_tag')) 766 767 version = sys.implementation.version 768 self.assertEqual(version[:2], (version.major, version.minor)) 769 770 hexversion = (version.major << 24 | version.minor << 16 | 771 version.micro << 8 | levels[version.releaselevel] << 4 | 772 version.serial << 0) 773 self.assertEqual(sys.implementation.hexversion, hexversion) 774 775 # PEP 421 requires that .name be lower case. 776 self.assertEqual(sys.implementation.name, 777 sys.implementation.name.lower()) 778 779 @test.support.cpython_only 780 def test_debugmallocstats(self): 781 # Test sys._debugmallocstats() 782 from test.support.script_helper import assert_python_ok 783 args = ['-c', 'import sys; sys._debugmallocstats()'] 784 ret, out, err = assert_python_ok(*args) 785 self.assertIn(b"free PyDictObjects", err) 786 787 # The function has no parameter 788 self.assertRaises(TypeError, sys._debugmallocstats, True) 789 790 @unittest.skipUnless(hasattr(sys, "getallocatedblocks"), 791 "sys.getallocatedblocks unavailable on this build") 792 def test_getallocatedblocks(self): 793 try: 794 import _testcapi 795 except ImportError: 796 with_pymalloc = support.with_pymalloc() 797 else: 798 try: 799 alloc_name = _testcapi.pymem_getallocatorsname() 800 except RuntimeError as exc: 801 # "cannot get allocators name" (ex: tracemalloc is used) 802 with_pymalloc = True 803 else: 804 with_pymalloc = (alloc_name in ('pymalloc', 'pymalloc_debug')) 805 806 # Some sanity checks 807 a = sys.getallocatedblocks() 808 self.assertIs(type(a), int) 809 if with_pymalloc: 810 self.assertGreater(a, 0) 811 else: 812 # When WITH_PYMALLOC isn't available, we don't know anything 813 # about the underlying implementation: the function might 814 # return 0 or something greater. 815 self.assertGreaterEqual(a, 0) 816 try: 817 # While we could imagine a Python session where the number of 818 # multiple buffer objects would exceed the sharing of references, 819 # it is unlikely to happen in a normal test run. 820 self.assertLess(a, sys.gettotalrefcount()) 821 except AttributeError: 822 # gettotalrefcount() not available 823 pass 824 gc.collect() 825 b = sys.getallocatedblocks() 826 self.assertLessEqual(b, a) 827 gc.collect() 828 c = sys.getallocatedblocks() 829 self.assertIn(c, range(b - 50, b + 50)) 830 831 @test.support.requires_type_collecting 832 def test_is_finalizing(self): 833 self.assertIs(sys.is_finalizing(), False) 834 # Don't use the atexit module because _Py_Finalizing is only set 835 # after calling atexit callbacks 836 code = """if 1: 837 import sys 838 839 class AtExit: 840 is_finalizing = sys.is_finalizing 841 print = print 842 843 def __del__(self): 844 self.print(self.is_finalizing(), flush=True) 845 846 # Keep a reference in the __main__ module namespace, so the 847 # AtExit destructor will be called at Python exit 848 ref = AtExit() 849 """ 850 rc, stdout, stderr = assert_python_ok('-c', code) 851 self.assertEqual(stdout.rstrip(), b'True') 852 853 @unittest.skipUnless(hasattr(sys, 'getandroidapilevel'), 854 'need sys.getandroidapilevel()') 855 def test_getandroidapilevel(self): 856 level = sys.getandroidapilevel() 857 self.assertIsInstance(level, int) 858 self.assertGreater(level, 0) 859 860 def test_sys_tracebacklimit(self): 861 code = """if 1: 862 import sys 863 def f1(): 864 1 / 0 865 def f2(): 866 f1() 867 sys.tracebacklimit = %r 868 f2() 869 """ 870 def check(tracebacklimit, expected): 871 p = subprocess.Popen([sys.executable, '-c', code % tracebacklimit], 872 stderr=subprocess.PIPE) 873 out = p.communicate()[1] 874 self.assertEqual(out.splitlines(), expected) 875 876 traceback = [ 877 b'Traceback (most recent call last):', 878 b' File "<string>", line 8, in <module>', 879 b' File "<string>", line 6, in f2', 880 b' File "<string>", line 4, in f1', 881 b'ZeroDivisionError: division by zero' 882 ] 883 check(10, traceback) 884 check(3, traceback) 885 check(2, traceback[:1] + traceback[2:]) 886 check(1, traceback[:1] + traceback[3:]) 887 check(0, [traceback[-1]]) 888 check(-1, [traceback[-1]]) 889 check(1<<1000, traceback) 890 check(-1<<1000, [traceback[-1]]) 891 check(None, traceback) 892 893 def test_no_duplicates_in_meta_path(self): 894 self.assertEqual(len(sys.meta_path), len(set(sys.meta_path))) 895 896 897@test.support.cpython_only 898class SizeofTest(unittest.TestCase): 899 900 def setUp(self): 901 self.P = struct.calcsize('P') 902 self.longdigit = sys.int_info.sizeof_digit 903 import _testcapi 904 self.gc_headsize = _testcapi.SIZEOF_PYGC_HEAD 905 906 check_sizeof = test.support.check_sizeof 907 908 def test_gc_head_size(self): 909 # Check that the gc header size is added to objects tracked by the gc. 910 vsize = test.support.calcvobjsize 911 gc_header_size = self.gc_headsize 912 # bool objects are not gc tracked 913 self.assertEqual(sys.getsizeof(True), vsize('') + self.longdigit) 914 # but lists are 915 self.assertEqual(sys.getsizeof([]), vsize('Pn') + gc_header_size) 916 917 def test_errors(self): 918 class BadSizeof: 919 def __sizeof__(self): 920 raise ValueError 921 self.assertRaises(ValueError, sys.getsizeof, BadSizeof()) 922 923 class InvalidSizeof: 924 def __sizeof__(self): 925 return None 926 self.assertRaises(TypeError, sys.getsizeof, InvalidSizeof()) 927 sentinel = ["sentinel"] 928 self.assertIs(sys.getsizeof(InvalidSizeof(), sentinel), sentinel) 929 930 class FloatSizeof: 931 def __sizeof__(self): 932 return 4.5 933 self.assertRaises(TypeError, sys.getsizeof, FloatSizeof()) 934 self.assertIs(sys.getsizeof(FloatSizeof(), sentinel), sentinel) 935 936 class OverflowSizeof(int): 937 def __sizeof__(self): 938 return int(self) 939 self.assertEqual(sys.getsizeof(OverflowSizeof(sys.maxsize)), 940 sys.maxsize + self.gc_headsize) 941 with self.assertRaises(OverflowError): 942 sys.getsizeof(OverflowSizeof(sys.maxsize + 1)) 943 with self.assertRaises(ValueError): 944 sys.getsizeof(OverflowSizeof(-1)) 945 with self.assertRaises((ValueError, OverflowError)): 946 sys.getsizeof(OverflowSizeof(-sys.maxsize - 1)) 947 948 def test_default(self): 949 size = test.support.calcvobjsize 950 self.assertEqual(sys.getsizeof(True), size('') + self.longdigit) 951 self.assertEqual(sys.getsizeof(True, -1), size('') + self.longdigit) 952 953 def test_objecttypes(self): 954 # check all types defined in Objects/ 955 calcsize = struct.calcsize 956 size = test.support.calcobjsize 957 vsize = test.support.calcvobjsize 958 check = self.check_sizeof 959 # bool 960 check(True, vsize('') + self.longdigit) 961 # buffer 962 # XXX 963 # builtin_function_or_method 964 check(len, size('4P')) # XXX check layout 965 # bytearray 966 samples = [b'', b'u'*100000] 967 for sample in samples: 968 x = bytearray(sample) 969 check(x, vsize('n2Pi') + x.__alloc__()) 970 # bytearray_iterator 971 check(iter(bytearray()), size('nP')) 972 # bytes 973 check(b'', vsize('n') + 1) 974 check(b'x' * 10, vsize('n') + 11) 975 # cell 976 def get_cell(): 977 x = 42 978 def inner(): 979 return x 980 return inner 981 check(get_cell().__closure__[0], size('P')) 982 # code 983 def check_code_size(a, expected_size): 984 self.assertGreaterEqual(sys.getsizeof(a), expected_size) 985 check_code_size(get_cell().__code__, size('6i13P')) 986 check_code_size(get_cell.__code__, size('6i13P')) 987 def get_cell2(x): 988 def inner(): 989 return x 990 return inner 991 check_code_size(get_cell2.__code__, size('6i13P') + calcsize('n')) 992 # complex 993 check(complex(0,1), size('2d')) 994 # method_descriptor (descriptor object) 995 check(str.lower, size('3PP')) 996 # classmethod_descriptor (descriptor object) 997 # XXX 998 # member_descriptor (descriptor object) 999 import datetime 1000 check(datetime.timedelta.days, size('3PP')) 1001 # getset_descriptor (descriptor object) 1002 import collections 1003 check(collections.defaultdict.default_factory, size('3PP')) 1004 # wrapper_descriptor (descriptor object) 1005 check(int.__add__, size('3P2P')) 1006 # method-wrapper (descriptor object) 1007 check({}.__iter__, size('2P')) 1008 # dict 1009 check({}, size('nQ2P') + calcsize('2nP2n') + 8 + (8*2//3)*calcsize('n2P')) 1010 longdict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8} 1011 check(longdict, size('nQ2P') + calcsize('2nP2n') + 16 + (16*2//3)*calcsize('n2P')) 1012 # dictionary-keyview 1013 check({}.keys(), size('P')) 1014 # dictionary-valueview 1015 check({}.values(), size('P')) 1016 # dictionary-itemview 1017 check({}.items(), size('P')) 1018 # dictionary iterator 1019 check(iter({}), size('P2nPn')) 1020 # dictionary-keyiterator 1021 check(iter({}.keys()), size('P2nPn')) 1022 # dictionary-valueiterator 1023 check(iter({}.values()), size('P2nPn')) 1024 # dictionary-itemiterator 1025 check(iter({}.items()), size('P2nPn')) 1026 # dictproxy 1027 class C(object): pass 1028 check(C.__dict__, size('P')) 1029 # BaseException 1030 check(BaseException(), size('5Pb')) 1031 # UnicodeEncodeError 1032 check(UnicodeEncodeError("", "", 0, 0, ""), size('5Pb 2P2nP')) 1033 # UnicodeDecodeError 1034 check(UnicodeDecodeError("", b"", 0, 0, ""), size('5Pb 2P2nP')) 1035 # UnicodeTranslateError 1036 check(UnicodeTranslateError("", 0, 1, ""), size('5Pb 2P2nP')) 1037 # ellipses 1038 check(Ellipsis, size('')) 1039 # EncodingMap 1040 import codecs, encodings.iso8859_3 1041 x = codecs.charmap_build(encodings.iso8859_3.decoding_table) 1042 check(x, size('32B2iB')) 1043 # enumerate 1044 check(enumerate([]), size('n3P')) 1045 # reverse 1046 check(reversed(''), size('nP')) 1047 # float 1048 check(float(0), size('d')) 1049 # sys.floatinfo 1050 check(sys.float_info, vsize('') + self.P * len(sys.float_info)) 1051 # frame 1052 import inspect 1053 CO_MAXBLOCKS = 20 1054 x = inspect.currentframe() 1055 ncells = len(x.f_code.co_cellvars) 1056 nfrees = len(x.f_code.co_freevars) 1057 extras = x.f_code.co_stacksize + x.f_code.co_nlocals +\ 1058 ncells + nfrees - 1 1059 check(x, vsize('5P2c4P3ic' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P')) 1060 # function 1061 def func(): pass 1062 check(func, size('12P')) 1063 class c(): 1064 @staticmethod 1065 def foo(): 1066 pass 1067 @classmethod 1068 def bar(cls): 1069 pass 1070 # staticmethod 1071 check(foo, size('PP')) 1072 # classmethod 1073 check(bar, size('PP')) 1074 # generator 1075 def get_gen(): yield 1 1076 check(get_gen(), size('Pb2PPP4P')) 1077 # iterator 1078 check(iter('abc'), size('lP')) 1079 # callable-iterator 1080 import re 1081 check(re.finditer('',''), size('2P')) 1082 # list 1083 samples = [[], [1,2,3], ['1', '2', '3']] 1084 for sample in samples: 1085 check(sample, vsize('Pn') + len(sample)*self.P) 1086 # sortwrapper (list) 1087 # XXX 1088 # cmpwrapper (list) 1089 # XXX 1090 # listiterator (list) 1091 check(iter([]), size('lP')) 1092 # listreverseiterator (list) 1093 check(reversed([]), size('nP')) 1094 # int 1095 check(0, vsize('')) 1096 check(1, vsize('') + self.longdigit) 1097 check(-1, vsize('') + self.longdigit) 1098 PyLong_BASE = 2**sys.int_info.bits_per_digit 1099 check(int(PyLong_BASE), vsize('') + 2*self.longdigit) 1100 check(int(PyLong_BASE**2-1), vsize('') + 2*self.longdigit) 1101 check(int(PyLong_BASE**2), vsize('') + 3*self.longdigit) 1102 # module 1103 check(unittest, size('PnPPP')) 1104 # None 1105 check(None, size('')) 1106 # NotImplementedType 1107 check(NotImplemented, size('')) 1108 # object 1109 check(object(), size('')) 1110 # property (descriptor object) 1111 class C(object): 1112 def getx(self): return self.__x 1113 def setx(self, value): self.__x = value 1114 def delx(self): del self.__x 1115 x = property(getx, setx, delx, "") 1116 check(x, size('4Pi')) 1117 # PyCapsule 1118 # XXX 1119 # rangeiterator 1120 check(iter(range(1)), size('4l')) 1121 # reverse 1122 check(reversed(''), size('nP')) 1123 # range 1124 check(range(1), size('4P')) 1125 check(range(66000), size('4P')) 1126 # set 1127 # frozenset 1128 PySet_MINSIZE = 8 1129 samples = [[], range(10), range(50)] 1130 s = size('3nP' + PySet_MINSIZE*'nP' + '2nP') 1131 for sample in samples: 1132 minused = len(sample) 1133 if minused == 0: tmp = 1 1134 # the computation of minused is actually a bit more complicated 1135 # but this suffices for the sizeof test 1136 minused = minused*2 1137 newsize = PySet_MINSIZE 1138 while newsize <= minused: 1139 newsize = newsize << 1 1140 if newsize <= 8: 1141 check(set(sample), s) 1142 check(frozenset(sample), s) 1143 else: 1144 check(set(sample), s + newsize*calcsize('nP')) 1145 check(frozenset(sample), s + newsize*calcsize('nP')) 1146 # setiterator 1147 check(iter(set()), size('P3n')) 1148 # slice 1149 check(slice(0), size('3P')) 1150 # super 1151 check(super(int), size('3P')) 1152 # tuple 1153 check((), vsize('')) 1154 check((1,2,3), vsize('') + 3*self.P) 1155 # type 1156 # static type: PyTypeObject 1157 fmt = 'P2n15Pl4Pn9Pn11PIP' 1158 if hasattr(sys, 'getcounts'): 1159 fmt += '3n2P' 1160 s = vsize(fmt) 1161 check(int, s) 1162 # class 1163 s = vsize(fmt + # PyTypeObject 1164 '3P' # PyAsyncMethods 1165 '36P' # PyNumberMethods 1166 '3P' # PyMappingMethods 1167 '10P' # PySequenceMethods 1168 '2P' # PyBufferProcs 1169 '4P') 1170 class newstyleclass(object): pass 1171 # Separate block for PyDictKeysObject with 8 keys and 5 entries 1172 check(newstyleclass, s + calcsize("2nP2n0P") + 8 + 5*calcsize("n2P")) 1173 # dict with shared keys 1174 check(newstyleclass().__dict__, size('nQ2P') + 5*self.P) 1175 o = newstyleclass() 1176 o.a = o.b = o.c = o.d = o.e = o.f = o.g = o.h = 1 1177 # Separate block for PyDictKeysObject with 16 keys and 10 entries 1178 check(newstyleclass, s + calcsize("2nP2n0P") + 16 + 10*calcsize("n2P")) 1179 # dict with shared keys 1180 check(newstyleclass().__dict__, size('nQ2P') + 10*self.P) 1181 # unicode 1182 # each tuple contains a string and its expected character size 1183 # don't put any static strings here, as they may contain 1184 # wchar_t or UTF-8 representations 1185 samples = ['1'*100, '\xff'*50, 1186 '\u0100'*40, '\uffff'*100, 1187 '\U00010000'*30, '\U0010ffff'*100] 1188 asciifields = "nnbP" 1189 compactfields = asciifields + "nPn" 1190 unicodefields = compactfields + "P" 1191 for s in samples: 1192 maxchar = ord(max(s)) 1193 if maxchar < 128: 1194 L = size(asciifields) + len(s) + 1 1195 elif maxchar < 256: 1196 L = size(compactfields) + len(s) + 1 1197 elif maxchar < 65536: 1198 L = size(compactfields) + 2*(len(s) + 1) 1199 else: 1200 L = size(compactfields) + 4*(len(s) + 1) 1201 check(s, L) 1202 # verify that the UTF-8 size is accounted for 1203 s = chr(0x4000) # 4 bytes canonical representation 1204 check(s, size(compactfields) + 4) 1205 # compile() will trigger the generation of the UTF-8 1206 # representation as a side effect 1207 compile(s, "<stdin>", "eval") 1208 check(s, size(compactfields) + 4 + 4) 1209 # TODO: add check that forces the presence of wchar_t representation 1210 # TODO: add check that forces layout of unicodefields 1211 # weakref 1212 import weakref 1213 check(weakref.ref(int), size('2Pn2P')) 1214 # weakproxy 1215 # XXX 1216 # weakcallableproxy 1217 check(weakref.proxy(int), size('2Pn2P')) 1218 1219 def check_slots(self, obj, base, extra): 1220 expected = sys.getsizeof(base) + struct.calcsize(extra) 1221 if gc.is_tracked(obj) and not gc.is_tracked(base): 1222 expected += self.gc_headsize 1223 self.assertEqual(sys.getsizeof(obj), expected) 1224 1225 def test_slots(self): 1226 # check all subclassable types defined in Objects/ that allow 1227 # non-empty __slots__ 1228 check = self.check_slots 1229 class BA(bytearray): 1230 __slots__ = 'a', 'b', 'c' 1231 check(BA(), bytearray(), '3P') 1232 class D(dict): 1233 __slots__ = 'a', 'b', 'c' 1234 check(D(x=[]), {'x': []}, '3P') 1235 class L(list): 1236 __slots__ = 'a', 'b', 'c' 1237 check(L(), [], '3P') 1238 class S(set): 1239 __slots__ = 'a', 'b', 'c' 1240 check(S(), set(), '3P') 1241 class FS(frozenset): 1242 __slots__ = 'a', 'b', 'c' 1243 check(FS(), frozenset(), '3P') 1244 from collections import OrderedDict 1245 class OD(OrderedDict): 1246 __slots__ = 'a', 'b', 'c' 1247 check(OD(x=[]), OrderedDict(x=[]), '3P') 1248 1249 def test_pythontypes(self): 1250 # check all types defined in Python/ 1251 size = test.support.calcobjsize 1252 vsize = test.support.calcvobjsize 1253 check = self.check_sizeof 1254 # _ast.AST 1255 import _ast 1256 check(_ast.AST(), size('P')) 1257 try: 1258 raise TypeError 1259 except TypeError: 1260 tb = sys.exc_info()[2] 1261 # traceback 1262 if tb is not None: 1263 check(tb, size('2P2i')) 1264 # symtable entry 1265 # XXX 1266 # sys.flags 1267 check(sys.flags, vsize('') + self.P * len(sys.flags)) 1268 1269 def test_asyncgen_hooks(self): 1270 old = sys.get_asyncgen_hooks() 1271 self.assertIsNone(old.firstiter) 1272 self.assertIsNone(old.finalizer) 1273 1274 firstiter = lambda *a: None 1275 sys.set_asyncgen_hooks(firstiter=firstiter) 1276 hooks = sys.get_asyncgen_hooks() 1277 self.assertIs(hooks.firstiter, firstiter) 1278 self.assertIs(hooks[0], firstiter) 1279 self.assertIs(hooks.finalizer, None) 1280 self.assertIs(hooks[1], None) 1281 1282 finalizer = lambda *a: None 1283 sys.set_asyncgen_hooks(finalizer=finalizer) 1284 hooks = sys.get_asyncgen_hooks() 1285 self.assertIs(hooks.firstiter, firstiter) 1286 self.assertIs(hooks[0], firstiter) 1287 self.assertIs(hooks.finalizer, finalizer) 1288 self.assertIs(hooks[1], finalizer) 1289 1290 sys.set_asyncgen_hooks(*old) 1291 cur = sys.get_asyncgen_hooks() 1292 self.assertIsNone(cur.firstiter) 1293 self.assertIsNone(cur.finalizer) 1294 1295 def test_changing_sys_stderr_and_removing_reference(self): 1296 # If the default displayhook doesn't take a strong reference 1297 # to sys.stderr the following code can crash. See bpo-43660 1298 # for more details. 1299 code = textwrap.dedent(''' 1300 import sys 1301 class MyStderr: 1302 def write(self, s): 1303 sys.stderr = None 1304 sys.stderr = MyStderr() 1305 1/0 1306 ''') 1307 rc, out, err = assert_python_failure('-c', code) 1308 self.assertEqual(out, b"") 1309 self.assertEqual(err, b"") 1310 1311def test_main(): 1312 test.support.run_unittest(SysModuleTest, SizeofTest) 1313 1314if __name__ == "__main__": 1315 test_main() 1316