]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40280: Skip subprocess-based tests on wasm32-emscripten (GH-30615)
authorChristian Heimes <christian@python.org>
Tue, 25 Jan 2022 07:09:06 +0000 (09:09 +0200)
committerGitHub <noreply@github.com>
Tue, 25 Jan 2022 07:09:06 +0000 (08:09 +0100)
42 files changed:
Lib/distutils/tests/test_build_clib.py
Lib/distutils/tests/test_build_ext.py
Lib/distutils/tests/test_build_py.py
Lib/distutils/tests/test_config_cmd.py
Lib/distutils/tests/test_install.py
Lib/distutils/tests/test_install_lib.py
Lib/distutils/tests/test_spawn.py
Lib/distutils/tests/test_sysconfig.py
Lib/lib2to3/tests/test_parser.py
Lib/test/support/__init__.py
Lib/test/support/script_helper.py
Lib/test/test_audit.py
Lib/test/test_capi.py
Lib/test/test_cmd_line.py
Lib/test/test_embed.py
Lib/test/test_faulthandler.py
Lib/test/test_file_eintr.py
Lib/test/test_gc.py
Lib/test/test_gzip.py
Lib/test/test_os.py
Lib/test/test_platform.py
Lib/test/test_poll.py
Lib/test/test_popen.py
Lib/test/test_py_compile.py
Lib/test/test_quopri.py
Lib/test/test_regrtest.py
Lib/test/test_repl.py
Lib/test/test_runpy.py
Lib/test/test_signal.py
Lib/test/test_site.py
Lib/test/test_source_encoding.py
Lib/test/test_subprocess.py
Lib/test/test_support.py
Lib/test/test_sys.py
Lib/test/test_sysconfig.py
Lib/test/test_threading.py
Lib/test/test_traceback.py
Lib/test/test_utf8_mode.py
Lib/test/test_venv.py
Lib/test/test_webbrowser.py
Lib/test/test_zipfile.py
Misc/NEWS.d/next/Tests/2022-01-14-23-22-41.bpo-40280.nHLWoD.rst [new file with mode: 0644]

index 601a1b10fa100c49c5efab86d3858f9a5ef3c509..95f928288e00483e2c0dd0aa0a760ab064eaac23 100644 (file)
@@ -4,7 +4,9 @@ import os
 import sys
 import sysconfig
 
-from test.support import run_unittest, missing_compiler_executable
+from test.support import (
+    run_unittest, missing_compiler_executable, requires_subprocess
+)
 
 from distutils.command.build_clib import build_clib
 from distutils.errors import DistutilsSetupError
@@ -112,6 +114,7 @@ class BuildCLibTestCase(support.TempdirManager,
         self.assertRaises(DistutilsSetupError, cmd.finalize_options)
 
     @unittest.skipIf(sys.platform == 'win32', "can't test on Windows")
+    @requires_subprocess()
     def test_run(self):
         pkg_dir, dist = self.create_dist()
         cmd = build_clib(dist)
index 3ee567d045508580ade07c15e7bc454500cc8771..460b62f50bc12e3aba52ceb2cac964c5c814caaf 100644 (file)
@@ -56,6 +56,7 @@ class BuildExtTestCase(TempdirManager,
     def build_ext(self, *args, **kwargs):
         return build_ext(*args, **kwargs)
 
+    @support.requires_subprocess()
     def test_build_ext(self):
         cmd = support.missing_compiler_executable()
         if cmd is not None:
@@ -332,6 +333,7 @@ class BuildExtTestCase(TempdirManager,
         cmd.run()
         self.assertEqual(cmd.compiler, 'unix')
 
+    @support.requires_subprocess()
     def test_get_outputs(self):
         cmd = support.missing_compiler_executable()
         if cmd is not None:
index a590a485a2b9294acdad37c8057f6b77f724a124..44a06cc963aa3c6e50897abc84c9e921785b2b51 100644 (file)
@@ -9,7 +9,7 @@ from distutils.core import Distribution
 from distutils.errors import DistutilsFileError
 
 from distutils.tests import support
-from test.support import run_unittest
+from test.support import run_unittest, requires_subprocess
 
 
 class BuildPyTestCase(support.TempdirManager,
@@ -89,6 +89,7 @@ class BuildPyTestCase(support.TempdirManager,
             self.fail("failed package_data test when package_dir is ''")
 
     @unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
+    @requires_subprocess()
     def test_byte_compile(self):
         project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
         os.chdir(project_dir)
@@ -106,6 +107,7 @@ class BuildPyTestCase(support.TempdirManager,
                          ['boiledeggs.%s.pyc' % sys.implementation.cache_tag])
 
     @unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
+    @requires_subprocess()
     def test_byte_compile_optimized(self):
         project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
         os.chdir(project_dir)
index 072f9ebe714aa7a400c10e2688e367baee37824b..c79db68aae115d15c43aad422cb11e5221ace633 100644 (file)
@@ -3,7 +3,9 @@ import unittest
 import os
 import sys
 import sysconfig
-from test.support import run_unittest, missing_compiler_executable
+from test.support import (
+    run_unittest, missing_compiler_executable, requires_subprocess
+)
 
 from distutils.command.config import dump_file, config
 from distutils.tests import support
@@ -42,6 +44,7 @@ class ConfigTestCase(support.LoggingSilencer,
         self.assertEqual(len(self._logs), numlines+1)
 
     @unittest.skipIf(sys.platform == 'win32', "can't test on Windows")
+    @requires_subprocess()
     def test_search_cpp(self):
         cmd = missing_compiler_executable(['preprocessor'])
         if cmd is not None:
index b2a3887f0bbc98d2245c97fa89a7c107e166ec69..c38f98b8b2c2949190c3ed9e1fb205b6f19983a6 100644 (file)
@@ -5,7 +5,7 @@ import sys
 import unittest
 import site
 
-from test.support import captured_stdout, run_unittest
+from test.support import captured_stdout, run_unittest, requires_subprocess
 
 from distutils import sysconfig
 from distutils.command.install import install, HAS_USER_SITE
@@ -208,6 +208,7 @@ class InstallTestCase(support.TempdirManager,
                     'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
         self.assertEqual(found, expected)
 
+    @requires_subprocess()
     def test_record_extensions(self):
         cmd = test_support.missing_compiler_executable()
         if cmd is not None:
index 652653f2b2c2bcb1e9f10787bf1c2337c4eff09a..f840d1a94665ed549877840480a18a5ef2114273 100644 (file)
@@ -8,7 +8,7 @@ from distutils.command.install_lib import install_lib
 from distutils.extension import Extension
 from distutils.tests import support
 from distutils.errors import DistutilsOptionError
-from test.support import run_unittest
+from test.support import run_unittest, requires_subprocess
 
 
 class InstallLibTestCase(support.TempdirManager,
@@ -35,6 +35,7 @@ class InstallLibTestCase(support.TempdirManager,
         self.assertEqual(cmd.optimize, 2)
 
     @unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
+    @requires_subprocess()
     def test_byte_compile(self):
         project_dir, dist = self.create_dist()
         os.chdir(project_dir)
@@ -90,6 +91,7 @@ class InstallLibTestCase(support.TempdirManager,
         inputs = cmd.get_inputs()
         self.assertEqual(len(inputs), 2, inputs)
 
+    @requires_subprocess()
     def test_dont_write_bytecode(self):
         # makes sure byte_compile is not used
         dist = self.create_dist()[1]
index 631d6455d457251339542bce866afda5285b5ad3..a0a1145da5df8e0544e630b890e646a7181ac4a1 100644 (file)
@@ -3,7 +3,7 @@ import os
 import stat
 import sys
 import unittest.mock
-from test.support import run_unittest, unix_shell
+from test.support import run_unittest, unix_shell, requires_subprocess
 from test.support import os_helper
 
 from distutils.spawn import find_executable
@@ -11,6 +11,8 @@ from distutils.spawn import spawn
 from distutils.errors import DistutilsExecError
 from distutils.tests import support
 
+
+@requires_subprocess()
 class SpawnTestCase(support.TempdirManager,
                     support.LoggingSilencer,
                     unittest.TestCase):
index 3697206229d2058b4400e255d3fd4c1e0a63f2c6..7a88c88f6cdc50c2f5f90211e89fad1a6969713b 100644 (file)
@@ -10,7 +10,7 @@ import unittest
 from distutils import sysconfig
 from distutils.ccompiler import get_default_compiler
 from distutils.tests import support
-from test.support import run_unittest, swap_item
+from test.support import run_unittest, swap_item, requires_subprocess
 from test.support.os_helper import TESTFN
 from test.support.warnings_helper import check_warnings
 
@@ -247,6 +247,7 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase):
         self.assertIsNotNone(vars['SO'])
         self.assertEqual(vars['SO'], vars['EXT_SUFFIX'])
 
+    @requires_subprocess()
     def test_customize_compiler_before_get_config_vars(self):
         # Issue #21923: test that a Distribution compiler
         # instance can be called without an explicit call to
index 5eefb5aad7d49e5aa4d1e972f4b2a76e97cdeab4..ff4f8078878d8d0e4d7e72acc7b33b2b6b8deb5c 100644 (file)
@@ -61,6 +61,9 @@ class TestPgen2Caching(support.TestCase):
             shutil.rmtree(tmpdir)
 
     @unittest.skipIf(sys.executable is None, 'sys.executable required')
+    @unittest.skipIf(
+        sys.platform == 'emscripten', 'requires working subprocess'
+    )
     def test_load_grammar_from_subprocess(self):
         tmpdir = tempfile.mkdtemp()
         tmpsubdir = os.path.join(tmpdir, 'subdir')
index ca903d302bdd31c995a3ed8d6f3a4930661c670f..1e4935fc3e6174edf5edf85d940bdc008fa72fd4 100644 (file)
@@ -40,11 +40,12 @@ __all__ = [
     "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
     "requires_IEEE_754", "requires_zlib",
     "has_fork_support", "requires_fork",
+    "has_subprocess_support", "requires_subprocess",
     "anticipate_failure", "load_package_tests", "detect_api_mismatch",
     "check__all__", "skip_if_buggy_ucrt_strfptime",
     "check_disallow_instantiation",
     # sys
-    "is_jython", "is_android", "is_emscripten",
+    "is_jython", "is_android", "is_emscripten", "is_wasi",
     "check_impl_detail", "unix_shell", "setswitchinterval",
     # network
     "open_urlresource",
@@ -467,15 +468,23 @@ if sys.platform not in ('win32', 'vxworks'):
 else:
     unix_shell = None
 
-# wasm32-emscripten is POSIX-like but does not provide a
-# working fork() or subprocess API.
+# wasm32-emscripten and -wasi are POSIX-like but do not
+# have subprocess or fork support.
 is_emscripten = sys.platform == "emscripten"
+is_wasi = sys.platform == "wasi"
 
-has_fork_support = hasattr(os, "fork") and not is_emscripten
+has_fork_support = hasattr(os, "fork") and not is_emscripten and not is_wasi
 
 def requires_fork():
     return unittest.skipUnless(has_fork_support, "requires working os.fork()")
 
+has_subprocess_support = not is_emscripten and not is_wasi
+
+def requires_subprocess():
+    """Used for subprocess, os.spawn calls"""
+    return unittest.skipUnless(has_subprocess_support, "requires subprocess support")
+
+
 # Define the URL of a dedicated HTTP server for the network tests.
 # The URL must use clear-text HTTP: no redirection to encrypted HTTPS.
 TEST_HTTP_URL = "http://www.pythontest.net"
index 6d699c8486cd20daa8f0b906089e61978cf61ade..c2b43f4060eb5522e93a25d753de070acf9f9120 100644 (file)
@@ -42,6 +42,10 @@ def interpreter_requires_environment():
         if 'PYTHONHOME' in os.environ:
             __cached_interp_requires_environment = True
             return True
+        # cannot run subprocess, assume we don't need it
+        if not support.has_subprocess_support:
+            __cached_interp_requires_environment = False
+            return False
 
         # Try running an interpreter with -E to see if it works or not.
         try:
@@ -87,6 +91,7 @@ class _PythonRunResult(collections.namedtuple("_PythonRunResult",
 
 
 # Executing the interpreter in a subprocess
+@support.requires_subprocess()
 def run_python_until_end(*args, **env_vars):
     env_required = interpreter_requires_environment()
     cwd = env_vars.pop('__cwd', None)
@@ -139,6 +144,7 @@ def run_python_until_end(*args, **env_vars):
     return _PythonRunResult(rc, out, err), cmd_line
 
 
+@support.requires_subprocess()
 def _assert_python(expected_success, /, *args, **env_vars):
     res, cmd_line = run_python_until_end(*args, **env_vars)
     if (res.rc and expected_success) or (not res.rc and not expected_success):
@@ -171,6 +177,7 @@ def assert_python_failure(*args, **env_vars):
     return _assert_python(False, *args, **env_vars)
 
 
+@support.requires_subprocess()
 def spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw):
     """Run a Python subprocess with the given arguments.
 
@@ -273,6 +280,7 @@ def make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
     return zip_name, os.path.join(zip_name, script_name_in_zip)
 
 
+@support.requires_subprocess()
 def run_test_script(script):
     # use -u to try to get the full output if the test hangs or crash
     if support.verbose:
index d99b3b7ed7d36d715b6b2015fc2c88b8d774bb2d..0fa2d74835cba6f1926fdca4a3c9824a6b53fbb1 100644 (file)
@@ -16,6 +16,8 @@ AUDIT_TESTS_PY = support.findfile("audit-tests.py")
 
 
 class AuditTest(unittest.TestCase):
+
+    @support.requires_subprocess()
     def do_test(self, *args):
         with subprocess.Popen(
             [sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
@@ -29,6 +31,7 @@ class AuditTest(unittest.TestCase):
             if p.returncode:
                 self.fail("".join(p.stderr))
 
+    @support.requires_subprocess()
     def run_python(self, *args):
         events = []
         with subprocess.Popen(
index 0957f3253d7a66d1e65be5dcf26925a1307c3d71..a5db8a11c5f672413f724aff0f2bec6c2f35a281 100644 (file)
@@ -66,6 +66,7 @@ class CAPITest(unittest.TestCase):
         self.assertEqual(testfunction.attribute, "test")
         self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test")
 
+    @support.requires_subprocess()
     def test_no_FatalError_infinite_loop(self):
         with support.SuppressCrashReport():
             p = subprocess.Popen([sys.executable, "-c",
index fa5f39ea5fa972e5524a85ded2909ebcab4d520f..352109ed4b2ff1821a7d097be2962838eba42545 100644 (file)
@@ -15,6 +15,8 @@ from test.support.script_helper import (
     interpreter_requires_environment
 )
 
+if not support.has_subprocess_support:
+    raise unittest.SkipTest("test module requires subprocess")
 
 # Debug build?
 Py_DEBUG = hasattr(sys, "gettotalrefcount")
index 19c53c392607b64dc4b847171e87117c820415b9..15c6b05916f34d61d3979664ff623838054fbb09 100644 (file)
@@ -17,6 +17,8 @@ import sysconfig
 import tempfile
 import textwrap
 
+if not support.has_subprocess_support:
+    raise unittest.SkipTest("test module requires subprocess")
 
 MS_WINDOWS = (os.name == 'nt')
 MACOS = (sys.platform == 'darwin')
index de986a3cbea97aed135e01909b275098f782f758..f7eaa779424768c32ca73377837b2fd8c6e761ec 100644 (file)
@@ -412,6 +412,7 @@ class FaultHandlerTests(unittest.TestCase):
         finally:
             sys.stderr = orig_stderr
 
+    @support.requires_subprocess()
     def test_disabled_by_default(self):
         # By default, the module should be disabled
         code = "import faulthandler; print(faulthandler.is_enabled())"
@@ -420,6 +421,7 @@ class FaultHandlerTests(unittest.TestCase):
         output = subprocess.check_output(args)
         self.assertEqual(output.rstrip(), b"False")
 
+    @support.requires_subprocess()
     def test_sys_xoptions(self):
         # Test python -X faulthandler
         code = "import faulthandler; print(faulthandler.is_enabled())"
@@ -432,6 +434,7 @@ class FaultHandlerTests(unittest.TestCase):
         output = subprocess.check_output(args, env=env)
         self.assertEqual(output.rstrip(), b"True")
 
+    @support.requires_subprocess()
     def test_env_var(self):
         # empty env var
         code = "import faulthandler; print(faulthandler.is_enabled())"
index 01408d838a83ccea338447434548be2c753a2adb..f9236f45ca4be84403533efd238a82eb486f90a5 100644 (file)
@@ -15,12 +15,15 @@ import subprocess
 import sys
 import time
 import unittest
+from test import support
+
+if not support.has_subprocess_support:
+    raise unittest.SkipTest("test module requires subprocess")
 
 # Test import all of the things we're about to try testing up front.
 import _io
 import _pyio
 
-
 @unittest.skipUnless(os.name == 'posix', 'tests requires a posix system.')
 class TestFileIOSignalInterrupt:
     def setUp(self):
index 52948f1c7bde5184654f90865bb28c331b959069..c4d4355dec9c6d87d6e462dbb10580a84d533671 100644 (file)
@@ -1,7 +1,7 @@
 import unittest
 import unittest.mock
 from test.support import (verbose, refcount_test,
-                          cpython_only)
+                          cpython_only, requires_subprocess)
 from test.support.import_helper import import_module
 from test.support.os_helper import temp_dir, TESTFN, unlink
 from test.support.script_helper import assert_python_ok, make_script
@@ -661,6 +661,7 @@ class GCTests(unittest.TestCase):
         gc.collect() # this blows up (bad C pointer) when it fails
 
     @cpython_only
+    @requires_subprocess()
     def test_garbage_at_shutdown(self):
         import subprocess
         code = """if 1:
index aa66d2f07f508cbb82437b97fa4b7648fb7ecdc6..497e66cd553b7f042d449747bc901c2f97459b66 100644 (file)
@@ -12,7 +12,7 @@ import unittest
 from subprocess import PIPE, Popen
 from test.support import import_helper
 from test.support import os_helper
-from test.support import _4G, bigmemtest
+from test.support import _4G, bigmemtest, requires_subprocess
 from test.support.script_helper import assert_python_ok, assert_python_failure
 
 gzip = import_helper.import_module('gzip')
@@ -760,6 +760,7 @@ def create_and_remove_directory(directory):
 class TestCommandLine(unittest.TestCase):
     data = b'This is a simple test with gzip'
 
+    @requires_subprocess()
     def test_decompress_stdin_stdout(self):
         with io.BytesIO() as bytes_io:
             with gzip.GzipFile(fileobj=bytes_io, mode='wb') as gzip_file:
@@ -795,6 +796,7 @@ class TestCommandLine(unittest.TestCase):
         self.assertEqual(rc, 1)
         self.assertEqual(out, b'')
 
+    @requires_subprocess()
     @create_and_remove_directory(TEMPDIR)
     def test_compress_stdin_outfile(self):
         args = sys.executable, '-m', 'gzip'
index 89e5e4190c640dfa4fac7bc810a96d03e3de94ad..84c27f346c3409b90552fb6c3722134c250afe2c 100644 (file)
@@ -1096,6 +1096,7 @@ class EnvironTests(mapping_tests.BasicTestMappingProtocol):
         value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
         self.assertEqual(os.environ['bytes'], value_str)
 
+    @support.requires_subprocess()
     def test_putenv_unsetenv(self):
         name = "PYTHONTESTVAR"
         value = "testvalue"
@@ -2279,6 +2280,7 @@ class PosixUidGidTests(unittest.TestCase):
         self.assertRaises(OverflowError, os.setreuid, 0, self.UID_OVERFLOW)
 
     @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
+    @support.requires_subprocess()
     def test_setreuid_neg1(self):
         # Needs to accept -1.  We run this in a subprocess to avoid
         # altering the test runner's process state (issue8045).
@@ -2287,6 +2289,7 @@ class PosixUidGidTests(unittest.TestCase):
                 'import os,sys;os.setreuid(-1,-1);sys.exit(0)'])
 
     @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
+    @support.requires_subprocess()
     def test_setregid(self):
         if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
             self.assertRaises(OSError, os.setregid, 0, 0)
@@ -2296,6 +2299,7 @@ class PosixUidGidTests(unittest.TestCase):
         self.assertRaises(OverflowError, os.setregid, 0, self.GID_OVERFLOW)
 
     @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
+    @support.requires_subprocess()
     def test_setregid_neg1(self):
         # Needs to accept -1.  We run this in a subprocess to avoid
         # altering the test runner's process state (issue8045).
@@ -2469,6 +2473,7 @@ class Win32KillTests(unittest.TestCase):
             self.fail("subprocess did not stop on {}".format(name))
 
     @unittest.skip("subprocesses aren't inheriting Ctrl+C property")
+    @support.requires_subprocess()
     def test_CTRL_C_EVENT(self):
         from ctypes import wintypes
         import ctypes
@@ -2487,6 +2492,7 @@ class Win32KillTests(unittest.TestCase):
 
         self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT")
 
+    @support.requires_subprocess()
     def test_CTRL_BREAK_EVENT(self):
         self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
 
@@ -2924,6 +2930,7 @@ class DeviceEncodingTests(unittest.TestCase):
         self.assertTrue(codecs.lookup(encoding))
 
 
+@support.requires_subprocess()
 class PidTests(unittest.TestCase):
     @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
     def test_getppid(self):
@@ -2996,6 +3003,7 @@ class PidTests(unittest.TestCase):
         self.check_waitpid(code, exitcode=-signum, callback=kill_process)
 
 
+@support.requires_subprocess()
 class SpawnTests(unittest.TestCase):
     def create_args(self, *, with_env=False, use_bytes=False):
         self.exitcode = 17
index 1a688775f463099f96d61f2b58547187e12781fa..d70ef155271f51e613d10e290f9c2210444bdcac 100644 (file)
@@ -79,6 +79,7 @@ class PlatformTest(unittest.TestCase):
         res = platform.architecture()
 
     @os_helper.skip_unless_symlink
+    @support.requires_subprocess()
     def test_architecture_via_symlink(self): # issue3762
         with support.PythonSymlink() as py:
             cmd = "-c", "import platform; print(platform.architecture())"
@@ -269,6 +270,7 @@ class PlatformTest(unittest.TestCase):
         self.assertEqual(res[:5], expected[:5])
 
     @unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used")
+    @support.requires_subprocess()
     def test_uname_processor(self):
         """
         On some systems, the processor must match the output
index 82bbb3af9f1b399c444a4358e9cd8a7110a31b1c..ae3ffc77e9924ae9318859602004b2e19f8327b5 100644 (file)
@@ -7,7 +7,7 @@ import select
 import threading
 import time
 import unittest
-from test.support import cpython_only
+from test.support import cpython_only, requires_subprocess
 from test.support import threading_helper
 from test.support.os_helper import TESTFN
 
@@ -120,6 +120,7 @@ class PollTests(unittest.TestCase):
     # Another test case for poll().  This is copied from the test case for
     # select(), modified to use poll() instead.
 
+    @requires_subprocess()
     def test_poll2(self):
         cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done'
         proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
index cac2f6177f3257373126942b7fe33e6e6b625d40..e6bfc480cbd12c46938077657fed8525db8453ee 100644 (file)
@@ -19,6 +19,7 @@ python = sys.executable
 if ' ' in python:
     python = '"' + python + '"'     # quote embedded space for cmdline
 
+@support.requires_subprocess()
 class PopenTest(unittest.TestCase):
 
     def _do_test_commandline(self, cmdline, expected):
index 5ed98dbff1737ee9aaf6da5276bd35b02a367bfe..794d6436b61ab02e0d8f6de8d32f421a23a8a200 100644 (file)
@@ -230,6 +230,7 @@ class PyCompileCLITestCase(unittest.TestCase):
     def tearDown(self):
         os_helper.rmtree(self.directory)
 
+    @support.requires_subprocess()
     def pycompilecmd(self, *args, **kwargs):
         # assert_python_* helpers don't return proc object. We'll just use
         # subprocess.run() instead of spawn_python() and its friends to test
index 715544c8a9669d56f5087a6487d1dad9414be4da..152d1858dcdd2424f851b52b4cbaffa0e4125f26 100644 (file)
@@ -3,6 +3,7 @@ import unittest
 import sys, io, subprocess
 import quopri
 
+from test import support
 
 
 ENCSAMPLE = b"""\
@@ -180,6 +181,7 @@ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''')
         for p, e in self.HSTRINGS:
             self.assertEqual(quopri.decodestring(e, header=True), p)
 
+    @support.requires_subprocess()
     def test_scriptencode(self):
         (p, e) = self.STRINGS[-1]
         process = subprocess.Popen([sys.executable, "-mquopri"],
@@ -196,6 +198,7 @@ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''')
             self.assertEqual(cout[i], e[i])
         self.assertEqual(cout, e)
 
+    @support.requires_subprocess()
     def test_scriptdecode(self):
         (p, e) = self.STRINGS[-1]
         process = subprocess.Popen([sys.executable, "-mquopri", "-d"],
index 08e2c87e15c4d86e4d875e054172116cbfe6196b..babc8a690877a2b0b3c554704a143330c7476ad2 100644 (file)
@@ -22,6 +22,8 @@ from test import support
 from test.support import os_helper
 from test.libregrtest import utils, setup
 
+if not support.has_subprocess_support:
+    raise unittest.SkipTest("test module requires subprocess")
 
 Py_DEBUG = hasattr(sys, 'gettotalrefcount')
 ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..')
index a8d04a425e278b577dafcf44fc8d0639e6fd71cc..ddb4aa68048df185512cbae4e15cebeb044f1a84 100644 (file)
@@ -5,9 +5,14 @@ import os
 import unittest
 import subprocess
 from textwrap import dedent
-from test.support import cpython_only, SuppressCrashReport
+from test.support import cpython_only, has_subprocess_support, SuppressCrashReport
 from test.support.script_helper import kill_python
 
+
+if not has_subprocess_support:
+    raise unittest.SkipTest("test module requires subprocess")
+
+
 def spawn_repl(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw):
     """Run the Python REPL with the given arguments.
 
index 2954dfedc7e42827867897b39732885caf90bee0..80e695a5f3f7906b049f39e9c0ff562f123a6808 100644 (file)
@@ -12,7 +12,7 @@ import tempfile
 import textwrap
 import unittest
 import warnings
-from test.support import no_tracing, verbose
+from test.support import no_tracing, verbose, requires_subprocess
 from test.support.import_helper import forget, make_legacy_pyc, unload
 from test.support.os_helper import create_empty_file, temp_dir
 from test.support.script_helper import make_script, make_zip_script
@@ -781,6 +781,7 @@ class TestExit(unittest.TestCase):
             )
             super().run(*args, **kwargs)
 
+    @requires_subprocess()
     def assertSigInt(self, *args, **kwargs):
         proc = subprocess.run(*args, **kwargs, text=True, stderr=subprocess.PIPE)
         self.assertTrue(proc.stderr.endswith("\nKeyboardInterrupt\n"))
index ac4626d0c456e27a5f77cb4911eee24bcabfab02..09de608bb771fb5b0b79a8510f7490261f0b37cd 100644 (file)
@@ -116,6 +116,7 @@ class PosixTests(unittest.TestCase):
         self.assertLess(len(s), signal.NSIG)
 
     @unittest.skipUnless(sys.executable, "sys.executable required.")
+    @support.requires_subprocess()
     def test_keyboard_interrupt_exit_code(self):
         """KeyboardInterrupt triggers exit via SIGINT."""
         process = subprocess.run(
@@ -166,6 +167,7 @@ class WindowsSignalTests(unittest.TestCase):
             signal.signal(7, handler)
 
     @unittest.skipUnless(sys.executable, "sys.executable required.")
+    @support.requires_subprocess()
     def test_keyboard_interrupt_exit_code(self):
         """KeyboardInterrupt triggers an exit using STATUS_CONTROL_C_EXIT."""
         # We don't test via os.kill(os.getpid(), signal.CTRL_C_EVENT) here
@@ -637,6 +639,7 @@ class WakeupSocketSignalTests(unittest.TestCase):
 
 @unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
 @unittest.skipUnless(hasattr(signal, 'siginterrupt'), "needs signal.siginterrupt()")
+@support.requires_subprocess()
 class SiginterruptTest(unittest.TestCase):
 
     def readpipe_interrupted(self, interrupt):
index c54d868cb234fd1b29c3cc0208de8c58917df40b..032a1be3aa5290a627df8e8adbd0f04b63d5982d 100644 (file)
@@ -211,6 +211,7 @@ class HelperFunctionsTests(unittest.TestCase):
 
     @unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 "
                           "user-site (site.ENABLE_USER_SITE)")
+    @support.requires_subprocess()
     def test_s_option(self):
         # (ncoghlan) Change this to use script_helper...
         usersite = site.USER_SITE
@@ -497,6 +498,7 @@ class ImportSideEffectTests(unittest.TestCase):
 
 class StartupImportTests(unittest.TestCase):
 
+    @support.requires_subprocess()
     def test_startup_imports(self):
         # Get sys.path in isolated mode (python3 -I)
         popen = subprocess.Popen([sys.executable, '-X', 'utf8', '-I',
@@ -547,17 +549,20 @@ class StartupImportTests(unittest.TestCase):
                           }.difference(sys.builtin_module_names)
         self.assertFalse(modules.intersection(collection_mods), stderr)
 
+    @support.requires_subprocess()
     def test_startup_interactivehook(self):
         r = subprocess.Popen([sys.executable, '-c',
             'import sys; sys.exit(hasattr(sys, "__interactivehook__"))']).wait()
         self.assertTrue(r, "'__interactivehook__' not added by site")
 
+    @support.requires_subprocess()
     def test_startup_interactivehook_isolated(self):
         # issue28192 readline is not automatically enabled in isolated mode
         r = subprocess.Popen([sys.executable, '-I', '-c',
             'import sys; sys.exit(hasattr(sys, "__interactivehook__"))']).wait()
         self.assertFalse(r, "'__interactivehook__' added in isolated mode")
 
+    @support.requires_subprocess()
     def test_startup_interactivehook_isolated_explicit(self):
         # issue28192 readline can be explicitly enabled in isolated mode
         r = subprocess.Popen([sys.executable, '-I', '-c',
@@ -607,6 +612,7 @@ class _pthFileTests(unittest.TestCase):
             sys_path.append(abs_path)
         return sys_path
 
+    @support.requires_subprocess()
     def test_underpth_basic(self):
         libpath = test.support.STDLIB_DIR
         exe_prefix = os.path.dirname(sys.executable)
@@ -627,6 +633,7 @@ class _pthFileTests(unittest.TestCase):
             "sys.path is incorrect"
         )
 
+    @support.requires_subprocess()
     def test_underpth_nosite_file(self):
         libpath = test.support.STDLIB_DIR
         exe_prefix = os.path.dirname(sys.executable)
@@ -655,6 +662,7 @@ class _pthFileTests(unittest.TestCase):
             "sys.path is incorrect"
         )
 
+    @support.requires_subprocess()
     def test_underpth_file(self):
         libpath = test.support.STDLIB_DIR
         exe_prefix = os.path.dirname(sys.executable)
@@ -679,6 +687,7 @@ class _pthFileTests(unittest.TestCase):
             )], env=env)
         self.assertTrue(rc, "sys.path is incorrect")
 
+    @support.requires_subprocess()
     def test_underpth_dll_file(self):
         libpath = test.support.STDLIB_DIR
         exe_prefix = os.path.dirname(sys.executable)
index a0cb605c1651cc4a886abca41fcc75a24d88901a..a0375fda0d36560cf31ac72e6c7adf49c900f884 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: koi8-r -*-
 
 import unittest
-from test.support import script_helper, captured_stdout
+from test.support import script_helper, captured_stdout, requires_subprocess
 from test.support.os_helper import TESTFN, unlink, rmtree
 from test.support.import_helper import unload
 import importlib
@@ -65,6 +65,7 @@ class MiscSourceEncodingTest(unittest.TestCase):
         # two bytes in common with the UTF-8 BOM
         self.assertRaises(SyntaxError, eval, b'\xef\xbb\x20')
 
+    @requires_subprocess()
     def test_20731(self):
         sub = subprocess.Popen([sys.executable,
                         os.path.join(os.path.dirname(__file__),
index 3af523e8346c462a70cb5f5829593c41dcf3aaab..99a25e279df92c087a052f2c8223fcc305ebd170 100644 (file)
@@ -48,6 +48,9 @@ except:
 if support.PGO:
     raise unittest.SkipTest("test is not helpful for PGO")
 
+if not support.has_subprocess_support:
+    raise unittest.SkipTest("test module requires subprocess")
+
 mswindows = (sys.platform == "win32")
 
 #
index 4dac7f6cd420000162a62d0ec045a9e0bd521f70..1ce3c826d6b1bc8c3f170d4343ee776a2066a2c8 100644 (file)
@@ -491,6 +491,7 @@ class TestSupport(unittest.TestCase):
         # pending child process
         support.reap_children()
 
+    @support.requires_subprocess()
     def check_options(self, args, func, expected=None):
         code = f'from test.support import {func}; print(repr({func}()))'
         cmd = [sys.executable, *args, '-c', code]
index f6da57f55f16178f3a225a59eab91275c2d994b6..41c4618ad10d40867a8fabb588a9bb4297648eb5 100644 (file)
@@ -694,6 +694,7 @@ class SysModuleTest(unittest.TestCase):
     def test_clear_type_cache(self):
         sys._clear_type_cache()
 
+    @support.requires_subprocess()
     def test_ioencoding(self):
         env = dict(os.environ)
 
@@ -741,6 +742,7 @@ class SysModuleTest(unittest.TestCase):
                          'requires OS support of non-ASCII encodings')
     @unittest.skipUnless(sys.getfilesystemencoding() == locale.getpreferredencoding(False),
                          'requires FS encoding to match locale')
+    @support.requires_subprocess()
     def test_ioencoding_nonascii(self):
         env = dict(os.environ)
 
@@ -753,6 +755,7 @@ class SysModuleTest(unittest.TestCase):
 
     @unittest.skipIf(sys.base_prefix != sys.prefix,
                      'Test is not venv-compatible')
+    @support.requires_subprocess()
     def test_executable(self):
         # sys.executable should be absolute
         self.assertEqual(os.path.abspath(sys.executable), sys.executable)
@@ -854,9 +857,11 @@ class SysModuleTest(unittest.TestCase):
                          'stdout: surrogateescape\n'
                          'stderr: backslashreplace\n')
 
+    @support.requires_subprocess()
     def test_c_locale_surrogateescape(self):
         self.check_locale_surrogateescape('C')
 
+    @support.requires_subprocess()
     def test_posix_locale_surrogateescape(self):
         self.check_locale_surrogateescape('POSIX')
 
@@ -1005,6 +1010,7 @@ class SysModuleTest(unittest.TestCase):
         self.assertIsInstance(level, int)
         self.assertGreater(level, 0)
 
+    @support.requires_subprocess()
     def test_sys_tracebacklimit(self):
         code = """if 1:
             import sys
@@ -1051,6 +1057,7 @@ class SysModuleTest(unittest.TestCase):
         out = out.decode('ascii', 'replace').rstrip()
         self.assertEqual(out, 'mbcs replace')
 
+    @support.requires_subprocess()
     def test_orig_argv(self):
         code = textwrap.dedent('''
             import sys
index 6fbb80d77f793cd302040780ea2d97babdb61515..80fe9c8a8b1e0eada24214ac9f8a5fb8903fd0c4 100644 (file)
@@ -5,7 +5,7 @@ import subprocess
 import shutil
 from copy import copy
 
-from test.support import (captured_stdout, PythonSymlink)
+from test.support import (captured_stdout, PythonSymlink, requires_subprocess)
 from test.support.import_helper import import_module
 from test.support.os_helper import (TESTFN, unlink, skip_unless_symlink,
                                     change_cwd)
@@ -273,6 +273,7 @@ class TestSysConfig(unittest.TestCase):
         self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
 
     @skip_unless_symlink
+    @requires_subprocess()
     def test_symlink(self): # Issue 7880
         with PythonSymlink() as py:
             cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
@@ -326,6 +327,7 @@ class TestSysConfig(unittest.TestCase):
         self.assertIn(ldflags, ldshared)
 
     @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX")
+    @requires_subprocess()
     def test_platform_in_subprocess(self):
         my_platform = sysconfig.get_platform()
 
index f03a64232e17c39543d2a5210f3f0351215743db..4830571474b5bfdd675f575b6b402838d941ed0f 100644 (file)
@@ -3,7 +3,7 @@ Tests for the threading module.
 """
 
 import test.support
-from test.support import threading_helper
+from test.support import threading_helper, requires_subprocess
 from test.support import verbose, cpython_only, os_helper
 from test.support.import_helper import import_module
 from test.support.script_helper import assert_python_ok, assert_python_failure
@@ -1259,6 +1259,7 @@ class ThreadingExceptionTests(BaseTestCase):
         lock = threading.Lock()
         self.assertRaises(RuntimeError, lock.release)
 
+    @requires_subprocess()
     def test_recursion_limit(self):
         # Issue 9670
         # test that excessive recursion within a non-main thread causes
index 966ff2a1241ca6f87768c6cbd1f74e14472cf1cd..e0884fb9b78141c8a077a1e363dbf9478790d154 100644 (file)
@@ -9,7 +9,8 @@ import unittest
 import re
 from test import support
 from test.support import (Error, captured_output, cpython_only, ALWAYS_EQ,
-                          requires_debug_ranges, has_no_debug_ranges)
+                          requires_debug_ranges, has_no_debug_ranges,
+                          requires_subprocess)
 from test.support.os_helper import TESTFN, unlink
 from test.support.script_helper import assert_python_ok, assert_python_failure
 
@@ -203,6 +204,7 @@ class TracebackCases(unittest.TestCase):
             str_name = '.'.join([X.__module__, X.__qualname__])
         self.assertEqual(err[0], "%s: %s\n" % (str_name, str_value))
 
+    @requires_subprocess()
     def test_encoded_file(self):
         # Test that tracebacks are correctly printed for encoded source files:
         # - correct line number (Issue2384)
index 8b6332ee22771bc7a464f766b62c097ecc26164e..2b96f76df305fedb365ef127f93c85ab72b1fb6e 100644 (file)
@@ -255,6 +255,7 @@ class UTF8ModeTests(unittest.TestCase):
     @unittest.skipIf(MS_WINDOWS,
                      "os.device_encoding() doesn't implement "
                      "the UTF-8 Mode on Windows")
+    @support.requires_subprocess()
     def test_device_encoding(self):
         # Use stdout as TTY
         if not sys.stdout.isatty():
index ca37abcf79854ac9f3dc1fdc618287dbc96815be..043158c79214b4fea4548911ad59e2b476dffd5e 100644 (file)
@@ -15,7 +15,8 @@ import subprocess
 import sys
 import tempfile
 from test.support import (captured_stdout, captured_stderr, requires_zlib,
-                          skip_if_broken_multiprocessing_synchronize, verbose)
+                          skip_if_broken_multiprocessing_synchronize, verbose,
+                          requires_subprocess)
 from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree)
 import unittest
 import venv
@@ -33,6 +34,7 @@ requireVenvCreate = unittest.skipUnless(
     or sys._base_executable != sys.executable,
     'cannot run venv.create from within a venv on this platform')
 
+@requires_subprocess()
 def check_output(cmd, encoding=None):
     p = subprocess.Popen(cmd,
         stdout=subprocess.PIPE,
index dbfd2e5a0f280b8356075f48327b942b267fdf55..9d608d63a01ed30646b3b16f2f9b17abf34e6189 100644 (file)
@@ -8,6 +8,8 @@ from test import support
 from test.support import import_helper
 from test.support import os_helper
 
+if not support.has_subprocess_support:
+    raise unittest.SkipTest("test webserver requires subprocess")
 
 URL = 'http://www.example.com'
 CMD_NAME = 'test'
index df48fabff951d87192365dc4ff3c99c828c1af09..e226dd741d7a75fe5956e6e0c7a65b9e6f9a1533 100644 (file)
@@ -21,7 +21,7 @@ from random import randint, random, randbytes
 
 from test.support import script_helper
 from test.support import (findfile, requires_zlib, requires_bz2,
-                          requires_lzma, captured_stdout)
+                          requires_lzma, captured_stdout, requires_subprocess)
 from test.support.os_helper import TESTFN, unlink, rmtree, temp_dir, temp_cwd
 
 
@@ -2771,6 +2771,7 @@ class TestExecutablePrependedZip(unittest.TestCase):
     @unittest.skipUnless(sys.executable, 'sys.executable required.')
     @unittest.skipUnless(os.access('/bin/bash', os.X_OK),
                          'Test relies on #!/bin/bash working.')
+    @requires_subprocess()
     def test_execute_zip2(self):
         output = subprocess.check_output([self.exe_zip, sys.executable])
         self.assertIn(b'number in executable: 5', output)
@@ -2778,6 +2779,7 @@ class TestExecutablePrependedZip(unittest.TestCase):
     @unittest.skipUnless(sys.executable, 'sys.executable required.')
     @unittest.skipUnless(os.access('/bin/bash', os.X_OK),
                          'Test relies on #!/bin/bash working.')
+    @requires_subprocess()
     def test_execute_zip64(self):
         output = subprocess.check_output([self.exe_zip64, sys.executable])
         self.assertIn(b'number in executable: 5', output)
diff --git a/Misc/NEWS.d/next/Tests/2022-01-14-23-22-41.bpo-40280.nHLWoD.rst b/Misc/NEWS.d/next/Tests/2022-01-14-23-22-41.bpo-40280.nHLWoD.rst
new file mode 100644 (file)
index 0000000..67134f1
--- /dev/null
@@ -0,0 +1,3 @@
+Add :func:`test.support.requires_subprocess` decorator to mark tests which
+require working :mod:`subprocess` module or ``os.spawn*``. The
+wasm32-emscripten platform has no support for processes.