--- Lib/site.py +++ Lib/site.py @@ -514,8 +514,9 @@ known_paths = removeduppaths() if ENABLE_USER_SITE is None: ENABLE_USER_SITE = check_enableusersite() - known_paths = addusersitepackages(known_paths) - known_paths = addsitepackages(known_paths) + if os.environ.get("_PYTHONNOSITEPACKAGES") is None: + known_paths = addusersitepackages(known_paths) + known_paths = addsitepackages(known_paths) if sys.platform == 'os2emx': setBEGINLIBPATH() setquit() --- Lib/test/regrtest.py +++ Lib/test/regrtest.py @@ -174,6 +174,7 @@ import unittest import warnings from inspect import isabstract +from subprocess import Popen, PIPE try: import threading @@ -510,6 +511,57 @@ support.use_resources = use_resources save_modules = sys.modules.keys() + opt_args = support.args_from_interpreter_flags() + base_cmd = [sys.executable] + opt_args + ['-m', 'test.regrtest'] + debug_output_pat = re.compile(r"\[\d+ refs\]$") + + def get_args_tuple(test, verbose, quiet, huntrleaks, debug, use_resources, + output_on_failure, failfast, match_tests): + return ( + (test, verbose, quiet), + dict(huntrleaks=huntrleaks, debug=debug, + use_resources=use_resources, + output_on_failure=output_on_failure, failfast=failfast, + match_tests=match_tests) + ) + + def _runtest(test, verbose, quiet, huntrleaks=False, debug=False, + use_resources=None, output_on_failure=False, failfast=False, + match_tests=None): + if test == "test_site": + args_tuple = get_args_tuple(test, verbose, quiet, huntrleaks, debug, + use_resources, output_on_failure, + failfast, match_tests) + env = os.environ.copy() + try: + del env["_PYTHONNOSITEPACKAGES"] + except KeyError: + pass + popen = Popen(base_cmd + ['--slaveargs', json.dumps(args_tuple)], + stdout=PIPE, stderr=PIPE, + universal_newlines=True, + close_fds=(os.name != 'nt'), + env=env) + stdout, stderr = popen.communicate() + # Strip last refcount output line if it exists, since it + # comes from the shutdown of the interpreter in the subcommand. + stderr = debug_output_pat.sub("", stderr) + stdout, _, result = stdout.strip().rpartition("\n") + result = json.loads(result) + if stdout: + print(stdout) + if stderr: + print(stderr, file=sys.stderr) + if result[0] == INTERRUPTED: + assert result[1] == 'KeyboardInterrupt' + raise KeyboardInterrupt + return result + else: + return runtest(test, verbose, quiet, huntrleaks=huntrleaks, + debug=debug, use_resources=use_resources, + output_on_failure=output_on_failure, + failfast=failfast, match_tests=match_tests) + def accumulate_result(test, result): ok, test_time = result test_times.append((test_time, test)) @@ -547,12 +599,8 @@ print("Multiprocess option requires thread support") sys.exit(2) from queue import Queue - from subprocess import Popen, PIPE - debug_output_pat = re.compile(r"\[\d+ refs\]$") output = Queue() pending = MultiprocessTests(tests) - opt_args = support.args_from_interpreter_flags() - base_cmd = [sys.executable] + opt_args + ['-m', 'test.regrtest'] def work(): # A worker thread. try: @@ -562,12 +610,9 @@ except StopIteration: output.put((None, None, None, None)) return - args_tuple = ( - (test, verbose, quiet), - dict(huntrleaks=huntrleaks, use_resources=use_resources, - debug=debug, output_on_failure=verbose3, - failfast=failfast, match_tests=match_tests) - ) + args_tuple = get_args_tuple(test, verbose, quiet, huntrleaks, + debug, use_resources, verbose3, + failfast, match_tests) # -E is needed by some tests, e.g. test_import # Running the child from the same working directory ensures # that TEMPDIR for the child is the same when @@ -632,13 +677,13 @@ if trace: # If we're tracing code coverage, then we don't exit with status # if on a false return value from main. - tracer.runctx('runtest(test, verbose, quiet)', + tracer.runctx('_runtest(test, verbose, quiet)', globals=globals(), locals=vars()) else: try: - result = runtest(test, verbose, quiet, huntrleaks, debug, - output_on_failure=verbose3, - failfast=failfast, match_tests=match_tests) + result = _runtest(test, verbose, quiet, huntrleaks, debug, + output_on_failure=verbose3, + failfast=failfast, match_tests=match_tests) accumulate_result(test, result) except KeyboardInterrupt: interrupted = True @@ -709,7 +754,7 @@ sys.stdout.flush() try: verbose = True - ok = runtest(test, True, quiet, huntrleaks, debug) + ok = _runtest(test, True, quiet, huntrleaks, debug) except KeyboardInterrupt: # print a newline separate from the ^C print() @@ -1077,8 +1122,9 @@ for name, get, restore in self.resource_info(): current = get() original = saved_values.pop(name) - # Check for changes to the resource's value - if current != original: + # Check for changes to the resource's value. test_site is always run + # in a subprocess and is allowed to change os.environ and sys.path. + if current != original and self.testname != "test_site": self.changed = True restore(original) if not self.quiet: --- Lib/test/test_site.py +++ Lib/test/test_site.py @@ -8,6 +8,7 @@ from test.support import run_unittest, TESTFN, EnvironmentVarGuard from test.support import captured_stderr import builtins +import imp import os import sys import re @@ -21,6 +22,9 @@ # already. if "site" in sys.modules: import site + if "_PYTHONNOSITEPACKAGES" in os.environ: + del os.environ["_PYTHONNOSITEPACKAGES"] + imp.reload(site) else: raise unittest.SkipTest("importation of site.py suppressed") --- Makefile.pre.in +++ Makefile.pre.in @@ -777,7 +777,7 @@ TESTOPTS= -l $(EXTRATESTOPTS) TESTPROG= $(srcdir)/Lib/test/regrtest.py -TESTPYTHON= $(RUNSHARED) ./$(BUILDPYTHON) -Wd -E -R -bb $(TESTPYTHONOPTS) +TESTPYTHON= _PYTHONNOSITEPACKAGES=1 $(RUNSHARED) ./$(BUILDPYTHON) -Wd -E -R -bb $(TESTPYTHONOPTS) test: all platform -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS)