8000 Add test_imp.ImportTests.test_singlephase_multiple_interpreters. · python/cpython@49e4bfe · GitHub
[go: up one dir, main page]

Skip to content

Commit 49e4bfe

Browse files
Add test_imp.ImportTests.test_singlephase_multiple_interpreters.
1 parent 096d009 commit 49e4bfe

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

Lib/test/test_imp.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import gc
22
import importlib
33
import importlib.util
4+
import shutil
45
import os
56
import os.path
67
import py_compile
78
import sys
9+
import tempfile
810
from test import support
911
from test.support import import_helper
1012
from test.support import os_helper
1113
from test.support import script_helper
1214
from test.support import warnings_helper
15+
import textwrap
1316
import unittest
1417
import warnings
1518
imp = warnings_helper.import_deprecated('imp')
1619
import _imp
20+
import _xxsubinterpreters as _interpreters
1721

1822

1923
OS_PATH_NAME = os.path.__name__
@@ -67,6 +71,17 @@ def setUp(self):
6771
self.test_strings = mod.test_strings
6872
self.test_path = mod.__path__
6973

74+
def _copy_extension(self, name):
75+
fileobj, pathname, _ = imp.find_module('_testsinglephase')
76+
fileobj.close()
77+
78+
dirname = tempfile.mkdtemp()
79+
self.addCleanup(os_helper.rmtree, dirname)
80+
81+
copied = os.path.join(dirname, os.path.basename(pathname))
82+
shutil.copyfile(pathname, copied)
83+
return copied
84+
7085
# test_import_encoded_module moved to test_source_encoding.py
7186

7287
def test_find_module_encoding(self):
@@ -251,6 +266,48 @@ def test_issue16421_multiple_modules_in_one_dll(self):
251266
with self.assertRaises(ImportError):
252267
imp.load_dynamic('nonexistent', pathname)
253268

269+
@requires_load_dynamic
270+
def test_singlephase_multiple_interpreters(self):
271+
# Currently, for every single-phrase init module loaded
272+
# in multiple interpreters, those interpreters share a
273+
# PyModuleDef for that object, which can be a problem.
274+
275+
# This single-phase module has global state, which is shared
276+
# by the interpreters.
277+
name = '_testsinglephase'
278+
filename = self._copy_extension(name)
279+
280+
interp1 = _interpreters.create(isolated=False)
281+
self.addCleanup(_interpreters.destroy, interp1)
282+
interp2 = _interpreters.create(isolated=False)
283+
self.addCleanup(_interpreters.destroy, interp2)
284+
285+
script = textwrap.dedent(f'''
286+
from test.support import warnings_helper
287+
imp = warnings_helper.import_deprecated('imp')
288+
module = imp.load_dynamic({name!r}, {filename!r})
289+
290+
init_count = module.initialized_count()
291+
if init_count != %d:
292+
raise Exception(init_count)
293+
294+
lookedup = module.look_up_self()
295+
if lookedup is not module:
296+
raise Exception((module, lookedup))
297+
''')
298+
# Use an interpreter that gets destroyed right away.
299+
ret = support.run_in_subinterp(script % 1)
300+
self.assertEqual(ret, 0)
301+
302+
# The module's init func gets run again.
303+
# The module's globals did not get destroyed.
304+
_interpreters.run_string(interp1, script % 2)
305+
306+
# The module's init func is not run again.
307+
# The second interpreter copies the module's m_copy.
308+
# However, globals are still shared.
309+
_interpreters.run_string(interp2, script % 2)
310+
254311
@requires_load_dynamic
255312
def test_singlephase_variants(self):
256313
'''Exercise the most meaningful variants described in Python/import.c.'''

0 commit comments

Comments
 (0)
0