From 4b54a8a038d5f9f2ead224b030f87f393d57d40b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Jun 2020 18:07:13 +0200 Subject: [PATCH 1/6] bpo-41003: Fix test_copyreg when numpy is installed (GH-20935) Fix test_copyreg when numpy is installed: test.pickletester now saves/restores warnings.filters when importing numpy, to ignore filters installed by numpy. Add the save_restore_warnings_filters() function to the test.support.warnings_helper module. --- tests/__init__.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index 5d2e69e3e6..16d011fd9e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -15,26 +15,25 @@ import os import sys import unittest -import warnings from test.support import run_unittest +from test.support.warnings_helper import save_restore_warnings_filters here = os.path.dirname(__file__) or os.curdir def test_suite(): - old_filters = warnings.filters[:] suite = unittest.TestSuite() for fn in os.listdir(here): if fn.startswith("test") and fn.endswith(".py"): modname = "distutils.tests." + fn[:-3] - __import__(modname) + # bpo-40055: Save/restore warnings filters to leave them unchanged. + # Importing tests imports docutils which imports pkg_resources + # which adds a warnings filter. + with save_restore_warnings_filters(): + __import__(modname) module = sys.modules[modname] suite.addTest(module.test_suite()) - # bpo-40055: Save/restore warnings filters to leave them unchanged. - # Importing tests imports docutils which imports pkg_resources which adds a - # warnings filter. - warnings.filters[:] = old_filters return suite From fba62111e62d2ef06097cd319a0838c5baf006ca Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 20 Jun 2020 11:10:31 +0300 Subject: [PATCH 2/6] bpo-41043: Escape literal part of the path for glob(). (GH-20994) --- command/build_py.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/command/build_py.py b/command/build_py.py index cf0ca57c32..edc2171cd1 100644 --- a/command/build_py.py +++ b/command/build_py.py @@ -5,7 +5,7 @@ import os import importlib.util import sys -from glob import glob +import glob from distutils.core import Command from distutils.errors import * @@ -125,7 +125,7 @@ def find_data_files(self, package, src_dir): files = [] for pattern in globs: # Each pattern has to be converted to a platform-specific path - filelist = glob(os.path.join(src_dir, convert_path(pattern))) + filelist = glob.glob(os.path.join(glob.escape(src_dir), convert_path(pattern))) # Files that match more than one pattern are only added once files.extend([fn for fn in filelist if fn not in files and os.path.isfile(fn)]) @@ -216,7 +216,7 @@ def check_module(self, module, module_file): def find_package_modules(self, package, package_dir): self.check_package(package, package_dir) - module_files = glob(os.path.join(package_dir, "*.py")) + module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py")) modules = [] setup_script = os.path.abspath(self.distribution.script_name) From 71d869a55cde5711800918cb0dfc17f987012b66 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 26 Jun 2020 01:17:57 +0800 Subject: [PATCH 3/6] bpo-40275: Use new test.support helper submodules in tests (GH-21151) Use new test.support helper submodules in tests: * distutils tests * test_buffer * test_compile * test_filecmp * test_fileinput * test_readline * test_smtpnet * test_structmembers * test_tools --- tests/test_archive_util.py | 4 +++- tests/test_bdist_msi.py | 3 ++- tests/test_bdist_wininst.py | 3 ++- tests/test_core.py | 10 +++++----- tests/test_dist.py | 3 ++- tests/test_extension.py | 3 ++- tests/test_file_util.py | 4 +++- tests/test_filelist.py | 3 ++- tests/test_register.py | 3 ++- tests/test_sdist.py | 3 ++- tests/test_sysconfig.py | 5 ++++- tests/test_unixccompiler.py | 3 ++- 12 files changed, 31 insertions(+), 16 deletions(-) diff --git a/tests/test_archive_util.py b/tests/test_archive_util.py index e9aad0e40f..edcec2513e 100644 --- a/tests/test_archive_util.py +++ b/tests/test_archive_util.py @@ -13,7 +13,9 @@ ARCHIVE_FORMATS) from distutils.spawn import find_executable, spawn from distutils.tests import support -from test.support import check_warnings, run_unittest, patch, change_cwd +from test.support import run_unittest, patch +from test.support.os_helper import change_cwd +from test.support.warnings_helper import check_warnings try: import grp diff --git a/tests/test_bdist_msi.py b/tests/test_bdist_msi.py index 418e60ec72..a61266a14f 100644 --- a/tests/test_bdist_msi.py +++ b/tests/test_bdist_msi.py @@ -1,7 +1,8 @@ """Tests for distutils.command.bdist_msi.""" import sys import unittest -from test.support import run_unittest, check_warnings +from test.support import run_unittest +from test.support.warnings_helper import check_warnings from distutils.tests import support diff --git a/tests/test_bdist_wininst.py b/tests/test_bdist_wininst.py index 5c3d025d33..c338069a1d 100644 --- a/tests/test_bdist_wininst.py +++ b/tests/test_bdist_wininst.py @@ -2,7 +2,8 @@ import sys import platform import unittest -from test.support import run_unittest, check_warnings +from test.support import run_unittest +from test.support.warnings_helper import check_warnings from distutils.command.bdist_wininst import bdist_wininst from distutils.tests import support diff --git a/tests/test_core.py b/tests/test_core.py index 27ce7324af..4e6694a3d1 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5,8 +5,8 @@ import os import shutil import sys -import test.support from test.support import captured_stdout, run_unittest +from test.support import os_helper import unittest from distutils.tests import support from distutils import log @@ -62,13 +62,13 @@ def tearDown(self): super(CoreTestCase, self).tearDown() def cleanup_testfn(self): - path = test.support.TESTFN + path = os_helper.TESTFN if os.path.isfile(path): os.remove(path) elif os.path.isdir(path): shutil.rmtree(path) - def write_setup(self, text, path=test.support.TESTFN): + def write_setup(self, text, path=os_helper.TESTFN): f = open(path, "w") try: f.write(text) @@ -105,8 +105,8 @@ def test_run_setup_uses_current_dir(self): cwd = os.getcwd() # Create a directory and write the setup.py file there: - os.mkdir(test.support.TESTFN) - setup_py = os.path.join(test.support.TESTFN, "setup.py") + os.mkdir(os_helper.TESTFN) + setup_py = os.path.join(os_helper.TESTFN, "setup.py") distutils.core.run_setup( self.write_setup(setup_prints_cwd, path=setup_py)) diff --git a/tests/test_dist.py b/tests/test_dist.py index 60956dadef..f8a9e86b16 100644 --- a/tests/test_dist.py +++ b/tests/test_dist.py @@ -12,8 +12,9 @@ from distutils.cmd import Command from test.support import ( - TESTFN, captured_stdout, captured_stderr, run_unittest + captured_stdout, captured_stderr, run_unittest ) +from test.support.os_helper import TESTFN from distutils.tests import support from distutils import log diff --git a/tests/test_extension.py b/tests/test_extension.py index e35f2738b6..81fad02dbe 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -3,7 +3,8 @@ import os import warnings -from test.support import check_warnings, run_unittest +from test.support import run_unittest +from test.support.warnings_helper import check_warnings from distutils.extension import read_setup_file, Extension class ExtensionTestCase(unittest.TestCase): diff --git a/tests/test_file_util.py b/tests/test_file_util.py index a4e2d025f9..c7783b858d 100644 --- a/tests/test_file_util.py +++ b/tests/test_file_util.py @@ -8,7 +8,9 @@ from distutils import log from distutils.tests import support from distutils.errors import DistutilsFileError -from test.support import run_unittest, unlink +from test.support import run_unittest +from test.support.os_helper import unlink + class FileUtilTestCase(support.TempdirManager, unittest.TestCase): diff --git a/tests/test_filelist.py b/tests/test_filelist.py index c71342d0dc..2c26c22617 100644 --- a/tests/test_filelist.py +++ b/tests/test_filelist.py @@ -9,6 +9,7 @@ from distutils import filelist import test.support +from test.support import os_helper from test.support import captured_stdout, run_unittest from distutils.tests import support @@ -295,7 +296,7 @@ def test_process_template(self): class FindAllTestCase(unittest.TestCase): - @test.support.skip_unless_symlink + @os_helper.skip_unless_symlink def test_missing_symlink(self): with test.support.temp_cwd(): os.symlink('foo', 'bar') diff --git a/tests/test_register.py b/tests/test_register.py index e68b0af3ce..bba48633c9 100644 --- a/tests/test_register.py +++ b/tests/test_register.py @@ -5,7 +5,8 @@ import urllib import warnings -from test.support import check_warnings, run_unittest +from test.support import run_unittest +from test.support.warnings_helper import check_warnings from distutils.command import register as register_module from distutils.command.register import register diff --git a/tests/test_sdist.py b/tests/test_sdist.py index 23db126959..752e9db5ba 100644 --- a/tests/test_sdist.py +++ b/tests/test_sdist.py @@ -6,7 +6,8 @@ import zipfile from os.path import join from textwrap import dedent -from test.support import captured_stdout, check_warnings, run_unittest +from test.support import captured_stdout, run_unittest +from test.support.warnings_helper import check_warnings try: import zlib diff --git a/tests/test_sysconfig.py b/tests/test_sysconfig.py index 236755d095..59676b0e0b 100644 --- a/tests/test_sysconfig.py +++ b/tests/test_sysconfig.py @@ -10,7 +10,10 @@ from distutils import sysconfig from distutils.ccompiler import get_default_compiler from distutils.tests import support -from test.support import TESTFN, run_unittest, check_warnings, swap_item +from test.support import run_unittest, swap_item +from test.support.os_helper import TESTFN +from test.support.warnings_helper import check_warnings + class SysconfigTestCase(support.EnvironGuard, unittest.TestCase): def setUp(self): diff --git a/tests/test_unixccompiler.py b/tests/test_unixccompiler.py index eef702cf01..eefe4ba402 100644 --- a/tests/test_unixccompiler.py +++ b/tests/test_unixccompiler.py @@ -1,7 +1,8 @@ """Tests for distutils.unixccompiler.""" import sys import unittest -from test.support import EnvironmentVarGuard, run_unittest +from test.support import run_unittest +from test.support.os_helper import EnvironmentVarGuard from distutils import sysconfig from distutils.unixccompiler import UnixCCompiler From c6fff69d9597c203cb6a7f3b34dbb6244f148ae6 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Mon, 6 Jul 2020 20:29:49 +0800 Subject: [PATCH 4/6] bpo-40275: Use new test.support helper submodules in tests (GH-21317) --- tests/support.py | 4 ++-- tests/test_build_ext.py | 3 ++- tests/test_filelist.py | 13 ++++++------- tests/test_spawn.py | 18 +++++++++--------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/support.py b/tests/support.py index 259af882ec..23b907b607 100644 --- a/tests/support.py +++ b/tests/support.py @@ -6,7 +6,7 @@ import unittest import sysconfig from copy import deepcopy -import test.support +from test.support import os_helper from distutils import log from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL @@ -64,7 +64,7 @@ def tearDown(self): super().tearDown() while self.tempdirs: tmpdir = self.tempdirs.pop() - test.support.rmtree(tmpdir) + os_helper.rmtree(tmpdir) def mkdtemp(self): """Create a temporary directory that will be cleaned up. diff --git a/tests/test_build_ext.py b/tests/test_build_ext.py index 5e47e0773a..f9e0d766d8 100644 --- a/tests/test_build_ext.py +++ b/tests/test_build_ext.py @@ -15,6 +15,7 @@ import unittest from test import support +from test.support import os_helper from test.support.script_helper import assert_python_ok # http://bugs.python.org/issue4373 @@ -38,7 +39,7 @@ def setUp(self): # bpo-30132: On Windows, a .pdb file may be created in the current # working directory. Create a temporary working directory to cleanup # everything at the end of the test. - change_cwd = support.change_cwd(self.tmp_dir) + change_cwd = os_helper.change_cwd(self.tmp_dir) change_cwd.__enter__() self.addCleanup(change_cwd.__exit__, None, None, None) diff --git a/tests/test_filelist.py b/tests/test_filelist.py index 2c26c22617..cee97d439e 100644 --- a/tests/test_filelist.py +++ b/tests/test_filelist.py @@ -8,7 +8,6 @@ from distutils.filelist import glob_to_re, translate_pattern, FileList from distutils import filelist -import test.support from test.support import os_helper from test.support import captured_stdout, run_unittest from distutils.tests import support @@ -298,7 +297,7 @@ def test_process_template(self): class FindAllTestCase(unittest.TestCase): @os_helper.skip_unless_symlink def test_missing_symlink(self): - with test.support.temp_cwd(): + with os_helper.temp_cwd(): os.symlink('foo', 'bar') self.assertEqual(filelist.findall(), []) @@ -308,13 +307,13 @@ def test_basic_discovery(self): '.' as the parameter, the dot should be omitted from the results. """ - with test.support.temp_cwd(): + with os_helper.temp_cwd(): os.mkdir('foo') file1 = os.path.join('foo', 'file1.txt') - test.support.create_empty_file(file1) + os_helper.create_empty_file(file1) os.mkdir('bar') file2 = os.path.join('bar', 'file2.txt') - test.support.create_empty_file(file2) + os_helper.create_empty_file(file2) expected = [file2, file1] self.assertEqual(sorted(filelist.findall()), expected) @@ -323,9 +322,9 @@ def test_non_local_discovery(self): When findall is called with another path, the full path name should be returned. """ - with test.support.temp_dir() as temp_dir: + with os_helper.temp_dir() as temp_dir: file1 = os.path.join(temp_dir, 'file1.txt') - test.support.create_empty_file(file1) + os_helper.create_empty_file(file1) expected = [file1] self.assertEqual(filelist.findall(temp_dir), expected) diff --git a/tests/test_spawn.py b/tests/test_spawn.py index cf1faad5f4..3647bab7b1 100644 --- a/tests/test_spawn.py +++ b/tests/test_spawn.py @@ -4,7 +4,7 @@ import sys import unittest.mock from test.support import run_unittest, unix_shell -from test import support as test_support +from test.support import os_helper from distutils.spawn import find_executable from distutils.spawn import spawn @@ -44,9 +44,9 @@ def test_spawn(self): spawn([exe]) # should work without any error def test_find_executable(self): - with test_support.temp_dir() as tmp_dir: + with os_helper.temp_dir() as tmp_dir: # use TESTFN to get a pseudo-unique filename - program_noeext = test_support.TESTFN + program_noeext = os_helper.TESTFN # Give the temporary program an ".exe" suffix for all. # It's needed on Windows and not harmful on other platforms. program = program_noeext + ".exe" @@ -66,7 +66,7 @@ def test_find_executable(self): self.assertEqual(rv, filename) # test find in the current directory - with test_support.change_cwd(tmp_dir): + with os_helper.change_cwd(tmp_dir): rv = find_executable(program) self.assertEqual(rv, program) @@ -76,7 +76,7 @@ def test_find_executable(self): self.assertIsNone(rv) # PATH='': no match, except in the current directory - with test_support.EnvironmentVarGuard() as env: + with os_helper.EnvironmentVarGuard() as env: env['PATH'] = '' with unittest.mock.patch('distutils.spawn.os.confstr', return_value=tmp_dir, create=True), \ @@ -86,12 +86,12 @@ def test_find_executable(self): self.assertIsNone(rv) # look in current directory - with test_support.change_cwd(tmp_dir): + with os_helper.change_cwd(tmp_dir): rv = find_executable(program) self.assertEqual(rv, program) # PATH=':': explicitly looks in the current directory - with test_support.EnvironmentVarGuard() as env: + with os_helper.EnvironmentVarGuard() as env: env['PATH'] = os.pathsep with unittest.mock.patch('distutils.spawn.os.confstr', return_value='', create=True), \ @@ -100,12 +100,12 @@ def test_find_executable(self): self.assertIsNone(rv) # look in current directory - with test_support.change_cwd(tmp_dir): + with os_helper.change_cwd(tmp_dir): rv = find_executable(program) self.assertEqual(rv, program) # missing PATH: test os.confstr("CS_PATH") and os.defpath - with test_support.EnvironmentVarGuard() as env: + with os_helper.EnvironmentVarGuard() as env: env.pop('PATH', None) # without confstr From a21ea47bf0a8bbd79afdbd93b80681f1133aedf0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 7 Jul 2020 06:39:32 -0400 Subject: [PATCH 5/6] Move assert outside the context so it actually has its effect. --- distutils/tests/test_spawn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distutils/tests/test_spawn.py b/distutils/tests/test_spawn.py index 704019a198..adaa48ef2d 100644 --- a/distutils/tests/test_spawn.py +++ b/distutils/tests/test_spawn.py @@ -129,7 +129,7 @@ def test_find_executable(self): def test_spawn_missing_exe(self): with self.assertRaises(DistutilsExecError) as ctx: spawn(['does-not-exist']) - assert 'command does-no-exist failed' in str(ctx) + self.assertIn("command 'does-not-exist' failed", str(ctx.exception)) def test_suite(): From e34d6d8b739a8e0edbdfa324bf3607430aa3ff70 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 7 Jul 2020 07:11:28 -0400 Subject: [PATCH 6/6] bpo-41207 In distutils.spawn, rewrite FileNotFound (GH-21359) Automerge-Triggered-By: @jaraco --- spawn.py | 12 +++++++++--- tests/test_spawn.py | 5 +++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spawn.py b/spawn.py index aad277b0ca..0d1bd0391e 100644 --- a/spawn.py +++ b/spawn.py @@ -71,9 +71,15 @@ def spawn(cmd, search_path=1, verbose=0, dry_run=0): env = dict(os.environ, MACOSX_DEPLOYMENT_TARGET=cur_target) - proc = subprocess.Popen(cmd, env=env) - proc.wait() - exitcode = proc.returncode + try: + proc = subprocess.Popen(cmd, env=env) + proc.wait() + exitcode = proc.returncode + except OSError as exc: + if not DEBUG: + cmd = cmd[0] + raise DistutilsExecError( + "command %r failed: %s" % (cmd, exc.args[-1])) from exc if exitcode: if not DEBUG: diff --git a/tests/test_spawn.py b/tests/test_spawn.py index 3647bab7b1..4ec767b120 100644 --- a/tests/test_spawn.py +++ b/tests/test_spawn.py @@ -124,6 +124,11 @@ def test_find_executable(self): rv = find_executable(program) self.assertEqual(rv, filename) + def test_spawn_missing_exe(self): + with self.assertRaises(DistutilsExecError) as ctx: + spawn(['does-not-exist']) + self.assertIn("command 'does-not-exist' failed", str(ctx.exception)) + def test_suite(): return unittest.makeSuite(SpawnTestCase)