mirror of https://github.com/python/cpython
Close #15415: Factor out temp dir helpers to test.support
Patch by Chris Jerdonek
This commit is contained in:
parent
69e3bda310
commit
5517596c04
|
@ -387,18 +387,40 @@ The :mod:`test.support` module defines the following functions:
|
||||||
self.assertEqual(captured, "hello")
|
self.assertEqual(captured, "hello")
|
||||||
|
|
||||||
|
|
||||||
.. function:: temp_cwd(name='tempcwd', quiet=False, path=None)
|
.. function:: temp_dir(path=None, quiet=False)
|
||||||
|
|
||||||
|
A context manager that creates a temporary directory at *path* and
|
||||||
|
yields the directory.
|
||||||
|
|
||||||
|
If *path* is None, the temporary directory is created using
|
||||||
|
:func:`tempfile.mkdtemp`. If *quiet* is ``False``, the context manager
|
||||||
|
raises an exception on error. Otherwise, if *path* is specified and
|
||||||
|
cannot be created, only a warning is issued.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: change_cwd(path, quiet=False)
|
||||||
|
|
||||||
A context manager that temporarily changes the current working
|
A context manager that temporarily changes the current working
|
||||||
directory (CWD).
|
directory to *path* and yields the directory.
|
||||||
|
|
||||||
An existing path may be provided as *path*, in which case this function
|
If *quiet* is ``False``, the context manager raises an exception
|
||||||
makes no changes to the file system.
|
on error. Otherwise, it issues only a warning and keeps the current
|
||||||
|
working directory the same.
|
||||||
|
|
||||||
Otherwise, the new CWD is created in the current directory and it's named
|
|
||||||
*name*. If *quiet* is ``False`` and it's not possible to create or
|
.. function:: temp_cwd(name='tempcwd', quiet=False)
|
||||||
change the CWD, an error is raised. If it's ``True``, only a warning
|
|
||||||
is raised and the original CWD is used.
|
A context manager that temporarily creates a new directory and
|
||||||
|
changes the current working directory (CWD).
|
||||||
|
|
||||||
|
The context manager creates a temporary directory in the current
|
||||||
|
directory with name *name* before temporarily changing the current
|
||||||
|
working directory. If *name* is None, the temporary directory is
|
||||||
|
created using :func:`tempfile.mkdtemp`.
|
||||||
|
|
||||||
|
If *quiet* is ``False`` and it is not possible to create or change
|
||||||
|
the CWD, an error is raised. Otherwise, only a warning is raised
|
||||||
|
and the original CWD is used.
|
||||||
|
|
||||||
|
|
||||||
.. function:: temp_umask(umask)
|
.. function:: temp_umask(umask)
|
||||||
|
|
|
@ -13,7 +13,7 @@ import shutil
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from imp import source_from_cache
|
from imp import source_from_cache
|
||||||
from test.support import make_legacy_pyc, strip_python_stderr
|
from test.support import make_legacy_pyc, strip_python_stderr, temp_dir
|
||||||
|
|
||||||
# Executing the interpreter in a subprocess
|
# Executing the interpreter in a subprocess
|
||||||
def _assert_python(expected_success, *args, **env_vars):
|
def _assert_python(expected_success, *args, **env_vars):
|
||||||
|
@ -77,16 +77,6 @@ def kill_python(p):
|
||||||
subprocess._cleanup()
|
subprocess._cleanup()
|
||||||
return data
|
return data
|
||||||
|
|
||||||
# Script creation utilities
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def temp_dir():
|
|
||||||
dirname = tempfile.mkdtemp()
|
|
||||||
dirname = os.path.realpath(dirname)
|
|
||||||
try:
|
|
||||||
yield dirname
|
|
||||||
finally:
|
|
||||||
shutil.rmtree(dirname)
|
|
||||||
|
|
||||||
def make_script(script_dir, script_basename, source):
|
def make_script(script_dir, script_basename, source):
|
||||||
script_filename = script_basename+os.extsep+'py'
|
script_filename = script_basename+os.extsep+'py'
|
||||||
script_name = os.path.join(script_dir, script_filename)
|
script_name = os.path.join(script_dir, script_filename)
|
||||||
|
|
|
@ -738,45 +738,85 @@ else:
|
||||||
SAVEDCWD = os.getcwd()
|
SAVEDCWD = os.getcwd()
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def temp_cwd(name='tempcwd', quiet=False, path=None):
|
def temp_dir(path=None, quiet=False):
|
||||||
"""
|
"""Return a context manager that creates a temporary directory.
|
||||||
Context manager that temporarily changes the CWD.
|
|
||||||
|
|
||||||
An existing path may be provided as *path*, in which case this
|
Arguments:
|
||||||
function makes no changes to the file system.
|
|
||||||
|
path: the directory to create temporarily. If omitted or None,
|
||||||
|
defaults to creating a temporary directory using tempfile.mkdtemp.
|
||||||
|
|
||||||
|
quiet: if False (the default), the context manager raises an exception
|
||||||
|
on error. Otherwise, if the path is specified and cannot be
|
||||||
|
created, only a warning is issued.
|
||||||
|
|
||||||
Otherwise, 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()
|
dir_created = False
|
||||||
is_temporary = False
|
|
||||||
if path is None:
|
if path is None:
|
||||||
path = name
|
path = tempfile.mkdtemp()
|
||||||
|
dir_created = True
|
||||||
|
path = os.path.realpath(path)
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
os.mkdir(name)
|
os.mkdir(path)
|
||||||
is_temporary = True
|
dir_created = True
|
||||||
except OSError:
|
except OSError:
|
||||||
if not quiet:
|
if not quiet:
|
||||||
raise
|
raise
|
||||||
warnings.warn('tests may fail, unable to create temp CWD ' + name,
|
warnings.warn('tests may fail, unable to create temp dir: ' + path,
|
||||||
RuntimeWarning, stacklevel=3)
|
RuntimeWarning, stacklevel=3)
|
||||||
|
try:
|
||||||
|
yield path
|
||||||
|
finally:
|
||||||
|
if dir_created:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def change_cwd(path, quiet=False):
|
||||||
|
"""Return a context manager that changes the current working directory.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
path: the directory to use as the temporary current working directory.
|
||||||
|
|
||||||
|
quiet: if False (the default), the context manager raises an exception
|
||||||
|
on error. Otherwise, it issues only a warning and keeps the current
|
||||||
|
working directory the same.
|
||||||
|
|
||||||
|
"""
|
||||||
|
saved_dir = os.getcwd()
|
||||||
try:
|
try:
|
||||||
os.chdir(path)
|
os.chdir(path)
|
||||||
except OSError:
|
except OSError:
|
||||||
if not quiet:
|
if not quiet:
|
||||||
raise
|
raise
|
||||||
warnings.warn('tests may fail, unable to change the CWD to ' + path,
|
warnings.warn('tests may fail, unable to change CWD to: ' + path,
|
||||||
RuntimeWarning, stacklevel=3)
|
RuntimeWarning, stacklevel=3)
|
||||||
try:
|
try:
|
||||||
yield os.getcwd()
|
yield os.getcwd()
|
||||||
finally:
|
finally:
|
||||||
os.chdir(saved_dir)
|
os.chdir(saved_dir)
|
||||||
if is_temporary:
|
|
||||||
rmtree(name)
|
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def temp_cwd(name='tempcwd', quiet=False):
|
||||||
|
"""
|
||||||
|
Context manager that temporarily creates and changes the CWD.
|
||||||
|
|
||||||
|
The function temporarily changes the current working directory
|
||||||
|
after creating a temporary directory in the current directory with
|
||||||
|
name *name*. If *name* is None, the temporary directory is
|
||||||
|
created using tempfile.mkdtemp.
|
||||||
|
|
||||||
|
If *quiet* is False (default) and it is not possible to
|
||||||
|
create or change the CWD, an error is raised. If *quiet* is True,
|
||||||
|
only a warning is raised and the original CWD is used.
|
||||||
|
|
||||||
|
"""
|
||||||
|
with temp_dir(path=name, quiet=quiet) as temp_path:
|
||||||
|
with change_cwd(temp_path, quiet=quiet) as cwd_dir:
|
||||||
|
yield cwd_dir
|
||||||
|
|
||||||
if hasattr(os, "umask"):
|
if hasattr(os, "umask"):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def temp_umask(umask):
|
def temp_umask(umask):
|
||||||
|
|
|
@ -290,7 +290,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
# Make sure package __init__ modules see "-m" in sys.argv0 while
|
# Make sure package __init__ modules see "-m" in sys.argv0 while
|
||||||
# searching for the module to execute
|
# searching for the module to execute
|
||||||
with temp_dir() as script_dir:
|
with temp_dir() as script_dir:
|
||||||
with support.temp_cwd(path=script_dir):
|
with support.change_cwd(path=script_dir):
|
||||||
pkg_dir = os.path.join(script_dir, 'test_pkg')
|
pkg_dir = os.path.join(script_dir, 'test_pkg')
|
||||||
make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])")
|
make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])")
|
||||||
script_name = _make_test_script(pkg_dir, 'script')
|
script_name = _make_test_script(pkg_dir, 'script')
|
||||||
|
@ -307,7 +307,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
# Make sure a "-c" file in the current directory
|
# Make sure a "-c" file in the current directory
|
||||||
# does not alter the value of sys.path[0]
|
# does not alter the value of sys.path[0]
|
||||||
with temp_dir() as script_dir:
|
with temp_dir() as script_dir:
|
||||||
with support.temp_cwd(path=script_dir):
|
with support.change_cwd(path=script_dir):
|
||||||
with open("-c", "w") as f:
|
with open("-c", "w") as f:
|
||||||
f.write("data")
|
f.write("data")
|
||||||
rc, out, err = assert_python_ok('-c',
|
rc, out, err = assert_python_ok('-c',
|
||||||
|
@ -322,7 +322,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
# does not alter the value of sys.path[0]
|
# does not alter the value of sys.path[0]
|
||||||
with temp_dir() as script_dir:
|
with temp_dir() as script_dir:
|
||||||
script_name = _make_test_script(script_dir, 'other')
|
script_name = _make_test_script(script_dir, 'other')
|
||||||
with support.temp_cwd(path=script_dir):
|
with support.change_cwd(path=script_dir):
|
||||||
with open("-m", "w") as f:
|
with open("-m", "w") as f:
|
||||||
f.write("data")
|
f.write("data")
|
||||||
rc, out, err = assert_python_ok('-m', 'other', *example_args)
|
rc, out, err = assert_python_ok('-m', 'other', *example_args)
|
||||||
|
@ -335,7 +335,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
# and results in an error that the return code to the
|
# and results in an error that the return code to the
|
||||||
# shell is '1'
|
# shell is '1'
|
||||||
with temp_dir() as script_dir:
|
with temp_dir() as script_dir:
|
||||||
with support.temp_cwd(path=script_dir):
|
with support.change_cwd(path=script_dir):
|
||||||
pkg_dir = os.path.join(script_dir, 'test_pkg')
|
pkg_dir = os.path.join(script_dir, 'test_pkg')
|
||||||
make_pkg(pkg_dir)
|
make_pkg(pkg_dir)
|
||||||
script_name = _make_test_script(pkg_dir, 'other',
|
script_name = _make_test_script(pkg_dir, 'other',
|
||||||
|
|
|
@ -1307,18 +1307,18 @@ class TestWhich(unittest.TestCase):
|
||||||
# that exists, it should be returned.
|
# that exists, it should be returned.
|
||||||
base_dir, tail_dir = os.path.split(self.dir)
|
base_dir, tail_dir = os.path.split(self.dir)
|
||||||
relpath = os.path.join(tail_dir, self.file)
|
relpath = os.path.join(tail_dir, self.file)
|
||||||
with support.temp_cwd(path=base_dir):
|
with support.change_cwd(path=base_dir):
|
||||||
rv = shutil.which(relpath, path=self.temp_dir)
|
rv = shutil.which(relpath, path=self.temp_dir)
|
||||||
self.assertEqual(rv, relpath)
|
self.assertEqual(rv, relpath)
|
||||||
# But it shouldn't be searched in PATH directories (issue #16957).
|
# But it shouldn't be searched in PATH directories (issue #16957).
|
||||||
with support.temp_cwd(path=self.dir):
|
with support.change_cwd(path=self.dir):
|
||||||
rv = shutil.which(relpath, path=base_dir)
|
rv = shutil.which(relpath, path=base_dir)
|
||||||
self.assertIsNone(rv)
|
self.assertIsNone(rv)
|
||||||
|
|
||||||
def test_cwd(self):
|
def test_cwd(self):
|
||||||
# Issue #16957
|
# Issue #16957
|
||||||
base_dir = os.path.dirname(self.dir)
|
base_dir = os.path.dirname(self.dir)
|
||||||
with support.temp_cwd(path=self.dir):
|
with support.change_cwd(path=self.dir):
|
||||||
rv = shutil.which(self.file, path=base_dir)
|
rv = shutil.which(self.file, path=base_dir)
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
# Windows: current directory implicitly on PATH
|
# Windows: current directory implicitly on PATH
|
||||||
|
@ -1339,7 +1339,7 @@ class TestWhich(unittest.TestCase):
|
||||||
|
|
||||||
def test_relative_path(self):
|
def test_relative_path(self):
|
||||||
base_dir, tail_dir = os.path.split(self.dir)
|
base_dir, tail_dir = os.path.split(self.dir)
|
||||||
with support.temp_cwd(path=base_dir):
|
with support.change_cwd(path=base_dir):
|
||||||
rv = shutil.which(self.file, path=tail_dir)
|
rv = shutil.which(self.file, path=tail_dir)
|
||||||
self.assertEqual(rv, os.path.join(tail_dir, self.file))
|
self.assertEqual(rv, os.path.join(tail_dir, self.file))
|
||||||
|
|
||||||
|
@ -1364,7 +1364,7 @@ class TestWhich(unittest.TestCase):
|
||||||
|
|
||||||
def test_empty_path(self):
|
def test_empty_path(self):
|
||||||
base_dir = os.path.dirname(self.dir)
|
base_dir = os.path.dirname(self.dir)
|
||||||
with support.temp_cwd(path=self.dir), \
|
with support.change_cwd(path=self.dir), \
|
||||||
support.EnvironmentVarGuard() as env:
|
support.EnvironmentVarGuard() as env:
|
||||||
env['PATH'] = self.dir
|
env['PATH'] = self.dir
|
||||||
rv = shutil.which(self.file, path='')
|
rv = shutil.which(self.file, path='')
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
@ -88,6 +89,118 @@ class TestSupport(unittest.TestCase):
|
||||||
s.listen(1)
|
s.listen(1)
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
# Tests for temp_dir()
|
||||||
|
|
||||||
|
def test_temp_dir(self):
|
||||||
|
"""Test that temp_dir() creates and destroys its directory."""
|
||||||
|
parent_dir = tempfile.mkdtemp()
|
||||||
|
parent_dir = os.path.realpath(parent_dir)
|
||||||
|
|
||||||
|
try:
|
||||||
|
path = os.path.join(parent_dir, 'temp')
|
||||||
|
self.assertFalse(os.path.isdir(path))
|
||||||
|
with support.temp_dir(path) as temp_path:
|
||||||
|
self.assertEqual(temp_path, path)
|
||||||
|
self.assertTrue(os.path.isdir(path))
|
||||||
|
self.assertFalse(os.path.isdir(path))
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(parent_dir)
|
||||||
|
|
||||||
|
def test_temp_dir__path_none(self):
|
||||||
|
"""Test passing no path."""
|
||||||
|
with support.temp_dir() as temp_path:
|
||||||
|
self.assertTrue(os.path.isdir(temp_path))
|
||||||
|
self.assertFalse(os.path.isdir(temp_path))
|
||||||
|
|
||||||
|
def test_temp_dir__existing_dir__quiet_default(self):
|
||||||
|
"""Test passing a directory that already exists."""
|
||||||
|
def call_temp_dir(path):
|
||||||
|
with support.temp_dir(path) as temp_path:
|
||||||
|
raise Exception("should not get here")
|
||||||
|
|
||||||
|
path = tempfile.mkdtemp()
|
||||||
|
path = os.path.realpath(path)
|
||||||
|
try:
|
||||||
|
self.assertTrue(os.path.isdir(path))
|
||||||
|
self.assertRaises(FileExistsError, call_temp_dir, path)
|
||||||
|
# Make sure temp_dir did not delete the original directory.
|
||||||
|
self.assertTrue(os.path.isdir(path))
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
def test_temp_dir__existing_dir__quiet_true(self):
|
||||||
|
"""Test passing a directory that already exists with quiet=True."""
|
||||||
|
path = tempfile.mkdtemp()
|
||||||
|
path = os.path.realpath(path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with support.check_warnings() as recorder:
|
||||||
|
with support.temp_dir(path, quiet=True) as temp_path:
|
||||||
|
self.assertEqual(path, temp_path)
|
||||||
|
warnings = [str(w.message) for w in recorder.warnings]
|
||||||
|
# Make sure temp_dir did not delete the original directory.
|
||||||
|
self.assertTrue(os.path.isdir(path))
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
expected = ['tests may fail, unable to create temp dir: ' + path]
|
||||||
|
self.assertEqual(warnings, expected)
|
||||||
|
|
||||||
|
# Tests for change_cwd()
|
||||||
|
|
||||||
|
def test_change_cwd(self):
|
||||||
|
original_cwd = os.getcwd()
|
||||||
|
|
||||||
|
with support.temp_dir() as temp_path:
|
||||||
|
with support.change_cwd(temp_path) as new_cwd:
|
||||||
|
self.assertEqual(new_cwd, temp_path)
|
||||||
|
self.assertEqual(os.getcwd(), new_cwd)
|
||||||
|
|
||||||
|
self.assertEqual(os.getcwd(), original_cwd)
|
||||||
|
|
||||||
|
def test_change_cwd__non_existent_dir(self):
|
||||||
|
"""Test passing a non-existent directory."""
|
||||||
|
original_cwd = os.getcwd()
|
||||||
|
|
||||||
|
def call_change_cwd(path):
|
||||||
|
with support.change_cwd(path) as new_cwd:
|
||||||
|
raise Exception("should not get here")
|
||||||
|
|
||||||
|
with support.temp_dir() as parent_dir:
|
||||||
|
non_existent_dir = os.path.join(parent_dir, 'does_not_exist')
|
||||||
|
self.assertRaises(FileNotFoundError, call_change_cwd,
|
||||||
|
non_existent_dir)
|
||||||
|
|
||||||
|
self.assertEqual(os.getcwd(), original_cwd)
|
||||||
|
|
||||||
|
def test_change_cwd__non_existent_dir__quiet_true(self):
|
||||||
|
"""Test passing a non-existent directory with quiet=True."""
|
||||||
|
original_cwd = os.getcwd()
|
||||||
|
|
||||||
|
with support.temp_dir() as parent_dir:
|
||||||
|
bad_dir = os.path.join(parent_dir, 'does_not_exist')
|
||||||
|
with support.check_warnings() as recorder:
|
||||||
|
with support.change_cwd(bad_dir, quiet=True) as new_cwd:
|
||||||
|
self.assertEqual(new_cwd, original_cwd)
|
||||||
|
self.assertEqual(os.getcwd(), new_cwd)
|
||||||
|
warnings = [str(w.message) for w in recorder.warnings]
|
||||||
|
|
||||||
|
expected = ['tests may fail, unable to change CWD to: ' + bad_dir]
|
||||||
|
self.assertEqual(warnings, expected)
|
||||||
|
|
||||||
|
# Tests for change_cwd()
|
||||||
|
|
||||||
|
def test_change_cwd__chdir_warning(self):
|
||||||
|
"""Check the warning message when os.chdir() fails."""
|
||||||
|
path = TESTFN + '_does_not_exist'
|
||||||
|
with support.check_warnings() as recorder:
|
||||||
|
with support.change_cwd(path=path, quiet=True):
|
||||||
|
pass
|
||||||
|
messages = [str(w.message) for w in recorder.warnings]
|
||||||
|
self.assertEqual(messages, ['tests may fail, unable to change CWD to: ' + path])
|
||||||
|
|
||||||
|
# Tests for temp_cwd()
|
||||||
|
|
||||||
def test_temp_cwd(self):
|
def test_temp_cwd(self):
|
||||||
here = os.getcwd()
|
here = os.getcwd()
|
||||||
with support.temp_cwd(name=TESTFN):
|
with support.temp_cwd(name=TESTFN):
|
||||||
|
@ -95,14 +208,15 @@ class TestSupport(unittest.TestCase):
|
||||||
self.assertFalse(os.path.exists(TESTFN))
|
self.assertFalse(os.path.exists(TESTFN))
|
||||||
self.assertTrue(os.path.basename(os.getcwd()), here)
|
self.assertTrue(os.path.basename(os.getcwd()), here)
|
||||||
|
|
||||||
def test_temp_cwd__chdir_warning(self):
|
|
||||||
"""Check the warning message when os.chdir() fails."""
|
def test_temp_cwd__name_none(self):
|
||||||
path = TESTFN + '_does_not_exist'
|
"""Test passing None to temp_cwd()."""
|
||||||
with support.check_warnings() as recorder:
|
original_cwd = os.getcwd()
|
||||||
with support.temp_cwd(path=path, quiet=True):
|
with support.temp_cwd(name=None) as new_cwd:
|
||||||
pass
|
self.assertNotEqual(new_cwd, original_cwd)
|
||||||
messages = [str(w.message) for w in recorder.warnings]
|
self.assertTrue(os.path.isdir(new_cwd))
|
||||||
self.assertEqual(messages, ['tests may fail, unable to change the CWD to ' + path])
|
self.assertEqual(os.getcwd(), new_cwd)
|
||||||
|
self.assertEqual(os.getcwd(), original_cwd)
|
||||||
|
|
||||||
def test_sortdict(self):
|
def test_sortdict(self):
|
||||||
self.assertEqual(support.sortdict({3:3, 2:2, 1:1}), "{1: 1, 2: 2, 3: 3}")
|
self.assertEqual(support.sortdict({3:3, 2:2, 1:1}), "{1: 1, 2: 2, 3: 3}")
|
||||||
|
|
|
@ -222,6 +222,9 @@ IDLE
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #15415: Add new temp_dir() and change_cwd() context managers to
|
||||||
|
test.support, and refactor temp_cwd() to use them. Patch by Chris Jerdonek.
|
||||||
|
|
||||||
- Issue #15494: test.support is now a package rather than a module (Initial
|
- Issue #15494: test.support is now a package rather than a module (Initial
|
||||||
patch by Indra Talip)
|
patch by Indra Talip)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue