@@ -258,6 +258,9 @@ def __call__(self, *args, **kwds):
258258class  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 :
@@ -6349,7 +6352,9 @@ def test_atexit(self):
63496352class  _TestSpawnedSysPath (BaseTestCase ):
63506353    """Test that sys.path is setup in forkserver and spawn processes.""" 
63516354
6352-     ALLOWED_TYPES  =  ('processes' ,)
6355+     ALLOWED_TYPES  =  {'processes' }
6356+     # Not applicable to fork which inherits everything from the process as is. 
6357+     START_METHODS  =  {"forkserver" , "spawn" }
63536358
63546359    def  setUp (self ):
63556360        self ._orig_sys_path  =  list (sys .path )
@@ -6361,11 +6366,8 @@ def setUp(self):
63616366        sys .path [:] =  [p  for  p  in  sys .path  if  p ]  # remove any existing ""s 
63626367        sys .path .insert (0 , self ._temp_dir )
63636368        sys .path .insert (0 , "" )  # Replaced with an abspath in child. 
6364-         try :
6365-             self ._ctx_forkserver  =  multiprocessing .get_context ("forkserver" )
6366-         except  ValueError :
6367-             self ._ctx_forkserver  =  None 
6368-         self ._ctx_spawn  =  multiprocessing .get_context ("spawn" )
6369+         self .assertIn (self .start_method , self .START_METHODS )
6370+         self ._ctx  =  multiprocessing .get_context (self .start_method )
63696371
63706372    def  tearDown (self ):
63716373        sys .path [:] =  self ._orig_sys_path 
@@ -6376,15 +6378,15 @@ def enq_imported_module_names(queue):
63766378        queue .put (tuple (sys .modules ))
63776379
63786380    def  test_forkserver_preload_imports_sys_path (self ):
6379-         ctx  =  self ._ctx_forkserver 
6380-         if  not  ctx :
6381-             self .skipTest ("requires forkserver start method." )
6381+         if  self ._ctx .get_start_method () !=  "forkserver" :
6382+             self .skipTest ("forkserver specific test." )
63826383        self .assertNotIn (self ._mod_name , sys .modules )
63836384        multiprocessing .forkserver ._forkserver ._stop ()  # Must be fresh. 
6384-         ctx .set_forkserver_preload (
6385+         self . _ctx .set_forkserver_preload (
63856386            ["test.test_multiprocessing_forkserver" , self ._mod_name ])
6386-         q  =  ctx .Queue ()
6387-         proc  =  ctx .Process (target = self .enq_imported_module_names , args = (q ,))
6387+         q  =  self ._ctx .Queue ()
6388+         proc  =  self ._ctx .Process (
6389+                 target = self .enq_imported_module_names , args = (q ,))
63886390        proc .start ()
63896391        proc .join ()
63906392        child_imported_modules  =  q .get ()
@@ -6402,23 +6404,19 @@ def enq_sys_path_and_import(queue, mod_name):
64026404            queue .put (None )
64036405
64046406    def  test_child_sys_path (self ):
6405-         for  ctx  in  (self ._ctx_spawn , self ._ctx_forkserver ):
6406-             if  not  ctx :
6407-                 continue 
6408-             with  self .subTest (f"{ ctx .get_start_method ()}  ):
6409-                 q  =  ctx .Queue ()
6410-                 proc  =  ctx .Process (target = self .enq_sys_path_and_import ,
6411-                                    args = (q , self ._mod_name ))
6412-                 proc .start ()
6413-                 proc .join ()
6414-                 child_sys_path  =  q .get ()
6415-                 import_error  =  q .get ()
6416-                 q .close ()
6417-                 self .assertNotIn ("" , child_sys_path )  # replaced by an abspath 
6418-                 self .assertIn (self ._temp_dir , child_sys_path )  # our addition 
6419-                 # ignore the first element, it is the absolute "" replacement 
6420-                 self .assertEqual (child_sys_path [1 :], sys .path [1 :])
6421-                 self .assertIsNone (import_error , msg = f"child could not import { self ._mod_name }  )
6407+         q  =  self ._ctx .Queue ()
6408+         proc  =  self ._ctx .Process (
6409+                 target = self .enq_sys_path_and_import , args = (q , self ._mod_name ))
6410+         proc .start ()
6411+         proc .join ()
6412+         child_sys_path  =  q .get ()
6413+         import_error  =  q .get ()
6414+         q .close ()
6415+         self .assertNotIn ("" , child_sys_path )  # replaced by an abspath 
6416+         self .assertIn (self ._temp_dir , child_sys_path )  # our addition 
6417+         # ignore the first element, it is the absolute "" replacement 
6418+         self .assertEqual (child_sys_path [1 :], sys .path [1 :])
6419+         self .assertIsNone (import_error , msg = f"child could not import { self ._mod_name }  )
64226420
64236421
64246422class  MiscTestCase (unittest .TestCase ):
@@ -6615,6 +6613,8 @@ def install_tests_in_module_dict(remote_globs, start_method,
66156613            if  base  is  BaseTestCase :
66166614                continue 
66176615            assert  set (base .ALLOWED_TYPES ) <=  ALL_TYPES , base .ALLOWED_TYPES 
6616+             if  base .START_METHODS  and  start_method  not  in base .START_METHODS :
6617+                 continue   # class not intended for this start method. 
66186618            for  type_  in  base .ALLOWED_TYPES :
66196619                if  only_type  and  type_  !=  only_type :
66206620                    continue 
@@ -6628,6 +6628,7 @@ class Temp(base, Mixin, unittest.TestCase):
66286628                    Temp  =  hashlib_helper .requires_hashdigest ('sha256' )(Temp )
66296629                Temp .__name__  =  Temp .__qualname__  =  newname 
66306630                Temp .__module__  =  __module__ 
6631+                 Temp .start_method  =  start_method 
66316632                remote_globs [newname ] =  Temp 
66326633        elif  issubclass (base , unittest .TestCase ):
66336634            if  only_type :
0 commit comments