diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 5331615b1b1587..3bcb4b111d669c 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -19,6 +19,7 @@ import types import unittest import warnings +lazy import platform __all__ = [ @@ -33,6 +34,7 @@ "is_resource_enabled", "get_resource_value", "requires", "requires_resource", "requires_freebsd_version", "requires_gil_enabled", "requires_linux_version", "requires_mac_ver", + "requires_ios_ver", "check_syntax_error", "requires_gzip", "requires_bz2", "requires_lzma", "requires_zstd", "bigmemtest", "nomemtest", "bigaddrspacetest", "cpython_only", "get_attribute", @@ -229,7 +231,6 @@ def _force_run(path, func, *args): def _is_gui_available(): if hasattr(_is_gui_available, 'result'): return _is_gui_available.result - import platform reason = None if sys.platform.startswith('win') and platform.win32_is_iot(): reason = "gui is not available on Windows IoT Core" @@ -354,7 +355,6 @@ def _requires_unix_version(sysname, min_version): For example, @_requires_unix_version('FreeBSD', (7, 2)) raises SkipTest if the FreeBSD version is less than 7.2. """ - import platform min_version_txt = '.'.join(map(str, min_version)) version_txt = platform.release().split('-', 1)[0] if platform.system() == sysname: @@ -392,19 +392,12 @@ def requires_linux_version(*min_version): """ return _requires_unix_version('Linux', min_version) -def requires_mac_ver(*min_version): - """Decorator raising SkipTest if the OS is Mac OS X and the OS X - version if less than min_version. - - For example, @requires_mac_ver(10, 5) raises SkipTest if the OS X version - is lesser than 10.5. - """ +def _requires_apple_os_version(name, sys_platform, get_version_text, min_version): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): - if sys.platform == 'darwin': - import platform - version_txt = platform.mac_ver()[0] + if sys.platform == sys_platform: + version_txt = get_version_text() try: version = tuple(map(int, version_txt.split('.'))) except ValueError: @@ -413,14 +406,40 @@ def wrapper(*args, **kw): if version < min_version: min_version_txt = '.'.join(map(str, min_version)) raise unittest.SkipTest( - "Mac OS X %s or higher required, not %s" - % (min_version_txt, version_txt)) + f"{name} {min_version_txt} or higher required, " + + f"not {version_txt}") return func(*args, **kw) wrapper.min_version = min_version return wrapper return decorator +def requires_mac_ver(*min_version): + """Decorator raising SkipTest if the OS is Mac OS X and the OS X + version if less than min_version. + + For example, @requires_mac_ver(10, 5) raises SkipTest if the OS X version + is lesser than 10.5. + """ + return _requires_apple_os_version( + "macOS", "darwin", + get_version_text=lambda: platform.mac_ver()[0], + min_version=min_version) + + +def requires_ios_ver(*min_version): + """Decorator raising SkipTest if the OS is iOS and the OS version + version if less than min_version. + + For example, requires_ios_ver(16, 0) raises SkipTest if the iOS version + is lesser than 16.0. + """ + return _requires_apple_os_version( + "iOS", "ios", + get_version_text=lambda: platform.ios_ver().release, + min_version=min_version) + + def thread_unsafe(reason): """Mark a test as not thread safe. When the test runner is run with --parallel-threads=N, the test will be run in a single thread.""" @@ -2223,7 +2242,6 @@ def setswitchinterval(interval): if is_android and interval < minimum_interval: global _old_android_emulator if _old_android_emulator is None: - import platform av = platform.android_ver() _old_android_emulator = av.is_emulator and av.api_level < 24 if _old_android_emulator: @@ -3480,7 +3498,6 @@ def linked_to_musl(): # On linux, we'll depend on the platform module to do the check, so new # musl platforms should add support in that module if possible. - import platform lib, version = platform.libc_ver() if lib != 'musl': _linked_to_musl = False diff --git a/Lib/test/test_os/test_posix.py b/Lib/test/test_os/test_posix.py index 7b8f8d2ddadd96..82115c338906fc 100644 --- a/Lib/test/test_os/test_posix.py +++ b/Lib/test/test_os/test_posix.py @@ -1946,6 +1946,8 @@ def test_readlink_with_fd_throws_not_implemented_error(self): @unittest.skipUnless(sys.platform in ["linux", "android", "darwin", "ios"], "feature not supported on this platform") + @support.requires_mac_ver(13, 0) + @support.requires_ios_ver(16, 0) def test_readlink_is_marked_as_supports_fd(self): self.assertIn(os.readlink, os.supports_fd)