Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"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
Expand Down Expand Up @@ -522,7 +522,7 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'):

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
Expand All @@ -532,12 +532,26 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
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
and not is_wasi
and not 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
and not is_wasi
and not is_apple_mobile
)

def requires_subprocess():
"""Used for subprocess, os.spawn calls, fd inheritance"""
Expand Down
8 changes: 4 additions & 4 deletions Lib/test/support/os_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

# 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
Expand All @@ -48,8 +48,8 @@
'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())
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_asyncio/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,7 @@ async def test():
next(it)


@support.requires_subprocess()
class SubprocessTestsMixin:

def check_terminated(self, returncode):
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_asyncio/test_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import unittest
from unittest import mock
import warnings
from test.support import socket_helper
try:
import ssl
except ImportError:
ssl = None

import asyncio
from test.test_asyncio import utils as test_utils
from test.support import requires_subprocess, socket_helper


def tearDownModule():
Expand Down Expand Up @@ -770,6 +770,7 @@ async def client(addr):
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
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_asyncio/test_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def _start(self, *args, **kwargs):
self._proc.pid = -1


@support.requires_subprocess()
class SubprocessTransportTests(test_utils.TestCase):
def setUp(self):
super().setUp()
Expand Down Expand Up @@ -110,6 +111,7 @@ def test_subprocess_repr(self):
transport.close()


@support.requires_subprocess()
class SubprocessMixin:

def test_stdin_stdout(self):
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_asyncio/test_unix_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1875,6 +1875,7 @@ async def runner():


@unittest.skipUnless(hasattr(os, 'fork'), 'requires os.fork()')
@support.requires_subprocess()
class TestFork(unittest.IsolatedAsyncioTestCase):

async def test_fork_not_share_event_loop(self):
Expand Down
16 changes: 10 additions & 6 deletions Lib/test/test_cmd_line_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

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)
Expand Down Expand Up @@ -557,12 +556,17 @@ def test_pep_409_verbiage(self):
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
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_code_module.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"Test InteractiveConsole and InteractiveInterpreter from code module"
import site
import sys
import unittest
from textwrap import dedent
Expand Down Expand Up @@ -160,6 +161,7 @@ def setUp(self):
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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work if the import site does not exist in the file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does - the import site was a leftover from a previous attempt to fix the problem that was ultimately resolved with the no_site-based skip. I've removed the import.

def test_exit(self):
# default exit message
self.infunc.side_effect = ["exit()"]
Expand Down
12 changes: 9 additions & 3 deletions Lib/test/test_fcntl.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
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
)
Comment on lines +9 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to do this change often. In the future, could you add a trailing comma, to make future diffs nicer?
(Or simply add another line if the current one gets too long:

from test.support import verbose, cpython_only, get_pagesize
from test.support import is_apple, requires_subprocess

)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@encukou Sure, no problem.

One of the issues I've hit is that the "preferred" style for imports varies wildly between files. I appreciate there's 30 years of historical baggage in the existing code - but is there a reason either of those two approaches is preferred over isort/black style syntax:

from test.support import (
    cpython_only, 
    get_pagesize, 
    is_apple, 
    requires_subprocess, 
    verbose,
)

Running black over every file I touch would make for unreadable patches; but if little black touches when the line is already being altered would be looked on favourably, then that's an easy tweak to make.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works too -- there's a trailing comma, so future diffs won't need to add it.

(The 30 years of baggage also means there is no shared preference for stuff that isn't in PEP 8. I'm partial to repeating from <name> because it's searchable with grep -- you don't need a code analyzer -- but that's just personal opinion.)

if little black touches when the line is already being altered would be looked on favourably

Sure! As long as it helps readability :)

from test.support.import_helper import import_module
from test.support.os_helper import TESTFN, unlink

Expand Down Expand Up @@ -56,8 +58,10 @@ def get_lockdata():
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'
Expand Down Expand Up @@ -157,6 +161,7 @@ def test_flock(self):
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
Expand All @@ -169,6 +174,7 @@ def test_lockf_exclusive(self):
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
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_ftplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

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
Expand Down Expand Up @@ -900,6 +901,7 @@ def retr():


@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.
Expand All @@ -916,6 +918,7 @@ def setUp(self, encoding=DEFAULT_ENCODING):


@skipUnless(ssl, "SSL not available")
@requires_subprocess()
class TestTLS_FTPClass(TestCase):
"""Specific TLS_FTP class tests."""

Expand Down
22 changes: 13 additions & 9 deletions Lib/test/test_genericpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
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

Expand Down Expand Up @@ -483,12 +483,16 @@ def test_abspath_issue3426(self):
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
Expand Down
18 changes: 10 additions & 8 deletions Lib/test/test_httpservers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@

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)

Expand Down Expand Up @@ -410,8 +411,8 @@ def close_conn():
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,
Expand All @@ -422,11 +423,11 @@ def test_undecodable_filename(self):
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)
Expand Down Expand Up @@ -697,6 +698,7 @@ def test_html_escape_filename(self):

@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.
Expand Down
16 changes: 7 additions & 9 deletions Lib/test/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@
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
Expand Down Expand Up @@ -606,10 +604,10 @@ def test_raw_bytes_io(self):
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)
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_marshal.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -286,7 +286,7 @@ def test_recursion_limit(self):
#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
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_mmap.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -1067,7 +1067,7 @@ def tearDown(self):
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')
Expand Down
4 changes: 3 additions & 1 deletion Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -3848,6 +3848,7 @@ def test_does_not_crash(self):
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

Expand Down Expand Up @@ -4577,7 +4578,8 @@ def test_posix_pty_functions(self):
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
Expand Down
Loading