test_sys.py 63 KB

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