]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-114099: Add test exclusions to support running the test suite on iOS (#114889)
authorRussell Keith-Magee <russell@keith-magee.com>
Mon, 5 Feb 2024 00:04:57 +0000 (08:04 +0800)
committerGitHub <noreply@github.com>
Mon, 5 Feb 2024 00:04:57 +0000 (01:04 +0100)
Add test annotations required to run the test suite on iOS (PEP 730).

The majority of the change involve annotating tests that use subprocess,
but are skipped on Emscripten/WASI for other reasons, and including
iOS/tvOS/watchOS under the same umbrella as macOS/darwin checks.

`is_apple` and `is_apple_mobile` test helpers have been added to
identify *any* Apple platform, and "any Apple platform except macOS",
respectively.

31 files changed:
Lib/test/support/__init__.py
Lib/test/support/os_helper.py
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_streams.py
Lib/test/test_asyncio/test_subprocess.py
Lib/test/test_asyncio/test_unix_events.py
Lib/test/test_cmd_line_script.py
Lib/test/test_code_module.py
Lib/test/test_fcntl.py
Lib/test/test_ftplib.py
Lib/test/test_genericpath.py
Lib/test/test_httpservers.py
Lib/test/test_io.py
Lib/test/test_marshal.py
Lib/test/test_mmap.py
Lib/test/test_os.py
Lib/test/test_pdb.py
Lib/test/test_platform.py
Lib/test/test_posix.py
Lib/test/test_pty.py
Lib/test/test_selectors.py
Lib/test/test_shutil.py
Lib/test/test_signal.py
Lib/test/test_socket.py
Lib/test/test_sqlite3/test_dbapi.py
Lib/test/test_stat.py
Lib/test/test_sys_settrace.py
Lib/test/test_unicode_file_functions.py
Lib/test/test_urllib2.py
Lib/test/test_venv.py
Misc/NEWS.d/next/Tests/2024-02-02-13-18-55.gh-issue-114099.C_ycWg.rst [new file with mode: 0644]

index f2e6af078a5f2918e74e6995945d03b61addfaac..5b091fb2fd32dc68d094bcc988bcaf19855c8250 100644 (file)
@@ -43,7 +43,7 @@ __all__ = [
     "requires_limited_api", "requires_specialization",
     # sys
     "MS_WINDOWS", "is_jython", "is_android", "is_emscripten", "is_wasi",
-    "check_impl_detail", "unix_shell", "setswitchinterval",
+    "is_apple_mobile", "check_impl_detail", "unix_shell", "setswitchinterval",
     # os
     "get_pagesize",
     # network
@@ -522,7 +522,7 @@ is_jython = sys.platform.startswith('java')
 
 is_android = hasattr(sys, 'getandroidapilevel')
 
-if sys.platform not in ('win32', 'vxworks'):
+if sys.platform not in {"win32", "vxworks", "ios", "tvos", "watchos"}:
     unix_shell = '/system/bin/sh' if is_android else '/bin/sh'
 else:
     unix_shell = None
@@ -532,19 +532,35 @@ else:
 is_emscripten = sys.platform == "emscripten"
 is_wasi = sys.platform == "wasi"
 
-has_fork_support = hasattr(os, "fork") and not is_emscripten and not is_wasi
+# Apple mobile platforms (iOS/tvOS/watchOS) are POSIX-like but do not
+# have subprocess or fork support.
+is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"}
+is_apple = is_apple_mobile or sys.platform == "darwin"
+
+has_fork_support = hasattr(os, "fork") and not (
+    is_emscripten
+    or is_wasi
+    or is_apple_mobile
+)
 
 def requires_fork():
     return unittest.skipUnless(has_fork_support, "requires working os.fork()")
 
-has_subprocess_support = not is_emscripten and not is_wasi
+has_subprocess_support = not (
+    is_emscripten
+    or is_wasi
+    or is_apple_mobile
+)
 
 def requires_subprocess():
     """Used for subprocess, os.spawn calls, fd inheritance"""
     return unittest.skipUnless(has_subprocess_support, "requires subprocess support")
 
 # Emscripten's socket emulation and WASI sockets have limitations.
-has_socket_support = not is_emscripten and not is_wasi
+has_socket_support = not (
+    is_emscripten
+    or is_wasi
+)
 
 def requires_working_socket(*, module=False):
     """Skip tests or modules that require working sockets
index 20f38fd36a8876e5277911415f9ebb014606a8cd..22787e32b5f3abe39e6a0c36cc3e947633a2d9b2 100644 (file)
@@ -22,8 +22,8 @@ TESTFN_ASCII = "{}_{}_tmp".format(TESTFN_ASCII, os.getpid())
 
 # TESTFN_UNICODE is a non-ascii filename
 TESTFN_UNICODE = TESTFN_ASCII + "-\xe0\xf2\u0258\u0141\u011f"
-if sys.platform == 'darwin':
-    # In Mac OS X's VFS API file names are, by definition, canonically
+if support.is_apple:
+    # On Apple's VFS API file names are, by definition, canonically
     # decomposed Unicode, encoded using UTF-8. See QA1173:
     # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html
     import unicodedata
@@ -48,8 +48,8 @@ if os.name == 'nt':
                   'encoding (%s). Unicode filename tests may not be effective'
                   % (TESTFN_UNENCODABLE, sys.getfilesystemencoding()))
             TESTFN_UNENCODABLE = None
-# macOS and Emscripten deny unencodable filenames (invalid utf-8)
-elif sys.platform not in {'darwin', 'emscripten', 'wasi'}:
+# Apple and Emscripten deny unencodable filenames (invalid utf-8)
+elif not support.is_apple and sys.platform not in {"emscripten", "wasi"}:
     try:
         # ascii and utf-8 cannot encode the byte 0xff
         b'\xff'.decode(sys.getfilesystemencoding())
index b25c0975736e20ebf9e03eb963568d0992fbdb02..c92c88bd5b2429c90a0c00963ad29ad74f82d188 100644 (file)
@@ -1815,6 +1815,7 @@ class SubprocessTestsMixin:
         else:
             self.assertEqual(-signal.SIGKILL, returncode)
 
+    @support.requires_subprocess()
     def test_subprocess_exec(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo.py')
 
@@ -1836,6 +1837,7 @@ class SubprocessTestsMixin:
         self.check_killed(proto.returncode)
         self.assertEqual(b'Python The Winner', proto.data[1])
 
+    @support.requires_subprocess()
     def test_subprocess_interactive(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo.py')
 
@@ -1863,6 +1865,7 @@ class SubprocessTestsMixin:
         self.loop.run_until_complete(proto.completed)
         self.check_killed(proto.returncode)
 
+    @support.requires_subprocess()
     def test_subprocess_shell(self):
         connect = self.loop.subprocess_shell(
                         functools.partial(MySubprocessProtocol, self.loop),
@@ -1879,6 +1882,7 @@ class SubprocessTestsMixin:
         self.assertEqual(proto.data[2], b'')
         transp.close()
 
+    @support.requires_subprocess()
     def test_subprocess_exitcode(self):
         connect = self.loop.subprocess_shell(
                         functools.partial(MySubprocessProtocol, self.loop),
@@ -1890,6 +1894,7 @@ class SubprocessTestsMixin:
         self.assertEqual(7, proto.returncode)
         transp.close()
 
+    @support.requires_subprocess()
     def test_subprocess_close_after_finish(self):
         connect = self.loop.subprocess_shell(
                         functools.partial(MySubprocessProtocol, self.loop),
@@ -1904,6 +1909,7 @@ class SubprocessTestsMixin:
         self.assertEqual(7, proto.returncode)
         self.assertIsNone(transp.close())
 
+    @support.requires_subprocess()
     def test_subprocess_kill(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo.py')
 
@@ -1920,6 +1926,7 @@ class SubprocessTestsMixin:
         self.check_killed(proto.returncode)
         transp.close()
 
+    @support.requires_subprocess()
     def test_subprocess_terminate(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo.py')
 
@@ -1937,6 +1944,7 @@ class SubprocessTestsMixin:
         transp.close()
 
     @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP")
+    @support.requires_subprocess()
     def test_subprocess_send_signal(self):
         # bpo-31034: Make sure that we get the default signal handler (killing
         # the process). The parent process may have decided to ignore SIGHUP,
@@ -1961,6 +1969,7 @@ class SubprocessTestsMixin:
         finally:
             signal.signal(signal.SIGHUP, old_handler)
 
+    @support.requires_subprocess()
     def test_subprocess_stderr(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo2.py')
 
@@ -1982,6 +1991,7 @@ class SubprocessTestsMixin:
         self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2])
         self.assertEqual(0, proto.returncode)
 
+    @support.requires_subprocess()
     def test_subprocess_stderr_redirect_to_stdout(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo2.py')
 
@@ -2007,6 +2017,7 @@ class SubprocessTestsMixin:
         transp.close()
         self.assertEqual(0, proto.returncode)
 
+    @support.requires_subprocess()
     def test_subprocess_close_client_stream(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo3.py')
 
@@ -2041,6 +2052,7 @@ class SubprocessTestsMixin:
         self.loop.run_until_complete(proto.completed)
         self.check_killed(proto.returncode)
 
+    @support.requires_subprocess()
     def test_subprocess_wait_no_same_group(self):
         # start the new process in a new session
         connect = self.loop.subprocess_shell(
@@ -2053,6 +2065,7 @@ class SubprocessTestsMixin:
         self.assertEqual(7, proto.returncode)
         transp.close()
 
+    @support.requires_subprocess()
     def test_subprocess_exec_invalid_args(self):
         async def connect(**kwds):
             await self.loop.subprocess_exec(
@@ -2066,6 +2079,7 @@ class SubprocessTestsMixin:
         with self.assertRaises(ValueError):
             self.loop.run_until_complete(connect(shell=True))
 
+    @support.requires_subprocess()
     def test_subprocess_shell_invalid_args(self):
 
         async def connect(cmd=None, **kwds):
index 3c8cc5f3649180d15ddb1a5a00f26008f25d8351..210990593adfa9bd046bd4fd07e294a8c99094c3 100644 (file)
@@ -10,7 +10,6 @@ import threading
 import unittest
 from unittest import mock
 import warnings
-from test.support import socket_helper
 try:
     import ssl
 except ImportError:
@@ -18,6 +17,7 @@ except ImportError:
 
 import asyncio
 from test.test_asyncio import utils as test_utils
+from test.support import requires_subprocess, socket_helper
 
 
 def tearDownModule():
@@ -770,6 +770,7 @@ class StreamTests(test_utils.TestCase):
         self.assertEqual(msg2, b"hello world 2!\n")
 
     @unittest.skipIf(sys.platform == 'win32', "Don't have pipes")
+    @requires_subprocess()
     def test_read_all_from_pipe_reader(self):
         # See asyncio issue 168.  This test is derived from the example
         # subprocess_attach_read_pipe.py, but we configure the
index 808b21c66175511c58c49d16b8d266d31939ca47..f50a9ebc031ba8ade59bbad3ba1c7ae3a30583d2 100644 (file)
@@ -47,6 +47,7 @@ class TestSubprocessTransport(base_subprocess.BaseSubprocessTransport):
         self._proc.pid = -1
 
 
+@support.requires_subprocess()
 class SubprocessTransportTests(test_utils.TestCase):
     def setUp(self):
         super().setUp()
@@ -110,6 +111,7 @@ class SubprocessTransportTests(test_utils.TestCase):
         transport.close()
 
 
+@support.requires_subprocess()
 class SubprocessMixin:
 
     def test_stdin_stdout(self):
index d2c8cba6acfa31c6766db4514a0a17a5b0f1e0e8..59ef9f5f58cabc3a5eb1a0122ddc008595cd2b8a 100644 (file)
@@ -1874,7 +1874,7 @@ class TestFunctional(unittest.TestCase):
             wsock.close()
 
 
-@unittest.skipUnless(hasattr(os, 'fork'), 'requires os.fork()')
+@support.requires_fork()
 class TestFork(unittest.IsolatedAsyncioTestCase):
 
     async def test_fork_not_share_event_loop(self):
index 48754d5a63da3b1e475e96faa1b933f9314c6a50..3a5a8abf81e43d4a9794cfe01e55f56c9f408941 100644 (file)
@@ -14,8 +14,7 @@ import io
 
 import textwrap
 from test import support
-from test.support import import_helper
-from test.support import os_helper
+from test.support import import_helper, is_apple, os_helper
 from test.support.script_helper import (
     make_pkg, make_script, make_zip_pkg, make_zip_script,
     assert_python_ok, assert_python_failure, spawn_python, kill_python)
@@ -557,12 +556,17 @@ class CmdLineTest(unittest.TestCase):
             self.assertTrue(text[3].startswith('NameError'))
 
     def test_non_ascii(self):
-        # Mac OS X denies the creation of a file with an invalid UTF-8 name.
+        # Apple platforms deny the creation of a file with an invalid UTF-8 name.
         # Windows allows creating a name with an arbitrary bytes name, but
         # Python cannot a undecodable bytes argument to a subprocess.
-        # WASI does not permit invalid UTF-8 names.
-        if (os_helper.TESTFN_UNDECODABLE
-        and sys.platform not in ('win32', 'darwin', 'emscripten', 'wasi')):
+        # Emscripten/WASI does not permit invalid UTF-8 names.
+        if (
+            os_helper.TESTFN_UNDECODABLE
+            and sys.platform not in {
+                "win32", "emscripten", "wasi"
+            }
+            and not is_apple
+        ):
             name = os.fsdecode(os_helper.TESTFN_UNDECODABLE)
         elif os_helper.TESTFN_NONASCII:
             name = os_helper.TESTFN_NONASCII
index 747c0f9683c19c76e6c4f304fd7bf27aab8e9e00..259778a5cade98feb9d84befdc9d2a1f11c91c38 100644 (file)
@@ -160,6 +160,7 @@ class TestInteractiveConsoleLocalExit(unittest.TestCase, MockSys):
         self.console = code.InteractiveConsole(local_exit=True)
         self.mock_sys()
 
+    @unittest.skipIf(sys.flags.no_site, "exit() isn't defined unless there's a site module")
     def test_exit(self):
         # default exit message
         self.infunc.side_effect = ["exit()"]
index 203dd6fe57dcd9933bba39a0ff2c2df473c88285..6d734d052454d3442d82f98c8b708a06155cc101 100644 (file)
@@ -6,7 +6,9 @@ import os
 import struct
 import sys
 import unittest
-from test.support import verbose, cpython_only, get_pagesize
+from test.support import (
+    cpython_only, get_pagesize, is_apple, requires_subprocess, verbose
+)
 from test.support.import_helper import import_module
 from test.support.os_helper import TESTFN, unlink
 
@@ -56,8 +58,10 @@ class TestFcntl(unittest.TestCase):
         else:
             start_len = "qq"
 
-        if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd'))
-            or sys.platform == 'darwin'):
+        if (
+            sys.platform.startswith(('netbsd', 'freebsd', 'openbsd'))
+            or is_apple
+        ):
             if struct.calcsize('l') == 8:
                 off_t = 'l'
                 pid_t = 'i'
@@ -157,6 +161,7 @@ class TestFcntl(unittest.TestCase):
         self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH)
 
     @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
+    @requires_subprocess()
     def test_lockf_exclusive(self):
         self.f = open(TESTFN, 'wb+')
         cmd = fcntl.LOCK_EX | fcntl.LOCK_NB
@@ -169,6 +174,7 @@ class TestFcntl(unittest.TestCase):
         self.assertEqual(p.exitcode, 0)
 
     @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
+    @requires_subprocess()
     def test_lockf_share(self):
         self.f = open(TESTFN, 'wb+')
         cmd = fcntl.LOCK_SH | fcntl.LOCK_NB
index 2f191ea7a44c1615123fe2db30f2fb78b0000f8d..81115e9db888cf2206de2440e10cb9143094cf7e 100644 (file)
@@ -18,6 +18,7 @@ except ImportError:
 
 from unittest import TestCase, skipUnless
 from test import support
+from test.support import requires_subprocess
 from test.support import threading_helper
 from test.support import socket_helper
 from test.support import warnings_helper
@@ -900,6 +901,7 @@ class TestIPv6Environment(TestCase):
 
 
 @skipUnless(ssl, "SSL not available")
+@requires_subprocess()
 class TestTLS_FTPClassMixin(TestFTPClass):
     """Repeat TestFTPClass tests starting the TLS layer for both control
     and data connections first.
@@ -916,6 +918,7 @@ class TestTLS_FTPClassMixin(TestFTPClass):
 
 
 @skipUnless(ssl, "SSL not available")
+@requires_subprocess()
 class TestTLS_FTPClass(TestCase):
     """Specific TLS_FTP class tests."""
 
index 4f311c2d498e9f4a8ded74ffdaa8e15e50f42205..b77cd4c67d6b2ae5762024d7bc226885fe13b860 100644 (file)
@@ -7,9 +7,9 @@ import os
 import sys
 import unittest
 import warnings
-from test.support import is_emscripten
-from test.support import os_helper
-from test.support import warnings_helper
+from test.support import (
+    is_apple, is_emscripten, os_helper, warnings_helper
+)
 from test.support.script_helper import assert_python_ok
 from test.support.os_helper import FakePath
 
@@ -483,12 +483,16 @@ class CommonTest(GenericTest):
                     self.assertIsInstance(abspath(path), str)
 
     def test_nonascii_abspath(self):
-        if (os_helper.TESTFN_UNDECODABLE
-        # macOS and Emscripten deny the creation of a directory with an
-        # invalid UTF-8 name. Windows allows creating a directory with an
-        # arbitrary bytes name, but fails to enter this directory
-        # (when the bytes name is used).
-        and sys.platform not in ('win32', 'darwin', 'emscripten', 'wasi')):
+        if (
+            os_helper.TESTFN_UNDECODABLE
+            # Apple platforms and Emscripten/WASI deny the creation of a
+            # directory with an invalid UTF-8 name. Windows allows creating a
+            # directory with an arbitrary bytes name, but fails to enter this
+            # directory (when the bytes name is used).
+            and sys.platform not in {
+                "win32", "emscripten", "wasi"
+            } and not is_apple
+        ):
             name = os_helper.TESTFN_UNDECODABLE
         elif os_helper.TESTFN_NONASCII:
             name = os_helper.TESTFN_NONASCII
index 9fa6ecf9c08e279173a9671001ece25f95ae1d3d..d762ec6102ab8aa628b6f9a82f3fdf85d8cbee69 100644 (file)
@@ -30,8 +30,9 @@ from io import BytesIO, StringIO
 
 import unittest
 from test import support
-from test.support import os_helper
-from test.support import threading_helper
+from test.support import (
+    is_apple, os_helper, requires_subprocess, threading_helper
+)
 
 support.requires_working_socket(module=True)
 
@@ -410,8 +411,8 @@ class SimpleHTTPServerTestCase(BaseTestCase):
         reader.close()
         return body
 
-    @unittest.skipIf(sys.platform == 'darwin',
-                     'undecodable name cannot always be decoded on macOS')
+    @unittest.skipIf(is_apple,
+                     'undecodable name cannot always be decoded on Apple platforms')
     @unittest.skipIf(sys.platform == 'win32',
                      'undecodable name cannot be decoded on win32')
     @unittest.skipUnless(os_helper.TESTFN_UNDECODABLE,
@@ -422,11 +423,11 @@ class SimpleHTTPServerTestCase(BaseTestCase):
         with open(os.path.join(self.tempdir, filename), 'wb') as f:
             f.write(os_helper.TESTFN_UNDECODABLE)
         response = self.request(self.base_url + '/')
-        if sys.platform == 'darwin':
-            # On Mac OS the HFS+ filesystem replaces bytes that aren't valid
-            # UTF-8 into a percent-encoded value.
+        if is_apple:
+            # On Apple platforms the HFS+ filesystem replaces bytes that
+            # aren't valid UTF-8 into a percent-encoded value.
             for name in os.listdir(self.tempdir):
-                if name != 'test': # Ignore a filename created in setUp().
+                if name != 'test':  # Ignore a filename created in setUp().
                     filename = name
                     break
         body = self.check_status_and_reason(response, HTTPStatus.OK)
@@ -697,6 +698,7 @@ print("</pre>")
 
 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
         "This test can't be run reliably as root (issue #13308).")
+@requires_subprocess()
 class CGIHTTPServerTestCase(BaseTestCase):
     class request_handler(NoLogRequestHandler, CGIHTTPRequestHandler):
         _test_case_self = None  # populated by each setUp() method call.
index 9e28b936e00bd5748ab4bcad8f8c1a7f36a28391..73669ecc7927763233c5bda1594df68ac0a1bf0e 100644 (file)
@@ -39,11 +39,9 @@ from itertools import cycle, count
 from test import support
 from test.support.script_helper import (
     assert_python_ok, assert_python_failure, run_python_until_end)
-from test.support import import_helper
-from test.support import os_helper
-from test.support import threading_helper
-from test.support import warnings_helper
-from test.support import skip_if_sanitizer
+from test.support import (
+    import_helper, is_apple, os_helper, skip_if_sanitizer, threading_helper, warnings_helper
+)
 from test.support.os_helper import FakePath
 
 import codecs
@@ -606,10 +604,10 @@ class IOTest(unittest.TestCase):
         self.read_ops(f, True)
 
     def test_large_file_ops(self):
-        # On Windows and Mac OSX this test consumes large resources; It takes
-        # a long time to build the >2 GiB file and takes >2 GiB of disk space
-        # therefore the resource must be enabled to run this test.
-        if sys.platform[:3] == 'win' or sys.platform == 'darwin':
+        # On Windows and Apple platforms this test consumes large resources; It
+        # takes a long time to build the >2 GiB file and takes >2 GiB of disk
+        # space therefore the resource must be enabled to run this test.
+        if sys.platform[:3] == 'win' or is_apple:
             support.requires(
                 'largefile',
                 'test requires %s bytes and a long time to run' % self.LARGE)
index 6e17e010e7f355dd53c592c68b100ee3d2f14330..615568e6af21028240a7d3004188844cdb6a168e 100644 (file)
@@ -1,5 +1,5 @@
 from test import support
-from test.support import os_helper, requires_debug_ranges
+from test.support import is_apple_mobile, os_helper, requires_debug_ranges
 from test.support.script_helper import assert_python_ok
 import array
 import io
@@ -286,7 +286,7 @@ class BugsTestCase(unittest.TestCase):
         #if os.name == 'nt' and support.Py_DEBUG:
         if os.name == 'nt':
             MAX_MARSHAL_STACK_DEPTH = 1000
-        elif sys.platform == 'wasi':
+        elif sys.platform == 'wasi' or is_apple_mobile:
             MAX_MARSHAL_STACK_DEPTH = 1500
         else:
             MAX_MARSHAL_STACK_DEPTH = 2000
index b89621e08577be088eba88b5f7999192b199ef00..ac759757d24659ca3ecf4a9f96f6f83fd85d54ba 100644 (file)
@@ -1,5 +1,5 @@
 from test.support import (
-    requires, _2G, _4G, gc_collect, cpython_only, is_emscripten
+    requires, _2G, _4G, gc_collect, cpython_only, is_emscripten, is_apple,
 )
 from test.support.import_helper import import_module
 from test.support.os_helper import TESTFN, unlink
@@ -1067,7 +1067,7 @@ class LargeMmapTests(unittest.TestCase):
         unlink(TESTFN)
 
     def _make_test_file(self, num_zeroes, tail):
-        if sys.platform[:3] == 'win' or sys.platform == 'darwin':
+        if sys.platform[:3] == 'win' or is_apple:
             requires('largefile',
                 'test requires %s bytes and a long time to run' % str(0x180000000))
         f = open(TESTFN, 'w+b')
index ed79a2c24ef30bff0e691166c26e4ca42ec8173f..86af1a8ed8ee15474d909deb81f1b4fd70a5594d 100644 (file)
@@ -3848,6 +3848,7 @@ class TermsizeTests(unittest.TestCase):
         self.assertGreaterEqual(size.columns, 0)
         self.assertGreaterEqual(size.lines, 0)
 
+    @support.requires_subprocess()
     def test_stty_match(self):
         """Check if stty returns the same results
 
@@ -4577,7 +4578,8 @@ class PseudoterminalTests(unittest.TestCase):
         self.addCleanup(os.close, son_fd)
         self.assertEqual(os.ptsname(mother_fd), os.ttyname(son_fd))
 
-    @unittest.skipUnless(hasattr(os, 'spawnl'), "need os.openpty()")
+    @unittest.skipUnless(hasattr(os, 'spawnl'), "need os.spawnl()")
+    @support.requires_subprocess()
     def test_pipe_spawnl(self):
         # gh-77046: On Windows, os.pipe() file descriptors must be created with
         # _O_NOINHERIT to make them non-inheritable. UCRT has no public API to
index b2283cff6cb4622bdba27cd3109299675157af70..2b0795cdad707e190639a035e70011681e314873 100644 (file)
@@ -779,58 +779,62 @@ def test_pdb_where_command():
     (Pdb) continue
     """
 
-def test_pdb_interact_command():
-    """Test interact command
 
-    >>> g = 0
-    >>> dict_g = {}
+# skip this test if sys.flags.no_site = True;
+# exit() isn't defined unless there's a site module.
+if not sys.flags.no_site:
+    def test_pdb_interact_command():
+        """Test interact command
 
-    >>> def test_function():
-    ...     x = 1
-    ...     lst_local = []
-    ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+        >>> g = 0
+        >>> dict_g = {}
 
-    >>> with PdbTestInput([  # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
-    ...     'interact',
-    ...     'x',
-    ...     'g',
-    ...     'x = 2',
-    ...     'g = 3',
-    ...     'dict_g["a"] = True',
-    ...     'lst_local.append(x)',
-    ...     'exit()',
-    ...     'p x',
-    ...     'p g',
-    ...     'p dict_g',
-    ...     'p lst_local',
-    ...     'continue',
-    ... ]):
-    ...    test_function()
-    --Return--
-    > <doctest test.test_pdb.test_pdb_interact_command[2]>(4)test_function()->None
-    -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
-    (Pdb) interact
-    *pdb interact start*
-    ... x
-    1
-    ... g
-    0
-    ... x = 2
-    ... g = 3
-    ... dict_g["a"] = True
-    ... lst_local.append(x)
-    ... exit()
-    *exit from pdb interact command*
-    (Pdb) p x
-    1
-    (Pdb) p g
-    0
-    (Pdb) p dict_g
-    {'a': True}
-    (Pdb) p lst_local
-    [2]
-    (Pdb) continue
-    """
+        >>> def test_function():
+        ...     x = 1
+        ...     lst_local = []
+        ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+
+        >>> with PdbTestInput([  # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
+        ...     'interact',
+        ...     'x',
+        ...     'g',
+        ...     'x = 2',
+        ...     'g = 3',
+        ...     'dict_g["a"] = True',
+        ...     'lst_local.append(x)',
+        ...     'exit()',
+        ...     'p x',
+        ...     'p g',
+        ...     'p dict_g',
+        ...     'p lst_local',
+        ...     'continue',
+        ... ]):
+        ...    test_function()
+        --Return--
+        > <doctest test.test_pdb.test_pdb_interact_command[2]>(4)test_function()->None
+        -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+        (Pdb) interact
+        *pdb interact start*
+        ... x
+        1
+        ... g
+        0
+        ... x = 2
+        ... g = 3
+        ... dict_g["a"] = True
+        ... lst_local.append(x)
+        ... exit()
+        *exit from pdb interact command*
+        (Pdb) p x
+        1
+        (Pdb) p g
+        0
+        (Pdb) p dict_g
+        {'a': True}
+        (Pdb) p lst_local
+        [2]
+        (Pdb) continue
+        """
 
 def test_convenience_variables():
     """Test convenience variables
index 216973350319fe69dd69319839ceeb0fb93aa2d6..648e18d0150ef08d228b23d2c82f352fe2e1c116 100644 (file)
@@ -472,7 +472,8 @@ class PlatformTest(unittest.TestCase):
                   'root:xnu-4570.71.2~1/RELEASE_X86_64'),
                  'x86_64', 'i386')
         arch = ('64bit', '')
-        with mock.patch.object(platform, 'uname', return_value=uname), \
+        with mock.patch.object(sys, "platform", "darwin"), \
+             mock.patch.object(platform, 'uname', return_value=uname), \
              mock.patch.object(platform, 'architecture', return_value=arch):
             for mac_ver, expected_terse, expected in [
                 # darwin: mac_ver() returns empty strings
index 9c382ace806e0f8c5b129c96baa9dec4325b47fd..72e348fbbdcbc14acdd199d44b3da5939caddd93 100644 (file)
@@ -1,7 +1,7 @@
 "Test posix functions"
 
 from test import support
-from test.support import import_helper
+from test.support import is_apple
 from test.support import os_helper
 from test.support import warnings_helper
 from test.support.script_helper import assert_python_ok
@@ -781,9 +781,10 @@ class PosixTester(unittest.TestCase):
             check_stat(uid, gid)
             self.assertRaises(OSError, chown_func, first_param, 0, -1)
             check_stat(uid, gid)
-            if 0 not in os.getgroups():
-                self.assertRaises(OSError, chown_func, first_param, -1, 0)
-                check_stat(uid, gid)
+            if hasattr(os, 'getgroups'):
+                if 0 not in os.getgroups():
+                    self.assertRaises(OSError, chown_func, first_param, -1, 0)
+                    check_stat(uid, gid)
         # test illegal types
         for t in str, float:
             self.assertRaises(TypeError, chown_func, first_param, t(uid), gid)
@@ -1256,8 +1257,8 @@ class PosixTester(unittest.TestCase):
         self.assertIsInstance(lo, int)
         self.assertIsInstance(hi, int)
         self.assertGreaterEqual(hi, lo)
-        # OSX evidently just returns 15 without checking the argument.
-        if sys.platform != "darwin":
+        # Apple plaforms return 15 without checking the argument.
+        if not is_apple:
             self.assertRaises(OSError, posix.sched_get_priority_min, -23)
             self.assertRaises(OSError, posix.sched_get_priority_max, -23)
 
@@ -2028,11 +2029,13 @@ class _PosixSpawnMixin:
 
 
 @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn")
+@support.requires_subprocess()
 class TestPosixSpawn(unittest.TestCase, _PosixSpawnMixin):
     spawn_func = getattr(posix, 'posix_spawn', None)
 
 
 @unittest.skipUnless(hasattr(os, 'posix_spawnp'), "test needs os.posix_spawnp")
+@support.requires_subprocess()
 class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin):
     spawn_func = getattr(posix, 'posix_spawnp', None)
 
index 51e3a46d0df178072ccbb8973a94fcc4ed926512..3f2bac0155fd9e8490a0836e025402d9df26c778 100644 (file)
@@ -1,12 +1,17 @@
-from test.support import verbose, reap_children
-from test.support.os_helper import TESTFN, unlink
+import sys
+import unittest
+from test.support import (
+    is_apple_mobile, is_emscripten, is_wasi, reap_children, verbose
+)
 from test.support.import_helper import import_module
+from test.support.os_helper import TESTFN, unlink
 
-# Skip these tests if termios or fcntl are not available
+# Skip these tests if termios is not available
 import_module('termios')
-# fcntl is a proxy for not being one of the wasm32 platforms even though we
-# don't use this module... a proper check for what crashes those is needed.
-import_module("fcntl")
+
+# Skip tests on WASM platforms, plus iOS/tvOS/watchOS
+if is_apple_mobile or is_emscripten or is_wasi:
+    raise unittest.SkipTest(f"pty tests not required on {sys.platform}")
 
 import errno
 import os
@@ -17,7 +22,6 @@ import select
 import signal
 import socket
 import io # readline
-import unittest
 import warnings
 
 TEST_STRING_1 = b"I wish to buy a fish license.\n"
index 677349c2bfca93da8b4ac6b56feea291978e20cf..643775597c56c672afaf4939dfa29d21e3c5b306 100644 (file)
@@ -6,8 +6,7 @@ import signal
 import socket
 import sys
 from test import support
-from test.support import os_helper
-from test.support import socket_helper
+from test.support import is_apple, os_helper, socket_helper
 from time import sleep
 import unittest
 import unittest.mock
@@ -526,7 +525,7 @@ class ScalableSelectorMixIn:
         try:
             fds = s.select()
         except OSError as e:
-            if e.errno == errno.EINVAL and sys.platform == 'darwin':
+            if e.errno == errno.EINVAL and is_apple:
                 # unexplainable errors on macOS don't need to fail the test
                 self.skipTest("Invalid argument error calling poll()")
             raise
index 8edd75e9907ec02986041b16f3a7c8cc9bd472c3..d96dad4eb9475d2585b1380302f29a50340f863f 100644 (file)
@@ -2148,6 +2148,7 @@ class TestMisc(BaseTest, unittest.TestCase):
             check_chown(dirname, uid, gid)
 
 
+@support.requires_subprocess()
 class TestWhich(BaseTest, unittest.TestCase):
 
     def setUp(self):
@@ -3181,6 +3182,7 @@ class TestGetTerminalSize(unittest.TestCase):
         self.assertGreaterEqual(size.lines, 0)
 
     @unittest.skipUnless(os.isatty(sys.__stdout__.fileno()), "not on tty")
+    @support.requires_subprocess()
     @unittest.skipUnless(hasattr(os, 'get_terminal_size'),
                          'need os.get_terminal_size()')
     def test_stty_match(self):
index 637a0ca3b3697269af11761f4b5ebdecc80989ff..61fb047caf6dab6c66a446cf880921b9a039bb0d 100644 (file)
@@ -13,9 +13,10 @@ import threading
 import time
 import unittest
 from test import support
-from test.support import os_helper
+from test.support import (
+    is_apple, is_apple_mobile, os_helper, threading_helper
+)
 from test.support.script_helper import assert_python_ok, spawn_python
-from test.support import threading_helper
 try:
     import _testcapi
 except ImportError:
@@ -832,7 +833,7 @@ class ItimerTest(unittest.TestCase):
         self.assertEqual(self.hndl_called, True)
 
     # Issue 3864, unknown if this affects earlier versions of freebsd also
-    @unittest.skipIf(sys.platform in ('netbsd5',),
+    @unittest.skipIf(sys.platform in ('netbsd5',) or is_apple_mobile,
         'itimer not reliable (does not mix well with threading) on some BSDs.')
     def test_itimer_virtual(self):
         self.itimer = signal.ITIMER_VIRTUAL
@@ -1344,7 +1345,7 @@ class StressTest(unittest.TestCase):
         # Python handler
         self.assertEqual(len(sigs), N, "Some signals were lost")
 
-    @unittest.skipIf(sys.platform == "darwin", "crashes due to system bug (FB13453490)")
+    @unittest.skipIf(is_apple, "crashes due to system bug (FB13453490)")
     @unittest.skipUnless(hasattr(signal, "SIGUSR1"),
                          "test needs SIGUSR1")
     @threading_helper.requires_working_threading()
index 231448c75f01db070c1dcdab46526874039cef40..1796423499206271beba397e9369412b35cacf44 100644 (file)
@@ -1,9 +1,8 @@
 import unittest
 from test import support
-from test.support import os_helper
-from test.support import socket_helper
-from test.support import threading_helper
-from test.support import refleak_helper
+from test.support import (
+    is_apple, os_helper, refleak_helper, socket_helper, threading_helper
+)
 
 import _thread as thread
 import array
@@ -1196,8 +1195,11 @@ class GeneralModuleTests(unittest.TestCase):
         # Find one service that exists, then check all the related interfaces.
         # I've ordered this by protocols that have both a tcp and udp
         # protocol, at least for modern Linuxes.
-        if (sys.platform.startswith(('freebsd', 'netbsd', 'gnukfreebsd'))
-            or sys.platform in ('linux', 'darwin')):
+        if (
+            sys.platform.startswith(('freebsd', 'netbsd', 'gnukfreebsd'))
+            or sys.platform == 'linux'
+            or is_apple
+        ):
             # avoid the 'echo' service on this platform, as there is an
             # assumption breaking non-standard port/protocol entry
             services = ('daytime', 'qotd', 'domain')
@@ -3708,7 +3710,7 @@ class SCMRightsTest(SendrecvmsgServerTimeoutBase):
     def _testFDPassCMSG_LEN(self):
         self.createAndSendFDs(1)
 
-    @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958")
+    @unittest.skipIf(is_apple, "skipping, see issue #12958")
     @unittest.skipIf(AIX, "skipping, see issue #22397")
     @requireAttrs(socket, "CMSG_SPACE")
     def testFDPassSeparate(self):
@@ -3719,7 +3721,7 @@ class SCMRightsTest(SendrecvmsgServerTimeoutBase):
                              maxcmsgs=2)
 
     @testFDPassSeparate.client_skip
-    @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958")
+    @unittest.skipIf(is_apple, "skipping, see issue #12958")
     @unittest.skipIf(AIX, "skipping, see issue #22397")
     def _testFDPassSeparate(self):
         fd0, fd1 = self.newFDs(2)
@@ -3732,7 +3734,7 @@ class SCMRightsTest(SendrecvmsgServerTimeoutBase):
                                           array.array("i", [fd1]))]),
             len(MSG))
 
-    @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958")
+    @unittest.skipIf(is_apple, "skipping, see issue #12958")
     @unittest.skipIf(AIX, "skipping, see issue #22397")
     @requireAttrs(socket, "CMSG_SPACE")
     def testFDPassSeparateMinSpace(self):
@@ -3746,7 +3748,7 @@ class SCMRightsTest(SendrecvmsgServerTimeoutBase):
                              maxcmsgs=2, ignoreflags=socket.MSG_CTRUNC)
 
     @testFDPassSeparateMinSpace.client_skip
-    @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958")
+    @unittest.skipIf(is_apple, "skipping, see issue #12958")
     @unittest.skipIf(AIX, "skipping, see issue #22397")
     def _testFDPassSeparateMinSpace(self):
         fd0, fd1 = self.newFDs(2)
@@ -3770,7 +3772,7 @@ class SCMRightsTest(SendrecvmsgServerTimeoutBase):
             nbytes = self.sendmsgToServer([msg])
         self.assertEqual(nbytes, len(msg))
 
-    @unittest.skipIf(sys.platform == "darwin", "see issue #24725")
+    @unittest.skipIf(is_apple, "skipping, see issue #12958")
     def testFDPassEmpty(self):
         # Try to pass an empty FD array.  Can receive either no array
         # or an empty array.
index f3efe0f52f4fd73561df4d976504d82c32d0422b..588272448bbfda640d4316c320c66b2156ee9ad3 100644 (file)
@@ -31,7 +31,7 @@ import urllib.parse
 
 from test.support import (
     SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess,
-    is_emscripten, is_wasi
+    is_apple, is_emscripten, is_wasi
 )
 from test.support import gc_collect
 from test.support import threading_helper
@@ -667,7 +667,7 @@ class OpenTests(unittest.TestCase):
             cx.execute(self._sql)
 
     @unittest.skipIf(sys.platform == "win32", "skipped on Windows")
-    @unittest.skipIf(sys.platform == "darwin", "skipped on macOS")
+    @unittest.skipIf(is_apple, "skipped on Apple platforms")
     @unittest.skipIf(is_emscripten or is_wasi, "not supported on Emscripten/WASI")
     @unittest.skipUnless(TESTFN_UNDECODABLE, "only works if there are undecodable paths")
     def test_open_with_undecodable_path(self):
@@ -713,7 +713,7 @@ class OpenTests(unittest.TestCase):
                 cx.execute(self._sql)
 
     @unittest.skipIf(sys.platform == "win32", "skipped on Windows")
-    @unittest.skipIf(sys.platform == "darwin", "skipped on macOS")
+    @unittest.skipIf(is_apple, "skipped on Apple platforms")
     @unittest.skipIf(is_emscripten or is_wasi, "not supported on Emscripten/WASI")
     @unittest.skipUnless(TESTFN_UNDECODABLE, "only works if there are undecodable paths")
     def test_open_undecodable_uri(self):
index d6b6dd6e741700277ded0ad77943324a538a436e..49013a4bcd8af6b74b1a52d57b6baa7a61b38610 100644 (file)
@@ -2,8 +2,7 @@ import unittest
 import os
 import socket
 import sys
-from test.support import os_helper
-from test.support import socket_helper
+from test.support import is_apple, os_helper, socket_helper
 from test.support.import_helper import import_fresh_module
 from test.support.os_helper import TESTFN
 
@@ -247,7 +246,7 @@ class TestFilemode:
         for flag in self.file_flags:
             if flag.startswith("UF"):
                 self.assertTrue(getattr(self.statmod, flag) & self.statmod.UF_SETTABLE, f"{flag} not in UF_SETTABLE")
-            elif sys.platform == 'darwin' and self.statmod is c_stat and flag == 'SF_DATALESS':
+            elif is_apple and self.statmod is c_stat and flag == 'SF_DATALESS':
                 self.assertTrue(self.statmod.SF_DATALESS & self.statmod.SF_SYNTHETIC, "SF_DATALESS not in SF_SYNTHETIC")
                 self.assertFalse(self.statmod.SF_DATALESS & self.statmod.SF_SETTABLE, "SF_DATALESS in SF_SETTABLE")
             else:
index ae6e192a7ab6effa6252f7f57ebe916ae7cb8f07..125f40227118f6366795f5c7443cbe5494d5222d 100644 (file)
@@ -7,7 +7,7 @@ import difflib
 import gc
 from functools import wraps
 import asyncio
-from test.support import import_helper
+from test.support import import_helper, requires_subprocess
 import contextlib
 import os
 import tempfile
@@ -1810,6 +1810,7 @@ class TraceOpcodesTestCase(TraceTestCase):
     def make_tracer():
         return Tracer(trace_opcode_events=True)
 
+    @requires_subprocess()
     def test_trace_opcodes_after_settrace(self):
         """Make sure setting f_trace_opcodes after starting trace works even
         if it's the first time f_trace_opcodes is being set. GH-103615"""
index 47619c8807bafe30c454ac683a5cae07e2ab8841..25c16e3a0b7e430c8f0721fd186287615789a27b 100644 (file)
@@ -5,7 +5,7 @@ import sys
 import unittest
 import warnings
 from unicodedata import normalize
-from test.support import os_helper
+from test.support import is_apple, os_helper
 from test import support
 
 
@@ -23,13 +23,13 @@ filenames = [
     '10_\u1fee\u1ffd',
     ]
 
-# Mac OS X decomposes Unicode names, using Normal Form D.
+# Apple platforms decompose Unicode names, using Normal Form D.
 # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html
 # "However, most volume formats do not follow the exact specification for
 # these normal forms.  For example, HFS Plus uses a variant of Normal Form D
 # in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through
 # U+2FAFF are not decomposed."
-if sys.platform != 'darwin':
+if not is_apple:
     filenames.extend([
         # Specific code points: NFC(fn), NFD(fn), NFKC(fn) and NFKD(fn) all different
         '11_\u0385\u03d3\u03d4',
@@ -119,11 +119,11 @@ class UnicodeFileTests(unittest.TestCase):
             os.stat(name)
             self._apply_failure(os.listdir, name, self._listdir_failure)
 
-    # Skip the test on darwin, because darwin does normalize the filename to
+    # Skip the test on Apple platforms, because they don't normalize the filename to
     # NFD (a variant of Unicode NFD form). Normalize the filename to NFC, NFKC,
     # NFKD in Python is useless, because darwin will normalize it later and so
     # open(), os.stat(), etc. don't raise any exception.
-    @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X')
+    @unittest.skipIf(is_apple, 'irrelevant test on Apple platforms')
     @unittest.skipIf(
         support.is_emscripten or support.is_wasi,
         "test fails on Emscripten/WASI when host platform is macOS."
@@ -142,10 +142,10 @@ class UnicodeFileTests(unittest.TestCase):
             self._apply_failure(os.remove, name)
             self._apply_failure(os.listdir, name)
 
-    # Skip the test on darwin, because darwin uses a normalization different
+    # Skip the test on Apple platforms, because they use a normalization different
     # than Python NFD normalization: filenames are different even if we use
     # Python NFD normalization.
-    @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X')
+    @unittest.skipIf(is_apple, 'irrelevant test on Apple platforms')
     def test_listdir(self):
         sf0 = set(self.files)
         with warnings.catch_warnings():
index 99c9e24994732fac0891d2120212d732b780c189..fa528a675892b5e43c7c97b6ac68b6b8bf03e39a 100644 (file)
@@ -1,6 +1,7 @@
 import unittest
 from test import support
 from test.support import os_helper
+from test.support import requires_subprocess
 from test.support import warnings_helper
 from test import test_urllib
 from unittest import mock
@@ -998,6 +999,7 @@ class HandlerTests(unittest.TestCase):
 
         file_obj.close()
 
+    @requires_subprocess()
     def test_http_body_pipe(self):
         # A file reading from a pipe.
         # A pipe cannot be seek'ed.  There is no way to determine the
index 6dda00efd7bbb6989d4b72c90c5280eb4761786c..ba31beb81e80b0911f116bca19dffb49c05b5d10 100644 (file)
@@ -19,8 +19,8 @@ import sysconfig
 import tempfile
 from test.support import (captured_stdout, captured_stderr,
                           skip_if_broken_multiprocessing_synchronize, verbose,
-                          requires_subprocess, is_emscripten, is_wasi,
-                          requires_venv_with_pip, TEST_HOME_DIR,
+                          requires_subprocess, is_apple_mobile, is_emscripten,
+                          is_wasi, requires_venv_with_pip, TEST_HOME_DIR,
                           requires_resource, copy_python_src_ignore)
 from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree)
 import unittest
@@ -39,8 +39,10 @@ requireVenvCreate = unittest.skipUnless(
     or sys._base_executable != sys.executable,
     'cannot run venv.create from within a venv on this platform')
 
-if is_emscripten or is_wasi:
-    raise unittest.SkipTest("venv is not available on Emscripten/WASI.")
+# Skip tests on WASM platforms, plus iOS/tvOS/watchOS
+if is_apple_mobile or is_emscripten or is_wasi:
+    raise unittest.SkipTest(f"venv tests not required on {sys.platform}")
+
 
 @requires_subprocess()
 def check_output(cmd, encoding=None):
diff --git a/Misc/NEWS.d/next/Tests/2024-02-02-13-18-55.gh-issue-114099.C_ycWg.rst b/Misc/NEWS.d/next/Tests/2024-02-02-13-18-55.gh-issue-114099.C_ycWg.rst
new file mode 100644 (file)
index 0000000..487cd50
--- /dev/null
@@ -0,0 +1 @@
+Added test exclusions required to run the test suite on iOS.