2525logger = logging .getLogger (__name__ )
2626
2727PythonVersion = Sequence [int ]
28- MacVersion = Tuple [int , int ]
28+ AppleVersion = Tuple [int , int ]
2929
3030INTERPRETER_SHORT_NAMES : dict [str , str ] = {
3131 "python" : "py" , # Generic.
@@ -363,7 +363,7 @@ def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str:
363363 return "i386"
364364
365365
366- def _mac_binary_formats (version : MacVersion , cpu_arch : str ) -> list [str ]:
366+ def _mac_binary_formats (version : AppleVersion , cpu_arch : str ) -> list [str ]:
367367 formats = [cpu_arch ]
368368 if cpu_arch == "x86_64" :
369369 if version < (10 , 4 ):
@@ -396,7 +396,7 @@ def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
396396
397397
398398def mac_platforms (
399- version : MacVersion | None = None , arch : str | None = None
399+ version : AppleVersion | None = None , arch : str | None = None
400400) -> Iterator [str ]:
401401 """
402402 Yields the platform tags for a macOS system.
@@ -408,7 +408,7 @@ def mac_platforms(
408408 """
409409 version_str , _ , cpu_arch = platform .mac_ver ()
410410 if version is None :
411- version = cast ("MacVersion " , tuple (map (int , version_str .split ("." )[:2 ])))
411+ version = cast ("AppleVersion " , tuple (map (int , version_str .split ("." )[:2 ])))
412412 if version == (10 , 16 ):
413413 # When built against an older macOS SDK, Python will report macOS 10.16
414414 # instead of the real version.
@@ -424,7 +424,7 @@ def mac_platforms(
424424 stdout = subprocess .PIPE ,
425425 text = True ,
426426 ).stdout
427- version = cast ("MacVersion " , tuple (map (int , version_str .split ("." )[:2 ])))
427+ version = cast ("AppleVersion " , tuple (map (int , version_str .split ("." )[:2 ])))
428428 else :
429429 version = version
430430 if arch is None :
@@ -483,6 +483,57 @@ def mac_platforms(
483483 )
484484
485485
486+ def ios_platforms (
487+ version : AppleVersion | None = None , multiarch : str | None = None
488+ ) -> Iterator [str ]:
489+ """
490+ Yields the platform tags for an iOS system.
491+
492+ :param version: A two-item tuple specifying the iOS version to generate
493+ platform tags for. Defaults to the current iOS version.
494+ :param multiarch: The CPU architecture+ABI to generate platform tags for -
495+ (the value used by `sys.implementation._multiarch` e.g.,
496+ `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current
497+ multiarch value.
498+ """
499+ if version is None :
500+ # if iOS is the current platform, ios_ver *must* be defined. However,
501+ # it won't exist for CPython versions before 3.13, which causes a mypy
502+ # error.
503+ _ , release , _ , _ = platform .ios_ver () # type: ignore[attr-defined]
504+ version = cast ("AppleVersion" , tuple (map (int , release .split ("." )[:2 ])))
505+
506+ if multiarch is None :
507+ multiarch = sys .implementation ._multiarch
508+
509+ ios_platform_template = "ios_{major}_{minor}_{multiarch}"
510+
511+ # Consider any major.minor version from iOS 12.0 to the version prior to the
512+ # version requested by platform. 12.0 is the first iOS version that is known
513+ # to have enough features to support CPython. Consider every possible minor
514+ # release up to X.9. There highest the minor has ever gone is 8 (14.8 and
515+ # 15.8) but having some extra candidates that won't ever match doesn't
516+ # really hurt, and it saves us from having to keep an explicit list of known
517+ # iOS versions in the code.
518+ for major in range (12 , version [0 ]):
519+ for minor in range (0 , 10 ):
520+ yield ios_platform_template .format (
521+ major = major , minor = minor , multiarch = multiarch
522+ )
523+
524+ # Consider every minor version from X.0 to the minor version prior to the
525+ # version requested by the platform.
526+ for minor in range (0 , version [1 ]):
527+ yield ios_platform_template .format (
528+ major = version [0 ], minor = minor , multiarch = multiarch
529+ )
530+
531+ # Consider the actual X.Y version that was requested.
532+ yield ios_platform_template .format (
533+ major = version [0 ], minor = version [1 ], multiarch = multiarch
534+ )
535+
536+
486537def _linux_platforms (is_32bit : bool = _32_BIT_INTERPRETER ) -> Iterator [str ]:
487538 linux = _normalize_string (sysconfig .get_platform ())
488539 if not linux .startswith ("linux_" ):
@@ -512,6 +563,8 @@ def platform_tags() -> Iterator[str]:
512563 """
513564 if platform .system () == "Darwin" :
514565 return mac_platforms ()
566+ elif platform .system () == "iOS" :
567+ return ios_platforms ()
515568 elif platform .system () == "Linux" :
516569 return _linux_platforms ()
517570 else :
0 commit comments