11import datetime
22import faulthandler
3- import json
43import locale
54import os
65import platform
2221from test import support
2322
2423
25- # When tests are run from the Python build directory, it is best practice
26- # to keep the test files in a subfolder. This eases the cleanup of leftover
27- # files using the "make distclean" command.
28- if sysconfig .is_python_build ():
29- TEMPDIR = sysconfig .get_config_var ('abs_builddir' )
30- if TEMPDIR is None :
31- # bpo-30284: On Windows, only srcdir is available. Using abs_builddir
32- # mostly matters on UNIX when building Python out of the source tree,
33- # especially when the source tree is read only.
34- TEMPDIR = sysconfig .get_config_var ('srcdir' )
35- TEMPDIR = os .path .join (TEMPDIR , 'build' )
36- else :
37- TEMPDIR = tempfile .gettempdir ()
38- TEMPDIR = os .path .abspath (TEMPDIR )
39-
40-
4124class Regrtest :
4225 """Execute a test suite.
4326
@@ -98,7 +81,10 @@ def __init__(self):
9881 # used by --junit-xml
9982 self .testsuite_xml = None
10083
84+ # misc
10185 self .win_load_tracker = None
86+ self .tmp_dir = None
87+ self .worker_test_name = None
10288
10389 def get_executed (self ):
10490 return (set (self .good ) | set (self .bad ) | set (self .skipped )
@@ -177,6 +163,13 @@ def parse_args(self, kwargs):
177163 if ns .xmlpath :
178164 support .junit_xml_list = self .testsuite_xml = []
179165
166+ worker_args = ns .worker_args
167+ if worker_args is not None :
168+ from test .libregrtest .runtest_mp import parse_worker_args
169+ ns , test_name = parse_worker_args (ns .worker_args )
170+ ns .worker_args = worker_args
171+ self .worker_test_name = test_name
172+
180173 # Strip .py extensions.
181174 removepy (ns .args )
182175
@@ -186,7 +179,7 @@ def find_tests(self, tests):
186179 self .tests = tests
187180
188181 if self .ns .single :
189- self .next_single_filename = os .path .join (TEMPDIR , 'pynexttest' )
182+ self .next_single_filename = os .path .join (self . tmp_dir , 'pynexttest' )
190183 try :
191184 with open (self .next_single_filename , 'r' ) as fp :
192185 next_test = fp .read ().strip ()
@@ -544,29 +537,54 @@ def save_xml_result(self):
544537 for s in ET .tostringlist (root ):
545538 f .write (s )
546539
547- def main (self , tests = None , ** kwargs ):
548- global TEMPDIR
549- self .ns = self .parse_args (kwargs )
550-
540+ def create_temp_dir (self ):
551541 if self .ns .tempdir :
552- TEMPDIR = self .ns .tempdir
553- elif self .ns .worker_args :
554- ns_dict , _ = json .loads (self .ns .worker_args )
555- TEMPDIR = ns_dict .get ("tempdir" ) or TEMPDIR
542+ self .tmp_dir = self .ns .tempdir
543+
544+ if not self .tmp_dir :
545+ # When tests are run from the Python build directory, it is best practice
546+ # to keep the test files in a subfolder. This eases the cleanup of leftover
547+ # files using the "make distclean" command.
548+ if sysconfig .is_python_build ():
549+ self .tmp_dir = sysconfig .get_config_var ('abs_builddir' )
550+ if self .tmp_dir is None :
551+ # bpo-30284: On Windows, only srcdir is available. Using
552+ # abs_builddir mostly matters on UNIX when building Python
553+ # out of the source tree, especially when the source tree
554+ # is read only.
555+ self .tmp_dir = sysconfig .get_config_var ('srcdir' )
556+ self .tmp_dir = os .path .join (self .tmp_dir , 'build' )
557+ else :
558+ self .tmp_dir = tempfile .gettempdir ()
556559
557- os .makedirs (TEMPDIR , exist_ok = True )
560+ self .tmp_dir = os .path .abspath (self .tmp_dir )
561+ os .makedirs (self .tmp_dir , exist_ok = True )
558562
559563 # Define a writable temp dir that will be used as cwd while running
560564 # the tests. The name of the dir includes the pid to allow parallel
561565 # testing (see the -j option).
562- test_cwd = 'test_python_{}' .format (os .getpid ())
563- test_cwd = os .path .join (TEMPDIR , test_cwd )
566+ pid = os .getpid ()
567+ if self .worker_test_name is not None :
568+ test_cwd = 'worker_{}' .format (pid )
569+ else :
570+ test_cwd = 'test_python_{}' .format (pid )
571+ test_cwd = os .path .join (self .tmp_dir , test_cwd )
572+ return test_cwd
573+
574+ def main (self , tests = None , ** kwargs ):
575+ self .ns = self .parse_args (kwargs )
576+
577+ test_cwd = self .create_temp_dir ()
564578
565- # Run the tests in a context manager that temporarily changes the CWD to a
566- # temporary and writable directory. If it's not possible to create or
567- # change the CWD, the original CWD will be used. The original CWD is
568- # available from support.SAVEDCWD.
579+ # Run the tests in a context manager that temporarily changes the CWD
580+ # to a temporary and writable directory. If it's not possible to
581+ # create or change the CWD, the original CWD will be used.
582+ # The original CWD is available from support.SAVEDCWD.
569583 with support .temp_cwd (test_cwd , quiet = True ):
584+ # When using multiprocessing, worker processes will use test_cwd
585+ # as their parent temporary directory. So when the main process
586+ # exit, it removes also subdirectories of worker processes.
587+ self .ns .tempdir = test_cwd
570588 self ._main (tests , kwargs )
571589
572590 def getloadavg (self ):
@@ -588,9 +606,9 @@ def _main(self, tests, kwargs):
588606 print (msg , file = sys .stderr , flush = True )
589607 sys .exit (2 )
590608
591- if self .ns . worker_args is not None :
609+ if self .worker_test_name is not None :
592610 from test .libregrtest .runtest_mp import run_tests_worker
593- run_tests_worker (self .ns . worker_args )
611+ run_tests_worker (self .ns , self . worker_test_name )
594612
595613 if self .ns .wait :
596614 input ("Press any key to continue..." )
@@ -611,7 +629,7 @@ def _main(self, tests, kwargs):
611629
612630 # If we're on windows and this is the parent runner (not a worker),
613631 # track the load average.
614- if sys .platform == 'win32' and ( self .ns . worker_args is None ) :
632+ if sys .platform == 'win32' and self .worker_test_name is None :
615633 from test .libregrtest .win_utils import WindowsLoadTracker
616634
617635 try :
0 commit comments