summaryrefslogtreecommitdiffstats
path: root/Lib/test/_test_embed_structseq.py
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-01-21 00:42:25 (GMT)
committerGitHub <noreply@github.com>2022-01-21 00:42:25 (GMT)
commite9e3eab0b868c7d0b48e472705024240d5c39d5c (patch)
tree65c254d948a37dd822085887ebb84f390ad48d94 /Lib/test/_test_embed_structseq.py
parent27df7566bc19699b967e0e30d7808637b90141f6 (diff)
downloadcpython-e9e3eab0b868c7d0b48e472705024240d5c39d5c.zip
cpython-e9e3eab0b868c7d0b48e472705024240d5c39d5c.tar.gz
cpython-e9e3eab0b868c7d0b48e472705024240d5c39d5c.tar.bz2
bpo-46417: Finalize structseq types at exit (GH-30645)
Add _PyStructSequence_FiniType() and _PyStaticType_Dealloc() functions to finalize a structseq static type in Py_Finalize(). Currrently, these functions do nothing if Python is built in release mode. Clear static types: * AsyncGenHooksType: sys.set_asyncgen_hooks() * FlagsType: sys.flags * FloatInfoType: sys.float_info * Hash_InfoType: sys.hash_info * Int_InfoType: sys.int_info * ThreadInfoType: sys.thread_info * UnraisableHookArgsType: sys.unraisablehook * VersionInfoType: sys.version * WindowsVersionType: sys.getwindowsversion()
Diffstat (limited to 'Lib/test/_test_embed_structseq.py')
-rw-r--r--Lib/test/_test_embed_structseq.py55
1 files changed, 55 insertions, 0 deletions
diff --git a/Lib/test/_test_embed_structseq.py b/Lib/test/_test_embed_structseq.py
new file mode 100644
index 0000000..868f9f8
--- /dev/null
+++ b/Lib/test/_test_embed_structseq.py
@@ -0,0 +1,55 @@
+import sys
+import types
+import unittest
+
+
+# bpo-46417: Test that structseq types used by the sys module are still
+# valid when Py_Finalize()/Py_Initialize() are called multiple times.
+class TestStructSeq(unittest.TestCase):
+ # test PyTypeObject members
+ def check_structseq(self, obj_type):
+ # ob_refcnt
+ self.assertGreaterEqual(sys.getrefcount(obj_type), 1)
+ # tp_base
+ self.assertTrue(issubclass(obj_type, tuple))
+ # tp_bases
+ self.assertEqual(obj_type.__bases__, (tuple,))
+ # tp_dict
+ self.assertIsInstance(obj_type.__dict__, types.MappingProxyType)
+ # tp_mro
+ self.assertEqual(obj_type.__mro__, (obj_type, tuple, object))
+ # tp_name
+ self.assertIsInstance(type.__name__, str)
+ # tp_subclasses
+ self.assertEqual(obj_type.__subclasses__(), [])
+
+ def test_sys_attrs(self):
+ for attr_name in (
+ 'flags', # FlagsType
+ 'float_info', # FloatInfoType
+ 'hash_info', # Hash_InfoType
+ 'int_info', # Int_InfoType
+ 'thread_info', # ThreadInfoType
+ 'version_info', # VersionInfoType
+ ):
+ with self.subTest(attr=attr_name):
+ attr = getattr(sys, attr_name)
+ self.check_structseq(type(attr))
+
+ def test_sys_funcs(self):
+ func_names = ['get_asyncgen_hooks'] # AsyncGenHooksType
+ if hasattr(sys, 'getwindowsversion'):
+ func_names.append('getwindowsversion') # WindowsVersionType
+ for func_name in func_names:
+ with self.subTest(func=func_name):
+ func = getattr(sys, func_name)
+ obj = func()
+ self.check_structseq(type(obj))
+
+
+try:
+ unittest.main()
+except SystemExit as exc:
+ if exc.args[0] != 0:
+ raise
+print("Tests passed")