Skip to content

Commit abb8265

Browse files
[3.12] gh-117378: Only run the new multiprocessing SysPath test when appropriate (GH-126635) (GH-126653)
gh-117378: Only run the new multiprocessing SysPath test when appropriate (GH-126635) The first version had it running two forkserver and one spawn tests underneath each of the _fork, _forkserver, and _spawn test suites that build off the generic one. This adds to the existing complexity of the multiprocessing test suite by offering BaseTestCase classes another attribute to control which suites they are invoked under. Practicality vs purity here. :/ Net result: we don't over-run the new test and their internal logic is simplified. (cherry picked from commit ca878b6) Co-authored-by: Gregory P. Smith <greg@krypto.org>
1 parent c47c641 commit abb8265

File tree

1 file changed

+30
-29
lines changed

1 file changed

+30
-29
lines changed

Lib/test/_test_multiprocessing.py

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ def __call__(self, *args, **kwds):
258258
class BaseTestCase(object):
259259

260260
ALLOWED_TYPES = ('processes', 'manager', 'threads')
261+
# If not empty, limit which start method suites run this class.
262+
START_METHODS: set[str] = set()
263+
start_method = None # set by install_tests_in_module_dict()
261264

262265
def assertTimingAlmostEqual(self, a, b):
263266
if CHECK_TIMINGS:
@@ -6202,7 +6205,9 @@ def submain(): pass
62026205
class _TestSpawnedSysPath(BaseTestCase):
62036206
"""Test that sys.path is setup in forkserver and spawn processes."""
62046207

6205-
ALLOWED_TYPES = ('processes',)
6208+
ALLOWED_TYPES = {'processes'}
6209+
# Not applicable to fork which inherits everything from the process as is.
6210+
START_METHODS = {"forkserver", "spawn"}
62066211

62076212
def setUp(self):
62086213
self._orig_sys_path = list(sys.path)
@@ -6214,11 +6219,8 @@ def setUp(self):
62146219
sys.path[:] = [p for p in sys.path if p] # remove any existing ""s
62156220
sys.path.insert(0, self._temp_dir)
62166221
sys.path.insert(0, "") # Replaced with an abspath in child.
6217-
try:
6218-
self._ctx_forkserver = multiprocessing.get_context("forkserver")
6219-
except ValueError:
6220-
self._ctx_forkserver = None
6221-
self._ctx_spawn = multiprocessing.get_context("spawn")
6222+
self.assertIn(self.start_method, self.START_METHODS)
6223+
self._ctx = multiprocessing.get_context(self.start_method)
62226224

62236225
def tearDown(self):
62246226
sys.path[:] = self._orig_sys_path
@@ -6229,15 +6231,15 @@ def enq_imported_module_names(queue):
62296231
queue.put(tuple(sys.modules))
62306232

62316233
def test_forkserver_preload_imports_sys_path(self):
6232-
ctx = self._ctx_forkserver
6233-
if not ctx:
6234-
self.skipTest("requires forkserver start method.")
6234+
if self._ctx.get_start_method() != "forkserver":
6235+
self.skipTest("forkserver specific test.")
62356236
self.assertNotIn(self._mod_name, sys.modules)
62366237
multiprocessing.forkserver._forkserver._stop() # Must be fresh.
6237-
ctx.set_forkserver_preload(
6238+
self._ctx.set_forkserver_preload(
62386239
["test.test_multiprocessing_forkserver", self._mod_name])
6239-
q = ctx.Queue()
6240-
proc = ctx.Process(target=self.enq_imported_module_names, args=(q,))
6240+
q = self._ctx.Queue()
6241+
proc = self._ctx.Process(
6242+
target=self.enq_imported_module_names, args=(q,))
62416243
proc.start()
62426244
proc.join()
62436245
child_imported_modules = q.get()
@@ -6255,23 +6257,19 @@ def enq_sys_path_and_import(queue, mod_name):
62556257
queue.put(None)
62566258

62576259
def test_child_sys_path(self):
6258-
for ctx in (self._ctx_spawn, self._ctx_forkserver):
6259-
if not ctx:
6260-
continue
6261-
with self.subTest(f"{ctx.get_start_method()} start method"):
6262-
q = ctx.Queue()
6263-
proc = ctx.Process(target=self.enq_sys_path_and_import,
6264-
args=(q, self._mod_name))
6265-
proc.start()
6266-
proc.join()
6267-
child_sys_path = q.get()
6268-
import_error = q.get()
6269-
q.close()
6270-
self.assertNotIn("", child_sys_path) # replaced by an abspath
6271-
self.assertIn(self._temp_dir, child_sys_path) # our addition
6272-
# ignore the first element, it is the absolute "" replacement
6273-
self.assertEqual(child_sys_path[1:], sys.path[1:])
6274-
self.assertIsNone(import_error, msg=f"child could not import {self._mod_name}")
6260+
q = self._ctx.Queue()
6261+
proc = self._ctx.Process(
6262+
target=self.enq_sys_path_and_import, args=(q, self._mod_name))
6263+
proc.start()
6264+
proc.join()
6265+
child_sys_path = q.get()
6266+
import_error = q.get()
6267+
q.close()
6268+
self.assertNotIn("", child_sys_path) # replaced by an abspath
6269+
self.assertIn(self._temp_dir, child_sys_path) # our addition
6270+
# ignore the first element, it is the absolute "" replacement
6271+
self.assertEqual(child_sys_path[1:], sys.path[1:])
6272+
self.assertIsNone(import_error, msg=f"child could not import {self._mod_name}")
62756273

62766274

62776275
class MiscTestCase(unittest.TestCase):
@@ -6450,6 +6448,8 @@ def install_tests_in_module_dict(remote_globs, start_method,
64506448
if base is BaseTestCase:
64516449
continue
64526450
assert set(base.ALLOWED_TYPES) <= ALL_TYPES, base.ALLOWED_TYPES
6451+
if base.START_METHODS and start_method not in base.START_METHODS:
6452+
continue # class not intended for this start method.
64536453
for type_ in base.ALLOWED_TYPES:
64546454
if only_type and type_ != only_type:
64556455
continue
@@ -6463,6 +6463,7 @@ class Temp(base, Mixin, unittest.TestCase):
64636463
Temp = hashlib_helper.requires_hashdigest('sha256')(Temp)
64646464
Temp.__name__ = Temp.__qualname__ = newname
64656465
Temp.__module__ = __module__
6466+
Temp.start_method = start_method
64666467
remote_globs[newname] = Temp
64676468
elif issubclass(base, unittest.TestCase):
64686469
if only_type:

0 commit comments

Comments
 (0)