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