mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
Merged revisions 78136 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r78136 | ezio.melotti | 2010-02-10 23:40:33 +0200 (Wed, 10 Feb 2010) | 1 line #7712: add a temp_cwd context manager to test_support and use it in regrtest to run all the tests in a temporary directory, saving the original CWD in test_support.SAVEDCWD. Thanks to Florent Xicluna who helped with the patch. ........
This commit is contained in:
parent
a3211ee8d4
commit
184bdfb03a
4 changed files with 98 additions and 27 deletions
|
@ -158,6 +158,24 @@ import traceback
|
||||||
import warnings
|
import warnings
|
||||||
import unittest
|
import unittest
|
||||||
from inspect import isabstract
|
from inspect import isabstract
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
# Some times __path__ and __file__ are not absolute (e.g. while running from
|
||||||
|
# Lib/) and, if we change the CWD to run the tests in a temporary dir, some
|
||||||
|
# imports might fail. This affects only the modules imported before os.chdir().
|
||||||
|
# These modules are searched first in sys.path[0] (so '' -- the CWD) and if
|
||||||
|
# they are found in the CWD their __file__ and __path__ will be relative (this
|
||||||
|
# happens before the chdir). All the modules imported after the chdir, are
|
||||||
|
# not found in the CWD, and since the other paths in sys.path[1:] are absolute
|
||||||
|
# (site.py absolutize them), the __file__ and __path__ will be absolute too.
|
||||||
|
# Therefore it is necessary to absolutize manually the __file__ and __path__ of
|
||||||
|
# the packages to prevent later imports to fail when the CWD is different.
|
||||||
|
for module in sys.modules.values():
|
||||||
|
if hasattr(module, '__path__'):
|
||||||
|
module.__path__ = [os.path.abspath(path) for path in module.__path__]
|
||||||
|
if hasattr(module, '__file__'):
|
||||||
|
module.__file__ = os.path.abspath(module.__file__)
|
||||||
|
|
||||||
|
|
||||||
# Ignore ImportWarnings that only occur in the source tree,
|
# Ignore ImportWarnings that only occur in the source tree,
|
||||||
# (because of modules with the same name as source-directories in Modules/)
|
# (because of modules with the same name as source-directories in Modules/)
|
||||||
|
@ -375,6 +393,9 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
resource_denieds = []
|
resource_denieds = []
|
||||||
environment_changed = []
|
environment_changed = []
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print('The CWD is now', os.getcwd())
|
||||||
|
|
||||||
if findleaks:
|
if findleaks:
|
||||||
try:
|
try:
|
||||||
import gc
|
import gc
|
||||||
|
@ -389,8 +410,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
found_garbage = []
|
found_garbage = []
|
||||||
|
|
||||||
if single:
|
if single:
|
||||||
from tempfile import gettempdir
|
filename = 'pynexttest'
|
||||||
filename = os.path.join(gettempdir(), 'pynexttest')
|
|
||||||
try:
|
try:
|
||||||
fp = open(filename, 'r')
|
fp = open(filename, 'r')
|
||||||
next_test = fp.read().strip()
|
next_test = fp.read().strip()
|
||||||
|
@ -401,7 +421,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
|
||||||
|
|
||||||
if fromfile:
|
if fromfile:
|
||||||
tests = []
|
tests = []
|
||||||
fp = open(fromfile)
|
fp = open(os.path.join(support.SAVEDCWD, fromfile))
|
||||||
for line in fp:
|
for line in fp:
|
||||||
guts = line.split() # assuming no test has whitespace in its name
|
guts = line.split() # assuming no test has whitespace in its name
|
||||||
if guts and not guts[0].startswith('#'):
|
if guts and not guts[0].startswith('#'):
|
||||||
|
@ -966,6 +986,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
|
||||||
|
|
||||||
deltas = []
|
deltas = []
|
||||||
nwarmup, ntracked, fname = huntrleaks
|
nwarmup, ntracked, fname = huntrleaks
|
||||||
|
fname = os.path.join(support.SAVEDCWD, fname)
|
||||||
repcount = nwarmup + ntracked
|
repcount = nwarmup + ntracked
|
||||||
print("beginning", repcount, "repetitions", file=sys.stderr)
|
print("beginning", repcount, "repetitions", file=sys.stderr)
|
||||||
print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr)
|
print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr)
|
||||||
|
@ -1412,4 +1433,23 @@ if __name__ == '__main__':
|
||||||
i -= 1
|
i -= 1
|
||||||
if os.path.abspath(os.path.normpath(sys.path[i])) == mydir:
|
if os.path.abspath(os.path.normpath(sys.path[i])) == mydir:
|
||||||
del sys.path[i]
|
del sys.path[i]
|
||||||
main()
|
|
||||||
|
# findtestdir() gets the dirname out of sys.argv[0], so we have to make it
|
||||||
|
# absolute before changing the CWD.
|
||||||
|
if sys.argv[0]:
|
||||||
|
sys.argv[0] = os.path.abspath(sys.argv[0])
|
||||||
|
|
||||||
|
|
||||||
|
# Define a writable temp dir that will be used as cwd while running
|
||||||
|
# the tests. The name of the dir includes the pid to allow parallel
|
||||||
|
# testing (see the -j option).
|
||||||
|
TESTCWD = 'test_python_{}'.format(os.getpid())
|
||||||
|
|
||||||
|
TESTCWD = os.path.abspath(os.path.join(tempfile.gettempdir(), TESTCWD))
|
||||||
|
|
||||||
|
# Run the tests in a context manager that temporary changes the CWD to a
|
||||||
|
# temporary and writable directory. If it's not possible to create or
|
||||||
|
# change the CWD, the original CWD will be used. The original CWD is
|
||||||
|
# available from support.SAVEDCWD.
|
||||||
|
with support.temp_cwd(TESTCWD, quiet=True):
|
||||||
|
main()
|
||||||
|
|
|
@ -21,8 +21,8 @@ __all__ = ["Error", "TestFailed", "ResourceDenied", "import_module",
|
||||||
"verbose", "use_resources", "max_memuse", "record_original_stdout",
|
"verbose", "use_resources", "max_memuse", "record_original_stdout",
|
||||||
"get_original_stdout", "unload", "unlink", "rmtree", "forget",
|
"get_original_stdout", "unload", "unlink", "rmtree", "forget",
|
||||||
"is_resource_enabled", "requires", "find_unused_port", "bind_port",
|
"is_resource_enabled", "requires", "find_unused_port", "bind_port",
|
||||||
"fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "findfile",
|
"fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "SAVEDCWD", "temp_cwd",
|
||||||
"sortdict", "check_syntax_error", "open_urlresource",
|
"findfile", "sortdict", "check_syntax_error", "open_urlresource",
|
||||||
"check_warnings", "CleanImport", "EnvironmentVarGuard",
|
"check_warnings", "CleanImport", "EnvironmentVarGuard",
|
||||||
"TransientResource", "captured_output", "captured_stdout",
|
"TransientResource", "captured_output", "captured_stdout",
|
||||||
"time_out", "socket_peer_reset", "ioerror_peer_reset",
|
"time_out", "socket_peer_reset", "ioerror_peer_reset",
|
||||||
|
@ -338,7 +338,7 @@ else:
|
||||||
|
|
||||||
# Disambiguate TESTFN for parallel testing, while letting it remain a valid
|
# Disambiguate TESTFN for parallel testing, while letting it remain a valid
|
||||||
# module name.
|
# module name.
|
||||||
TESTFN = "{0}_{1}_tmp".format(TESTFN, os.getpid())
|
TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid())
|
||||||
|
|
||||||
# Assuming sys.getfilesystemencoding()!=sys.getdefaultencoding()
|
# Assuming sys.getfilesystemencoding()!=sys.getdefaultencoding()
|
||||||
# TESTFN_UNICODE is a filename that can be encoded using the
|
# TESTFN_UNICODE is a filename that can be encoded using the
|
||||||
|
@ -369,23 +369,37 @@ else:
|
||||||
'Unicode filename tests may not be effective'
|
'Unicode filename tests may not be effective'
|
||||||
% TESTFN_UNICODE_UNENCODEABLE)
|
% TESTFN_UNICODE_UNENCODEABLE)
|
||||||
|
|
||||||
# Make sure we can write to TESTFN, try in /tmp if we can't
|
# Save the initial cwd
|
||||||
fp = None
|
SAVEDCWD = os.getcwd()
|
||||||
try:
|
|
||||||
fp = open(TESTFN, 'w+')
|
@contextlib.contextmanager
|
||||||
except IOError:
|
def temp_cwd(name='tempcwd', quiet=False):
|
||||||
TMP_TESTFN = os.path.join('/tmp', TESTFN)
|
"""
|
||||||
|
Context manager that creates a temporary directory and set it as CWD.
|
||||||
|
|
||||||
|
The new CWD is created in the current directory and it's named *name*.
|
||||||
|
If *quiet* is False (default) and it's not possible to create or change
|
||||||
|
the CWD, an error is raised. If it's True, only a warning is raised
|
||||||
|
and the original CWD is used.
|
||||||
|
"""
|
||||||
|
saved_dir = os.getcwd()
|
||||||
|
is_temporary = False
|
||||||
try:
|
try:
|
||||||
fp = open(TMP_TESTFN, 'w+')
|
os.mkdir(name)
|
||||||
TESTFN = TMP_TESTFN
|
os.chdir(name)
|
||||||
del TMP_TESTFN
|
is_temporary = True
|
||||||
except IOError:
|
except OSError:
|
||||||
print(('WARNING: tests will fail, unable to write to: %s or %s' %
|
if not quiet:
|
||||||
(TESTFN, TMP_TESTFN)))
|
raise
|
||||||
if fp is not None:
|
warnings.warn('tests may fail, unable to change the CWD to ' + name,
|
||||||
fp.close()
|
RuntimeWarning, stacklevel=3)
|
||||||
unlink(TESTFN)
|
try:
|
||||||
del fp
|
yield os.getcwd()
|
||||||
|
finally:
|
||||||
|
os.chdir(saved_dir)
|
||||||
|
if is_temporary:
|
||||||
|
rmtree(name)
|
||||||
|
|
||||||
|
|
||||||
def findfile(file, here=__file__):
|
def findfile(file, here=__file__):
|
||||||
"""Try to find a file on sys.path and the working directory. If it is not
|
"""Try to find a file on sys.path and the working directory. If it is not
|
||||||
|
|
|
@ -7,6 +7,7 @@ import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
|
import sysconfig
|
||||||
|
|
||||||
mswindows = (sys.platform == "win32")
|
mswindows = (sys.platform == "win32")
|
||||||
|
|
||||||
|
@ -141,10 +142,21 @@ class ProcessTestCase(unittest.TestCase):
|
||||||
p.wait()
|
p.wait()
|
||||||
self.assertEqual(p.stderr, None)
|
self.assertEqual(p.stderr, None)
|
||||||
|
|
||||||
def test_executable(self):
|
def test_executable_with_cwd(self):
|
||||||
arg0 = os.path.join(os.path.dirname(sys.executable),
|
python_dir = os.path.dirname(os.path.realpath(sys.executable))
|
||||||
"somethingyoudonthave")
|
p = subprocess.Popen(["somethingyoudonthave", "-c",
|
||||||
p = subprocess.Popen([arg0, "-c", "import sys; sys.exit(47)"],
|
"import sys; sys.exit(47)"],
|
||||||
|
executable=sys.executable, cwd=python_dir)
|
||||||
|
p.wait()
|
||||||
|
self.assertEqual(p.returncode, 47)
|
||||||
|
|
||||||
|
@unittest.skipIf(sysconfig.is_python_build(),
|
||||||
|
"need an installed Python. See #7774")
|
||||||
|
def test_executable_without_cwd(self):
|
||||||
|
# For a normal installation, it should work without 'cwd'
|
||||||
|
# argument. For test runs in the build directory, see #7774.
|
||||||
|
p = subprocess.Popen(["somethingyoudonthave", "-c",
|
||||||
|
"import sys; sys.exit(47)"],
|
||||||
executable=sys.executable)
|
executable=sys.executable)
|
||||||
p.wait()
|
p.wait()
|
||||||
self.assertEqual(p.returncode, 47)
|
self.assertEqual(p.returncode, 47)
|
||||||
|
|
|
@ -740,6 +740,11 @@ Documentation
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #7712: test.support gained a new `temp_cwd` context manager which is
|
||||||
|
now also used by regrtest to run all the tests in a temporary directory.
|
||||||
|
The original CWD is saved in `support.SAVEDCWD`.
|
||||||
|
Thanks to Florent Xicluna who helped with the patch.
|
||||||
|
|
||||||
- Issue #7924: Fix an intermittent 'XXX undetected error' failure in
|
- Issue #7924: Fix an intermittent 'XXX undetected error' failure in
|
||||||
test_capi (only seen so far on platforms where the curses module
|
test_capi (only seen so far on platforms where the curses module
|
||||||
wasn't built), due to an uncleared exception.
|
wasn't built), due to an uncleared exception.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue