diff --git a/pyobjc-core/Lib/PyObjCTools/TestSupport.py b/pyobjc-core/Lib/PyObjCTools/TestSupport.py index 34bd89495..914f4eb6c 100644 --- a/pyobjc-core/Lib/PyObjCTools/TestSupport.py +++ b/pyobjc-core/Lib/PyObjCTools/TestSupport.py @@ -1107,6 +1107,16 @@ def assertPickleRoundTrips(self, value): self.assertEqual(clone, value) self.assertIsInstance(clone, type(value)) + def assertFreeThreadedIfConfigured(self): + """ + Assert that the process is running in free-threaded mode when + the interpreter was configured as such. + """ + if not _get_config_var("Py_GIL_DISABLED"): + return + + self.assertFalse(_sys._is_gil_enabled(), "GIL is enabled") + def _validateCallableMetadata( self, value, class_name=None, skip_simple_charptr_check=False ): @@ -1393,6 +1403,10 @@ def assertCallableMetadataIsSane( else: continue + # Quick check that the GIL is actually disabled. Testing this here isn't + # ideal, but avoids changing all framework bindings. + self.assertFreeThreadedIfConfigured() + def __init__(self, methodName="runTest"): super().__init__(methodName) diff --git a/pyobjc-core/PyObjCTest/test_regr.py b/pyobjc-core/PyObjCTest/test_regr.py index 98b17f0a5..946d16ff7 100644 --- a/pyobjc-core/PyObjCTest/test_regr.py +++ b/pyobjc-core/PyObjCTest/test_regr.py @@ -680,3 +680,8 @@ def __del__(self): s = super(D, D()) del s assert deleted + + +class TestFreeThreaded(TestCase): + def test_freethreaded_if_configured(self): + self.assertFreeThreadedIfConfigured()