1import sys
2import types
3import unittest
4
5
6# bpo-46417: Test that structseq types used by the sys module are still
7# valid when Py_Finalize()/Py_Initialize() are called multiple times.
8class TestStructSeq(unittest.TestCase):
9    # test PyTypeObject members
10    def check_structseq(self, obj_type):
11        # ob_refcnt
12        self.assertGreaterEqual(sys.getrefcount(obj_type), 1)
13        # tp_base
14        self.assertTrue(issubclass(obj_type, tuple))
15        # tp_bases
16        self.assertEqual(obj_type.__bases__, (tuple,))
17        # tp_dict
18        self.assertIsInstance(obj_type.__dict__, types.MappingProxyType)
19        # tp_mro
20        self.assertEqual(obj_type.__mro__, (obj_type, tuple, object))
21        # tp_name
22        self.assertIsInstance(type.__name__, str)
23        # tp_subclasses
24        self.assertEqual(obj_type.__subclasses__(), [])
25
26    def test_sys_attrs(self):
27        for attr_name in (
28            'flags',          # FlagsType
29            'float_info',     # FloatInfoType
30            'hash_info',      # Hash_InfoType
31            'int_info',       # Int_InfoType
32            'thread_info',    # ThreadInfoType
33            'version_info',   # VersionInfoType
34        ):
35            with self.subTest(attr=attr_name):
36                attr = getattr(sys, attr_name)
37                self.check_structseq(type(attr))
38
39    def test_sys_funcs(self):
40        func_names = ['get_asyncgen_hooks']  # AsyncGenHooksType
41        if hasattr(sys, 'getwindowsversion'):
42            func_names.append('getwindowsversion')  # WindowsVersionType
43        for func_name in func_names:
44            with self.subTest(func=func_name):
45                func = getattr(sys, func_name)
46                obj = func()
47                self.check_structseq(type(obj))
48
49
50try:
51    unittest.main()
52except SystemExit as exc:
53    if exc.args[0] != 0:
54        raise
55print("Tests passed")
56