4646import sys
4747import sysconfig
4848import time
49- from collections .abc import Sequence
49+ from collections .abc import Callable , Sequence
5050from contextlib import contextmanager
5151from datetime import datetime , timezone
5252from os .path import basename , relpath
5353from pathlib import Path
5454from subprocess import CalledProcessError
55- from typing import Callable
5655
5756EnvironmentT = dict [str , str ]
5857ArgsT = Sequence [str | Path ]
@@ -140,17 +139,15 @@ def print_env(env: EnvironmentT) -> None:
140139def apple_env (host : str ) -> EnvironmentT :
141140 """Construct an Apple development environment for the given host."""
142141 env = {
143- "PATH" : ":" .join (
144- [
145- str (PYTHON_DIR / "Apple/iOS/Resources/bin" ),
146- str (subdir (host ) / "prefix" ),
147- "/usr/bin" ,
148- "/bin" ,
149- "/usr/sbin" ,
150- "/sbin" ,
151- "/Library/Apple/usr/bin" ,
152- ]
153- ),
142+ "PATH" : ":" .join ([
143+ str (PYTHON_DIR / "Apple/iOS/Resources/bin" ),
144+ str (subdir (host ) / "prefix" ),
145+ "/usr/bin" ,
146+ "/bin" ,
147+ "/usr/sbin" ,
148+ "/sbin" ,
149+ "/Library/Apple/usr/bin" ,
150+ ]),
154151 }
155152
156153 return env
@@ -196,14 +193,10 @@ def clean(context: argparse.Namespace, target: str = "all") -> None:
196193 paths .append (target )
197194
198195 if target in {"all" , "hosts" , "test" }:
199- paths .extend (
200- [
201- path .name
202- for path in CROSS_BUILD_DIR .glob (
203- f"{ context .platform } -testbed.*"
204- )
205- ]
206- )
196+ paths .extend ([
197+ path .name
198+ for path in CROSS_BUILD_DIR .glob (f"{ context .platform } -testbed.*" )
199+ ])
207200
208201 for path in paths :
209202 delete_path (path )
@@ -352,18 +345,16 @@ def download(url: str, target_dir: Path) -> Path:
352345
353346 out_path = target_path / basename (url )
354347 if not Path (out_path ).is_file ():
355- run (
356- [
357- "curl" ,
358- "-Lf" ,
359- "--retry" ,
360- "5" ,
361- "--retry-all-errors" ,
362- "-o" ,
363- out_path ,
364- url ,
365- ]
366- )
348+ run ([
349+ "curl" ,
350+ "-Lf" ,
351+ "--retry" ,
352+ "5" ,
353+ "--retry-all-errors" ,
354+ "-o" ,
355+ out_path ,
356+ url ,
357+ ])
367358 else :
368359 print (f"Using cached version of { basename (url )} " )
369360 return out_path
@@ -468,8 +459,7 @@ def package_version(prefix_path: Path) -> str:
468459
469460
470461def lib_platform_files (dirname , names ):
471- """A file filter that ignores platform-specific files in the lib directory.
472- """
462+ """A file filter that ignores platform-specific files in lib."""
473463 path = Path (dirname )
474464 if (
475465 path .parts [- 3 ] == "lib"
@@ -478,15 +468,15 @@ def lib_platform_files(dirname, names):
478468 ):
479469 return names
480470 elif path .parts [- 2 ] == "lib" and path .parts [- 1 ].startswith ("python" ):
481- ignored_names = set (
471+ ignored_names = {
482472 name
483473 for name in names
484474 if (
485475 name .startswith ("_sysconfigdata_" )
486476 or name .startswith ("_sysconfig_vars_" )
487477 or name == "build-details.json"
488478 )
489- )
479+ }
490480 else :
491481 ignored_names = set ()
492482
@@ -499,7 +489,9 @@ def lib_non_platform_files(dirname, names):
499489 """
500490 path = Path (dirname )
501491 if path .parts [- 2 ] == "lib" and path .parts [- 1 ].startswith ("python" ):
502- return set (names ) - lib_platform_files (dirname , names ) - {"lib-dynload" }
492+ return (
493+ set (names ) - lib_platform_files (dirname , names ) - {"lib-dynload" }
494+ )
503495 else :
504496 return set ()
505497
@@ -514,7 +506,8 @@ def create_xcframework(platform: str) -> str:
514506 package_path .mkdir ()
515507 except FileExistsError :
516508 raise RuntimeError (
517- f"{ platform } XCframework already exists; do you need to run with --clean?"
509+ f"{ platform } XCframework already exists; do you need to run "
510+ "with --clean?"
518511 ) from None
519512
520513 frameworks = []
@@ -607,7 +600,7 @@ def create_xcframework(platform: str) -> str:
607600 print (f" - { slice_name } binaries" )
608601 shutil .copytree (first_path / "bin" , slice_path / "bin" )
609602
610- # Copy the include path (this will be a symlink to the framework headers)
603+ # Copy the include path (a symlink to the framework headers)
611604 print (f" - { slice_name } include files" )
612605 shutil .copytree (
613606 first_path / "include" ,
@@ -659,7 +652,8 @@ def create_xcframework(platform: str) -> str:
659652 # statically link those libraries into a Framework, you become
660653 # responsible for providing a privacy manifest for that framework.
661654 xcprivacy_file = {
662- "OpenSSL" : subdir (host_triple ) / "prefix/share/OpenSSL.xcprivacy"
655+ "OpenSSL" : subdir (host_triple )
656+ / "prefix/share/OpenSSL.xcprivacy"
663657 }
664658 print (f" - { multiarch } xcprivacy files" )
665659 for module , lib in [
@@ -669,7 +663,8 @@ def create_xcframework(platform: str) -> str:
669663 shutil .copy (
670664 xcprivacy_file [lib ],
671665 slice_path
672- / f"lib-{ arch } /python{ version_tag } /lib-dynload/{ module } .xcprivacy" ,
666+ / f"lib-{ arch } /python{ version_tag } "
667+ / f"lib-dynload/{ module } .xcprivacy" ,
673668 )
674669
675670 print (" - build tools" )
@@ -692,18 +687,16 @@ def package(context: argparse.Namespace) -> None:
692687
693688 # Clone testbed
694689 print ()
695- run (
696- [
697- sys .executable ,
698- "Apple/testbed" ,
699- "clone" ,
700- "--platform" ,
701- context .platform ,
702- "--framework" ,
703- CROSS_BUILD_DIR / context .platform / "Python.xcframework" ,
704- CROSS_BUILD_DIR / context .platform / "testbed" ,
705- ]
706- )
690+ run ([
691+ sys .executable ,
692+ "Apple/testbed" ,
693+ "clone" ,
694+ "--platform" ,
695+ context .platform ,
696+ "--framework" ,
697+ CROSS_BUILD_DIR / context .platform / "Python.xcframework" ,
698+ CROSS_BUILD_DIR / context .platform / "testbed" ,
699+ ])
707700
708701 # Build the final archive
709702 archive_name = (
@@ -757,7 +750,7 @@ def build(context: argparse.Namespace, host: str | None = None) -> None:
757750 package (context )
758751
759752
760- def test (context : argparse .Namespace , host : str | None = None ) -> None :
753+ def test (context : argparse .Namespace , host : str | None = None ) -> None : # noqa: PT028
761754 """The implementation of the "test" command."""
762755 if host is None :
763756 host = context .host
@@ -795,18 +788,16 @@ def test(context: argparse.Namespace, host: str | None = None) -> None:
795788 / f"Frameworks/{ apple_multiarch (host )} "
796789 )
797790
798- run (
799- [
800- sys .executable ,
801- "Apple/testbed" ,
802- "clone" ,
803- "--platform" ,
804- context .platform ,
805- "--framework" ,
806- framework_path ,
807- testbed_dir ,
808- ]
809- )
791+ run ([
792+ sys .executable ,
793+ "Apple/testbed" ,
794+ "clone" ,
795+ "--platform" ,
796+ context .platform ,
797+ "--framework" ,
798+ framework_path ,
799+ testbed_dir ,
800+ ])
810801
811802 run (
812803 [
@@ -840,7 +831,7 @@ def apple_sim_host(platform_name: str) -> str:
840831 """Determine the native simulator target for this platform."""
841832 for _ , slice_parts in HOSTS [platform_name ].items ():
842833 for host_triple in slice_parts :
843- parts = host_triple .split ('-' )
834+ parts = host_triple .split ("-" )
844835 if parts [0 ] == platform .machine () and parts [- 1 ] == "simulator" :
845836 return host_triple
846837
@@ -968,20 +959,29 @@ def parse_args() -> argparse.Namespace:
968959 cmd .add_argument (
969960 "--simulator" ,
970961 help = (
971- "The name of the simulator to use (eg: 'iPhone 16e'). Defaults to "
972- "the most recently released 'entry level' iPhone device. Device "
973- "architecture and OS version can also be specified; e.g., "
974- "`--simulator 'iPhone 16 Pro,arch=arm64,OS=26.0'` would run on "
975- "an ARM64 iPhone 16 Pro simulator running iOS 26.0."
962+ "The name of the simulator to use (eg: 'iPhone 16e'). "
963+ "Defaults to the most recently released 'entry level' "
964+ "iPhone device. Device architecture and OS version can also "
965+ "be specified; e.g., "
966+ "`--simulator 'iPhone 16 Pro,arch=arm64,OS=26.0'` would "
967+ "run on an ARM64 iPhone 16 Pro simulator running iOS 26.0."
976968 ),
977969 )
978970 group = cmd .add_mutually_exclusive_group ()
979971 group .add_argument (
980- "--fast-ci" , action = "store_const" , dest = "ci_mode" , const = "fast" ,
981- help = "Add test arguments for GitHub Actions" )
972+ "--fast-ci" ,
973+ action = "store_const" ,
974+ dest = "ci_mode" ,
975+ const = "fast" ,
976+ help = "Add test arguments for GitHub Actions" ,
977+ )
982978 group .add_argument (
983- "--slow-ci" , action = "store_const" , dest = "ci_mode" , const = "slow" ,
984- help = "Add test arguments for buildbots" )
979+ "--slow-ci" ,
980+ action = "store_const" ,
981+ dest = "ci_mode" ,
982+ const = "slow" ,
983+ help = "Add test arguments for buildbots" ,
984+ )
985985
986986 for subcommand in [configure_build , configure_host , build , ci ]:
987987 subcommand .add_argument (
0 commit comments