| import sys | |
| import unittest | |
| import sysconfig | |
| from test.support import subTests | |
| from test.support import import_helper | |
| _testcapi = import_helper.import_module('_testcapi') | |
| class Test_ABIInfo_Check(unittest.TestCase): | |
| @subTests('modname', (None, 'test_mod')) | |
| def test_zero(self, modname): | |
| _testcapi.pyabiinfo_check(modname, 0, 0, 0, 0, 0) | |
| _testcapi.pyabiinfo_check(modname, 1, 0, 0, 0, 0) | |
| def test_large_major_version(self): | |
| with self.assertRaisesRegex(ImportError, | |
| '^PyABIInfo version too high$'): | |
| _testcapi.pyabiinfo_check(None, 2, 0, 0, 0, 0) | |
| with self.assertRaisesRegex(ImportError, | |
| '^test_mod: PyABIInfo version too high$'): | |
| _testcapi.pyabiinfo_check("test_mod", 2, 0, 0, 0, 0) | |
| @subTests('modname', (None, 'test_mod')) | |
| def test_large_minor_version(self, modname): | |
| _testcapi.pyabiinfo_check(modname, 1, 2, 0, 0, 0) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('major', (0, 1)) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| def test_positive_regular(self, modname, major, minor, build): | |
| ver = sys.hexversion | |
| truncated = ver & 0xffff0000 | |
| filled = truncated | 0x12b8 | |
| maxed = truncated | 0xffff | |
| for abi_version in (0, ver, truncated, filled, maxed): | |
| with self.subTest(abi_version=abi_version): | |
| _testcapi.pyabiinfo_check(modname, major, minor, 0, | |
| build, abi_version) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| @subTests('offset', (+0x00010000, -0x00010000)) | |
| def test_negative_regular(self, modname, minor, build, offset): | |
| ver = sys.hexversion + offset | |
| truncated = ver & 0xffff0000 | |
| filled = truncated | 0x12b8 | |
| maxed = truncated | 0xffff | |
| for abi_version in (ver, truncated, filled, maxed): | |
| with self.subTest(abi_version=abi_version): | |
| with self.assertRaisesRegex( | |
| ImportError, | |
| r'incompatible ABI version \(3\.\d+\)$'): | |
| _testcapi.pyabiinfo_check(modname, 1, minor, 0, | |
| build, | |
| abi_version) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('major', (0, 1)) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| @subTests('abi_version', ( | |
| 0, | |
| 0x03020000, | |
| sys.hexversion, | |
| sys.hexversion & 0xffff0000, | |
| sys.hexversion - 0x00010000, | |
| )) | |
| def test_positive_stable(self, modname, major, minor, build, abi_version): | |
| _testcapi.pyabiinfo_check(modname, major, minor, | |
| _testcapi.PyABIInfo_STABLE, | |
| build, | |
| abi_version) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| @subTests('abi_version_and_msg', ( | |
| (1, 'invalid'), | |
| (3, 'invalid'), | |
| (0x0301ffff, 'invalid'), | |
| ((sys.hexversion & 0xffff0000) + 0x00010000, 'incompatible future'), | |
| (sys.hexversion + 0x00010000, 'incompatible future'), | |
| (0x04000000, 'incompatible future'), | |
| )) | |
| def test_negative_stable(self, modname, minor, build, abi_version_and_msg): | |
| abi_version, msg = abi_version_and_msg | |
| with self.assertRaisesRegex( | |
| ImportError, | |
| rf'{msg} stable ABI version \(\d+\.\d+\)$'): | |
| _testcapi.pyabiinfo_check(modname, 1, minor, | |
| _testcapi.PyABIInfo_STABLE, | |
| build, | |
| abi_version) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('major', (0, 1)) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| @subTests('abi_version', (0, sys.hexversion)) | |
| def test_positive_internal(self, modname, major, minor, build, abi_version): | |
| _testcapi.pyabiinfo_check(modname, major, minor, | |
| _testcapi.PyABIInfo_INTERNAL, | |
| build, | |
| abi_version) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| @subTests('abi_version', ( | |
| sys.hexversion - 0x00010000, | |
| sys.hexversion - 1, | |
| sys.hexversion + 1, | |
| sys.hexversion + 0x00010000, | |
| )) | |
| def test_negative_internal(self, modname, minor, build, abi_version): | |
| with self.assertRaisesRegex( | |
| ImportError, | |
| r'incompatible internal ABI \(0x[\da-f]+ != 0x[\da-f]+\)$'): | |
| _testcapi.pyabiinfo_check(modname, 1, minor, | |
| _testcapi.PyABIInfo_INTERNAL, | |
| build, | |
| abi_version) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| @subTests('ft_flag', ( | |
| 0, | |
| (_testcapi.PyABIInfo_FREETHREADED | |
| if sysconfig.get_config_var("Py_GIL_DISABLED") | |
| else _testcapi.PyABIInfo_GIL), | |
| _testcapi.PyABIInfo_FREETHREADING_AGNOSTIC, | |
| )) | |
| def test_positive_freethreading(self, modname, minor, build, ft_flag): | |
| self.assertEqual(ft_flag & _testcapi.PyABIInfo_FREETHREADING_AGNOSTIC, | |
| ft_flag) | |
| _testcapi.pyabiinfo_check(modname, 1, minor, ft_flag, build, 0) | |
| @subTests('modname', (None, 'test_mod')) | |
| @subTests('minor', (0, 1, 9)) | |
| @subTests('build', (0, sys.hexversion)) | |
| def test_negative_freethreading(self, modname, minor, build): | |
| if sysconfig.get_config_var("Py_GIL_DISABLED"): | |
| ft_flag = _testcapi.PyABIInfo_GIL | |
| msg = "incompatible with free-threaded CPython" | |
| else: | |
| ft_flag = _testcapi.PyABIInfo_FREETHREADED | |
| msg = "only compatible with free-threaded CPython" | |
| with self.assertRaisesRegex(ImportError, msg): | |
| _testcapi.pyabiinfo_check(modname, 1, minor, ft_flag, build, 0) | |
| class TestModsupport(unittest.TestCase): | |
| def test_pyarg_parsearray(self): | |
| func = _testcapi.pyarg_parsearray | |
| self.assertEqual(func(1, 2), (1, 2, 0)) | |
| self.assertEqual(func(1, 2, 3), (1, 2, 3)) | |
| self.assertRaises(TypeError, func, 1) | |
| self.assertRaises(TypeError, func, "str", 2) | |
| def test_funcandkeywords(self): | |
| func = _testcapi.pyarg_parsearrayandkeywords | |
| self.assertEqual(func(1, 2), (1, 2, 0)) | |
| self.assertEqual(func(1, 2, 3), (1, 2, 3)) | |
| self.assertEqual(func(1, b=2), (1, 2, 0)) | |
| self.assertEqual(func(1, b=2, c=3), (1, 2, 3)) | |
| self.assertRaises(TypeError, func, 1) | |
| self.assertRaises(TypeError, func, "str", 2) | |
| self.assertRaises(TypeError, func, 1, z=2) |