mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
gh-116322: Add Py_mod_gil module slot (#116882)
This PR adds the ability to enable the GIL if it was disabled at interpreter startup, and modifies the multi-phase module initialization path to enable the GIL when loading a module, unless that module's spec includes a slot indicating it can run safely without the GIL. PEP 703 called the constant for the slot `Py_mod_gil_not_used`; I went with `Py_MOD_GIL_NOT_USED` for consistency with gh-104148. A warning will be issued up to once per interpreter for the first GIL-using module that is loaded. If `-v` is given, a shorter message will be printed to stderr every time a GIL-using module is loaded (including the first one that issues a warning).
This commit is contained in:
parent
3e818afb9b
commit
c2627d6eea
123 changed files with 376 additions and 62 deletions
44
Lib/test/test_importlib/extension/_test_nonmodule_cases.py
Normal file
44
Lib/test/test_importlib/extension/_test_nonmodule_cases.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
import types
|
||||
import unittest
|
||||
from test.test_importlib import util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
from test.test_importlib.extension.test_loader import MultiPhaseExtensionModuleTests
|
||||
|
||||
|
||||
class NonModuleExtensionTests:
|
||||
setUp = MultiPhaseExtensionModuleTests.setUp
|
||||
load_module_by_name = MultiPhaseExtensionModuleTests.load_module_by_name
|
||||
|
||||
def _test_nonmodule(self):
|
||||
# Test returning a non-module object from create works.
|
||||
name = self.name + '_nonmodule'
|
||||
mod = self.load_module_by_name(name)
|
||||
self.assertNotEqual(type(mod), type(unittest))
|
||||
self.assertEqual(mod.three, 3)
|
||||
|
||||
# issue 27782
|
||||
def test_nonmodule_with_methods(self):
|
||||
# Test creating a non-module object with methods defined.
|
||||
name = self.name + '_nonmodule_with_methods'
|
||||
mod = self.load_module_by_name(name)
|
||||
self.assertNotEqual(type(mod), type(unittest))
|
||||
self.assertEqual(mod.three, 3)
|
||||
self.assertEqual(mod.bar(10, 1), 9)
|
||||
|
||||
def test_null_slots(self):
|
||||
# Test that NULL slots aren't a problem.
|
||||
name = self.name + '_null_slots'
|
||||
module = self.load_module_by_name(name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, name)
|
||||
|
||||
|
||||
(Frozen_NonModuleExtensionTests,
|
||||
Source_NonModuleExtensionTests
|
||||
) = util.test_both(NonModuleExtensionTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -10,7 +10,8 @@ import unittest
|
|||
import warnings
|
||||
import importlib.util
|
||||
import importlib
|
||||
from test.support import MISSING_C_DOCSTRINGS
|
||||
from test import support
|
||||
from test.support import MISSING_C_DOCSTRINGS, script_helper
|
||||
|
||||
|
||||
class LoaderTests:
|
||||
|
@ -325,29 +326,6 @@ class MultiPhaseExtensionModuleTests(abc.LoaderTests):
|
|||
self.load_module_by_name(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
def test_nonmodule(self):
|
||||
# Test returning a non-module object from create works.
|
||||
name = self.name + '_nonmodule'
|
||||
mod = self.load_module_by_name(name)
|
||||
self.assertNotEqual(type(mod), type(unittest))
|
||||
self.assertEqual(mod.three, 3)
|
||||
|
||||
# issue 27782
|
||||
def test_nonmodule_with_methods(self):
|
||||
# Test creating a non-module object with methods defined.
|
||||
name = self.name + '_nonmodule_with_methods'
|
||||
mod = self.load_module_by_name(name)
|
||||
self.assertNotEqual(type(mod), type(unittest))
|
||||
self.assertEqual(mod.three, 3)
|
||||
self.assertEqual(mod.bar(10, 1), 9)
|
||||
|
||||
def test_null_slots(self):
|
||||
# Test that NULL slots aren't a problem.
|
||||
name = self.name + '_null_slots'
|
||||
module = self.load_module_by_name(name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, name)
|
||||
|
||||
def test_bad_modules(self):
|
||||
# Test SystemError is raised for misbehaving extensions.
|
||||
for name_base in [
|
||||
|
@ -401,5 +379,14 @@ class MultiPhaseExtensionModuleTests(abc.LoaderTests):
|
|||
) = util.test_both(MultiPhaseExtensionModuleTests, machinery=machinery)
|
||||
|
||||
|
||||
class NonModuleExtensionTests(unittest.TestCase):
|
||||
def test_nonmodule_cases(self):
|
||||
# The test cases in this file cause the GIL to be enabled permanently
|
||||
# in free-threaded builds, so they are run in a subprocess to isolate
|
||||
# this effect.
|
||||
script = support.findfile("test_importlib/extension/_test_nonmodule_cases.py")
|
||||
script_helper.run_test_script(script)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue