From e30787fdb4d11beed971a4dc8c30b2f6f368fe79 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 25 Jun 2024 15:26:51 +0800 Subject: [PATCH 01/11] Add --app-store-compliance configuration option. --- Doc/library/urllib.parse.rst | 10 ++- Doc/using/configure.rst | 11 ++++ Doc/using/ios.rst | 18 ++++++ Doc/using/mac.rst | 22 +++++++ Mac/Resources/app-store-compliance.patch | 29 +++++++++ Makefile.pre.in | 12 +++- configure | 78 ++++++++++++++++++++++++ configure.ac | 63 +++++++++++++++++++ 8 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 Mac/Resources/app-store-compliance.patch diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index 27909b763e9e43..7f83a45e0a69cf 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -22,11 +22,19 @@ to an absolute URL given a "base URL." The module has been designed to match the internet RFC on Relative Uniform Resource Locators. It supports the following URL schemes: ``file``, ``ftp``, -``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``mailto``, ``mms``, +``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``itms-services``, ``mailto``, ``mms``, ``news``, ``nntp``, ``prospero``, ``rsync``, ``rtsp``, ``rtsps``, ``rtspu``, ``sftp``, ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``, ``telnet``, ``wais``, ``ws``, ``wss``. +.. note:: + + The inclusion of the ``itms-services`` URL scheme can prevent an app from + passing Apple's App Store review process for the macOS and iOS App Stores. + Handling for the ``itms-services`` scheme is always removed on iOS; on + macOS, it *may* be removed if Python has been built with the + ``--with-app-store-compliance`` option. + The :mod:`urllib.parse` module defines functions that fall into two broad categories: URL parsing and URL quoting. These are covered in detail in the following sections. diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 428ee5275276a0..76174a233c368d 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -945,6 +945,17 @@ See :source:`Mac/README.rst`. Specify the name for the python framework on macOS only valid when :option:`--enable-framework` is set (default: ``Python``). +.. option:: --with-app-store-compliance +.. option:: --with-app-store-compliance=PATCH-FILE + + The Python standard library contains strings that are known to cause + trigger automated inspection tools when submitted for distribution by + the macOS App Store. If enabled, this option will apply the list of + patches that are known to correct app store compliance. A custom patch + file can also be specified. This option is disabled by default. + + .. versionadded:: 3.13 + iOS Options ----------- diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst index 71fc29c450c8eb..4eb93d33045625 100644 --- a/Doc/using/ios.rst +++ b/Doc/using/ios.rst @@ -312,3 +312,21 @@ modules in your app, some additional steps will be required: * If you're using a separate folder for third-party packages, ensure that folder is included as part of the ``PYTHONPATH`` configuration in step 10. + +App Store Compliance +==================== + +The only mechanism for distributing apps to third-party iOS devices is to +submit the app to the iOS App Store; app submitted for distribution must pass +Apple's app review process. This process includes a set of automated validation +rules that inspect the submitted application bundle for problematic code. + +The Python standard library contains some code that is known to violate these +automated rules. While these violations appear to be false positives, Apple's +review rules cannot be challenged; so, it is necessary to modify the Python +standard library for an app to pass App Store review. + +The Python source tree contains +:source:`a patch file ` that will remove +all code that is known to cause issues with the App Store review process. This +patch is applied automatically when building for iOS. diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 31d37aad2a7408..a3e4a25d0a6915 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -188,6 +188,28 @@ distributable application: * `PyInstaller `__: A cross-platform packaging tool that creates a single file or folder as a distributable artifact. +App Store Compliance +-------------------- + +Apps submitted for distribution through the macOS App Store must pass Apple's +app review process. This process includes a set of automated validation rules +that inspect the submitted application bundle for problematic code. + +The Python standard library contains some code that is known to violate these +automated rules. While these violations appear to be false positives, Apple's +review rules cannot be challenged. Therefore, it is necessary to modify the +Python standard library for an app to pass App Store review. + +The Python source tree contains +:source:`a patch file ` that will remove +all code that is known to cause issues with the App Store review process. This +patch is applied automatically when Python is configured with the +``--with-app-store-compliance`` option. + +This patch is not normally required to use Python on a Mac; nor is it required +if you are distributing an app *outside* the macOS App Store. It is *only* +required if you are using the macOS App Store as a distribution channel. + Other Resources =============== diff --git a/Mac/Resources/app-store-compliance.patch b/Mac/Resources/app-store-compliance.patch new file mode 100644 index 00000000000000..f4b7decc01cf1f --- /dev/null +++ b/Mac/Resources/app-store-compliance.patch @@ -0,0 +1,29 @@ +diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py +index d6c83a75c1c..19ed4e01091 100644 +--- a/Lib/test/test_urlparse.py ++++ b/Lib/test/test_urlparse.py +@@ -237,11 +237,6 @@ def test_roundtrips(self): + '','',''), + ('git+ssh', 'git@github.com','/user/project.git', + '', '')), +- ('itms-services://?action=download-manifest&url=https://example.com/app', +- ('itms-services', '', '', '', +- 'action=download-manifest&url=https://example.com/app', ''), +- ('itms-services', '', '', +- 'action=download-manifest&url=https://example.com/app', '')), + ('+scheme:path/to/file', + ('', '', '+scheme:path/to/file', '', '', ''), + ('', '', '+scheme:path/to/file', '', '')), +diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py +index 8f724f907d4..148caf742c9 100644 +--- a/Lib/urllib/parse.py ++++ b/Lib/urllib/parse.py +@@ -59,7 +59,7 @@ + 'imap', 'wais', 'file', 'mms', 'https', 'shttp', + 'snews', 'prospero', 'rtsp', 'rtsps', 'rtspu', 'rsync', + 'svn', 'svn+ssh', 'sftp', 'nfs', 'git', 'git+ssh', +- 'ws', 'wss', 'itms-services'] ++ 'ws', 'wss'] + + uses_params = ['', 'ftp', 'hdl', 'prospero', 'http', 'imap', + 'https', 'shttp', 'rtsp', 'rtsps', 'rtspu', 'sip', diff --git a/Makefile.pre.in b/Makefile.pre.in index 6551c2ec4cea87..1dff7b6e68ee5b 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -178,6 +178,9 @@ EXPORTSFROM= @EXPORTSFROM@ EXE= @EXEEXT@ BUILDEXE= @BUILDEXEEXT@ +# Name of the patch file to apply for app store compliance +APP_STORE_COMPLIANCE_PATCH=@APP_STORE_COMPLIANCE_PATCH@ + # Short name and location for Mac OS X Python framework UNIVERSALSDK=@UNIVERSALSDK@ PYTHONFRAMEWORK= @PYTHONFRAMEWORK@ @@ -691,7 +694,7 @@ list-targets: @grep -E '^[A-Za-z][-A-Za-z0-9]+:' Makefile | awk -F : '{print $$1}' .PHONY: build_all -build_all: check-clean-src $(BUILDPYTHON) platform sharedmods \ +build_all: check-clean-src @APP_STORE_COMPLIANCE_PATCH_TARGET@ $(BUILDPYTHON) platform sharedmods \ gdbhooks Programs/_testembed scripts checksharedmods rundsymutil .PHONY: build_wasm @@ -927,6 +930,13 @@ SRC_GDB_HOOKS=$(srcdir)/Tools/gdb/libpython.py $(BUILDPYTHON)-gdb.py: $(SRC_GDB_HOOKS) $(INSTALL_DATA) $(SRC_GDB_HOOKS) $(BUILDPYTHON)-gdb.py +# Compliance with app stores (such as iOS and macOS) sometimes requires making +# modifications to the Python standard library. If enabled, apply the patch of +# known modifications to the source tree before building. +.PHONY: app-store-compliance +app-store-compliance: + patch -p1 @APP_STORE_COMPLIANCE_PATCH_FLAGS@ < $(srcdir)/$(APP_STORE_COMPLIANCE_PATCH) + # This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary # minimal framework (not including the Lib directory and such) in the current # directory. diff --git a/configure b/configure index 0f7ea7dfb5259d..7f3abc1e0875f7 100755 --- a/configure +++ b/configure @@ -981,6 +981,9 @@ IPHONEOS_DEPLOYMENT_TARGET EXPORT_MACOSX_DEPLOYMENT_TARGET CONFIGURE_MACOSX_DEPLOYMENT_TARGET _PYTHON_HOST_PLATFORM +APP_STORE_COMPLIANCE_PATCH_FLAGS +APP_STORE_COMPLIANCE_PATCH_TARGET +APP_STORE_COMPLIANCE_PATCH INSTALLTARGETS FRAMEWORKINSTALLAPPSPREFIX FRAMEWORKUNIXTOOLSPREFIX @@ -1076,6 +1079,7 @@ enable_universalsdk with_universal_archs with_framework_name enable_framework +with_app_store_compliance with_emscripten_target enable_wasm_dynamic_linking enable_wasm_pthreads @@ -1855,6 +1859,10 @@ Optional Packages: specify the name for the python framework on macOS only valid when --enable-framework is set. see Mac/README.rst (default is 'Python') + --with-app-store-compliance=[=PATCH-FILE] + Enable any patches required for compiliance with app + stores. Optional PATCH-FILE specifies the custom + patch to apply. --with-emscripten-target=[browser|node] Emscripten platform --with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty, @@ -4430,6 +4438,76 @@ fi printf "%s\n" "#define _PYTHONFRAMEWORK \"${PYTHONFRAMEWORK}\"" >>confdefs.h +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-app-store-compliance" >&5 +printf %s "checking for --with-app-store-compliance... " >&6; } + +# Check whether --with-app_store_compliance was given. +if test ${with_app_store_compliance+y} +then : + withval=$with_app_store_compliance; + case "$withval" in + yes) + case $ac_sys_system in + Darwin) + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + ;; + iOS) + # iOS is able to share the macOS patch + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + ;; + *) as_fn_error $? "No default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; + esac + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying default app store compliance patch\"" >&5 +printf "%s\n" "\"applying default app store compliance patch\"" >&6; } + ;; + *) + APP_STORE_COMPLIANCE_PATCH="${withval}" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying custom app store compliance patch\"" >&5 +printf "%s\n" "\"applying custom app store compliance patch\"" >&6; } + ;; + esac + +else $as_nop + + case $ac_sys_system in + iOS) + # Always apply the compliance patch on iOS; we can use the macOS patch + APP_STORE_COMPLIANCE_PATCH="iOS/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying default app store compliance patch\"" >&5 +printf "%s\n" "\"applying default app store compliance patch\"" >&6; } + ;; + Darwin) + # Always *check* the compliance patch on macOS + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS="--dry-run" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"checking (not applying) default app store compliance patch\"" >&5 +printf "%s\n" "\"checking (not applying) default app store compliance patch\"" >&6; } + ;; + *) + # No app compliance patching on any other platform + APP_STORE_COMPLIANCE_PATCH= + APP_STORE_COMPLIANCE_PATCH_TARGET= + APP_STORE_COMPLIANCE_PATCH_FLAGS= + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"not patching for app store compliance\"" >&5 +printf "%s\n" "\"not patching for app store compliance\"" >&6; } + ;; + esac + +fi + + + + + if test "$cross_compiling" = yes; then case "$host" in diff --git a/configure.ac b/configure.ac index a4698451465155..7b14e2c54d3b41 100644 --- a/configure.ac +++ b/configure.ac @@ -695,6 +695,69 @@ AC_SUBST([INSTALLTARGETS]) AC_DEFINE_UNQUOTED([_PYTHONFRAMEWORK], ["${PYTHONFRAMEWORK}"], [framework name]) +dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output +AC_MSG_CHECKING([for --with-app-store-compliance]) +AC_ARG_WITH( + [app_store_compliance], + [AS_HELP_STRING( + [--with-app-store-compliance=@<:@=PATCH-FILE@:>@], + [Enable any patches required for compiliance with app stores. + Optional PATCH-FILE specifies the custom patch to apply.] + )],[ + case "$withval" in + yes) + case $ac_sys_system in + Darwin) + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + ;; + iOS) + # iOS is able to share the macOS patch + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + ;; + *) AC_MSG_ERROR([No default app store compliance patch available for $ac_sys_system]) ;; + esac + AC_MSG_RESULT(["applying default app store compliance patch"]) + ;; + *) + APP_STORE_COMPLIANCE_PATCH="${withval}" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + AC_MSG_RESULT(["applying custom app store compliance patch"]) + ;; + esac + ],[ + case $ac_sys_system in + iOS) + # Always apply the compliance patch on iOS; we can use the macOS patch + APP_STORE_COMPLIANCE_PATCH="iOS/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS= + AC_MSG_RESULT(["applying default app store compliance patch"]) + ;; + Darwin) + # Always *check* the compliance patch on macOS + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_FLAGS="--dry-run" + AC_MSG_RESULT(["checking (not applying) default app store compliance patch"]) + ;; + *) + # No app compliance patching on any other platform + APP_STORE_COMPLIANCE_PATCH= + APP_STORE_COMPLIANCE_PATCH_TARGET= + APP_STORE_COMPLIANCE_PATCH_FLAGS= + AC_MSG_RESULT(["not patching for app store compliance"]) + ;; + esac +]) +AC_SUBST([APP_STORE_COMPLIANCE_PATCH]) +AC_SUBST([APP_STORE_COMPLIANCE_PATCH_TARGET]) +AC_SUBST([APP_STORE_COMPLIANCE_PATCH_FLAGS]) + AC_SUBST([_PYTHON_HOST_PLATFORM]) if test "$cross_compiling" = yes; then case "$host" in From ae53183d377a65bbfecf9e264a2ac4abc911f874 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 25 Jun 2024 15:29:35 +0800 Subject: [PATCH 02/11] Added blurb. --- .../next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst diff --git a/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst b/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst new file mode 100644 index 00000000000000..b885de85960ba6 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst @@ -0,0 +1,2 @@ +Added a ``--with-app-store-compliance`` option to patch out known issues +with macOS/iOS App Store review processes. From eee0c930e2e901e67ee4204d14a41abe5f963fd0 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 25 Jun 2024 15:43:03 +0800 Subject: [PATCH 03/11] Correct tab-vs-spaces formatting issue. --- configure | 13 ++++--------- configure.ac | 13 ++++--------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/configure b/configure index 7f3abc1e0875f7..d03e15619dbe3a 100755 --- a/configure +++ b/configure @@ -4445,15 +4445,10 @@ printf %s "checking for --with-app-store-compliance... " >&6; } if test ${with_app_store_compliance+y} then : withval=$with_app_store_compliance; - case "$withval" in - yes) + case "$withval" in + yes) case $ac_sys_system in - Darwin) - APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" - APP_STORE_COMPLIANCE_PATCH_FLAGS= - ;; - iOS) + Darwin|iOS) # iOS is able to share the macOS patch APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" @@ -4478,7 +4473,7 @@ else $as_nop case $ac_sys_system in iOS) # Always apply the compliance patch on iOS; we can use the macOS patch - APP_STORE_COMPLIANCE_PATCH="iOS/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" APP_STORE_COMPLIANCE_PATCH_FLAGS= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying default app store compliance patch\"" >&5 diff --git a/configure.ac b/configure.ac index 7b14e2c54d3b41..ada6be50bd3630 100644 --- a/configure.ac +++ b/configure.ac @@ -704,15 +704,10 @@ AC_ARG_WITH( [Enable any patches required for compiliance with app stores. Optional PATCH-FILE specifies the custom patch to apply.] )],[ - case "$withval" in - yes) + case "$withval" in + yes) case $ac_sys_system in - Darwin) - APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" - APP_STORE_COMPLIANCE_PATCH_FLAGS= - ;; - iOS) + Darwin|iOS) # iOS is able to share the macOS patch APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" @@ -733,7 +728,7 @@ AC_ARG_WITH( case $ac_sys_system in iOS) # Always apply the compliance patch on iOS; we can use the macOS patch - APP_STORE_COMPLIANCE_PATCH="iOS/Resources/app-store-compliance.patch" + APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" APP_STORE_COMPLIANCE_PATCH_FLAGS= AC_MSG_RESULT(["applying default app store compliance patch"]) From eeb976f9b17b598b0d6916bf017172c482b2209b Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 25 Jun 2024 16:18:37 +0800 Subject: [PATCH 04/11] Correct source file name in docs. Co-authored-by: Nice Zombies --- Doc/using/ios.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst index 4eb93d33045625..ce91d9714bbf0c 100644 --- a/Doc/using/ios.rst +++ b/Doc/using/ios.rst @@ -327,6 +327,6 @@ review rules cannot be challenged; so, it is necessary to modify the Python standard library for an app to pass App Store review. The Python source tree contains -:source:`a patch file ` that will remove +:source:`a patch file ` that will remove all code that is known to cause issues with the App Store review process. This patch is applied automatically when building for iOS. From 26cd9aea091c5759f48a37bf0e9d7fd2c72aa7cd Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 25 Jun 2024 16:27:24 +0800 Subject: [PATCH 05/11] Correct source code reference in Mac docs Co-authored-by: Nice Zombies --- Doc/using/mac.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index a3e4a25d0a6915..4da3f5fd982955 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -201,7 +201,7 @@ review rules cannot be challenged. Therefore, it is necessary to modify the Python standard library for an app to pass App Store review. The Python source tree contains -:source:`a patch file ` that will remove +:source:`a patch file ` that will remove all code that is known to cause issues with the App Store review process. This patch is applied automatically when Python is configured with the ``--with-app-store-compliance`` option. From 2d5a0a7c7c536fc1e8e2023ac52a77bce6d016d0 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 25 Jun 2024 17:45:59 +0800 Subject: [PATCH 06/11] Only apply the patch forward, and ensure the working directory is correct. --- Makefile.pre.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index 1dff7b6e68ee5b..d0b128d2cdb4bb 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -935,7 +935,7 @@ $(BUILDPYTHON)-gdb.py: $(SRC_GDB_HOOKS) # known modifications to the source tree before building. .PHONY: app-store-compliance app-store-compliance: - patch -p1 @APP_STORE_COMPLIANCE_PATCH_FLAGS@ < $(srcdir)/$(APP_STORE_COMPLIANCE_PATCH) + patch @APP_STORE_COMPLIANCE_PATCH_FLAGS@ --forward --strip=1 --directory="$(srcdir)" --input "$(APP_STORE_COMPLIANCE_PATCH)" # This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary # minimal framework (not including the Lib directory and such) in the current From 12cb4693bb1dbe104cba439e279418971afd367b Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Wed, 26 Jun 2024 07:19:22 +0800 Subject: [PATCH 07/11] Make patching reslient to multiple builds. --- Makefile.pre.in | 16 ++++++++++++---- configure | 8 ++++---- configure.ac | 8 ++++---- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index d0b128d2cdb4bb..22e6d0e2abf9f3 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -932,10 +932,18 @@ $(BUILDPYTHON)-gdb.py: $(SRC_GDB_HOOKS) # Compliance with app stores (such as iOS and macOS) sometimes requires making # modifications to the Python standard library. If enabled, apply the patch of -# known modifications to the source tree before building. -.PHONY: app-store-compliance -app-store-compliance: - patch @APP_STORE_COMPLIANCE_PATCH_FLAGS@ --forward --strip=1 --directory="$(srcdir)" --input "$(APP_STORE_COMPLIANCE_PATCH)" +# known modifications to the source tree before building. The patch will be +# applied in a dry-run mode (validating, but not applying the patch) on builds +# that *have* a compliance patch, but where compliance has not been enabled. +build/app-store-compliant: + patch @APP_STORE_COMPLIANCE_PATCH_FLAGS@ --forward --strip=1 --directory="$(srcdir)" --input "$(APP_STORE_COMPLIANCE_PATCH)" ; \ + if test "@APP_STORE_COMPLIANCE_PATCH_FLAGS@" == ""; then \ + echo "Source tree has been patched for app store compliance."; \ + mkdir -p build ; \ + echo "$(APP_STORE_COMPLIANCE_PATCH)" > build/app-store-compliant ; \ + else \ + echo "App store compliance patch has been verified, but not applied."; \ + fi # This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary # minimal framework (not including the Lib directory and such) in the current diff --git a/configure b/configure index d03e15619dbe3a..e559155c765e94 100755 --- a/configure +++ b/configure @@ -4451,7 +4451,7 @@ then : Darwin|iOS) # iOS is able to share the macOS patch APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= ;; *) as_fn_error $? "No default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; @@ -4461,7 +4461,7 @@ printf "%s\n" "\"applying default app store compliance patch\"" >&6; } ;; *) APP_STORE_COMPLIANCE_PATCH="${withval}" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying custom app store compliance patch\"" >&5 printf "%s\n" "\"applying custom app store compliance patch\"" >&6; } @@ -4474,7 +4474,7 @@ else $as_nop iOS) # Always apply the compliance patch on iOS; we can use the macOS patch APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying default app store compliance patch\"" >&5 printf "%s\n" "\"applying default app store compliance patch\"" >&6; } @@ -4482,7 +4482,7 @@ printf "%s\n" "\"applying default app store compliance patch\"" >&6; } Darwin) # Always *check* the compliance patch on macOS APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS="--dry-run" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"checking (not applying) default app store compliance patch\"" >&5 printf "%s\n" "\"checking (not applying) default app store compliance patch\"" >&6; } diff --git a/configure.ac b/configure.ac index ada6be50bd3630..ccf5b17f6db88f 100644 --- a/configure.ac +++ b/configure.ac @@ -710,7 +710,7 @@ AC_ARG_WITH( Darwin|iOS) # iOS is able to share the macOS patch APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= ;; *) AC_MSG_ERROR([No default app store compliance patch available for $ac_sys_system]) ;; @@ -719,7 +719,7 @@ AC_ARG_WITH( ;; *) APP_STORE_COMPLIANCE_PATCH="${withval}" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= AC_MSG_RESULT(["applying custom app store compliance patch"]) ;; @@ -729,14 +729,14 @@ AC_ARG_WITH( iOS) # Always apply the compliance patch on iOS; we can use the macOS patch APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= AC_MSG_RESULT(["applying default app store compliance patch"]) ;; Darwin) # Always *check* the compliance patch on macOS APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - APP_STORE_COMPLIANCE_PATCH_TARGET="app-store-compliance" + APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS="--dry-run" AC_MSG_RESULT(["checking (not applying) default app store compliance patch"]) ;; From 56f748786daa0b99641ba20da221b5e3fd195992 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 27 Jun 2024 06:19:59 +0800 Subject: [PATCH 08/11] Documentation fixes found during review Co-authored-by: Alyssa Coghlan --- Doc/library/urllib.parse.rst | 4 ++-- Doc/using/configure.rst | 6 +++--- Doc/using/ios.rst | 2 +- Doc/using/mac.rst | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index 7f83a45e0a69cf..f383f801fd345d 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -27,12 +27,12 @@ Resource Locators. It supports the following URL schemes: ``file``, ``ftp``, ``sftp``, ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``, ``telnet``, ``wais``, ``ws``, ``wss``. -.. note:: +.. impl-detail:: The inclusion of the ``itms-services`` URL scheme can prevent an app from passing Apple's App Store review process for the macOS and iOS App Stores. Handling for the ``itms-services`` scheme is always removed on iOS; on - macOS, it *may* be removed if Python has been built with the + macOS, it *may* be removed if CPython has been built with the ``--with-app-store-compliance`` option. The :mod:`urllib.parse` module defines functions that fall into two broad diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 76174a233c368d..2a1f06e2d286ff 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -948,9 +948,9 @@ See :source:`Mac/README.rst`. .. option:: --with-app-store-compliance .. option:: --with-app-store-compliance=PATCH-FILE - The Python standard library contains strings that are known to cause - trigger automated inspection tools when submitted for distribution by - the macOS App Store. If enabled, this option will apply the list of + The Python standard library contains strings that are known to trigger + automated inspection tool errors when submitted for distribution by + the macOS and iOS App Stores. If enabled, this option will apply the list of patches that are known to correct app store compliance. A custom patch file can also be specified. This option is disabled by default. diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst index ce91d9714bbf0c..774856e8aec2ac 100644 --- a/Doc/using/ios.rst +++ b/Doc/using/ios.rst @@ -317,7 +317,7 @@ App Store Compliance ==================== The only mechanism for distributing apps to third-party iOS devices is to -submit the app to the iOS App Store; app submitted for distribution must pass +submit the app to the iOS App Store; apps submitted for distribution must pass Apple's app review process. This process includes a set of automated validation rules that inspect the submitted application bundle for problematic code. diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 4da3f5fd982955..115e70c86562cd 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -203,10 +203,10 @@ Python standard library for an app to pass App Store review. The Python source tree contains :source:`a patch file ` that will remove all code that is known to cause issues with the App Store review process. This -patch is applied automatically when Python is configured with the +patch is applied automatically when CPython is configured with the ``--with-app-store-compliance`` option. -This patch is not normally required to use Python on a Mac; nor is it required +This patch is not normally required to use CPython on a Mac; nor is it required if you are distributing an app *outside* the macOS App Store. It is *only* required if you are using the macOS App Store as a distribution channel. From a7a1275fa60ad0fb6468b650012571aa5a5486ab Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Fri, 28 Jun 2024 18:13:54 +0800 Subject: [PATCH 09/11] Documentation and configure.ac syntax improvements Co-authored-by: Erlend E. Aasland --- Doc/library/urllib.parse.rst | 2 +- Doc/using/mac.rst | 2 +- .../2024-06-25-15-29-27.gh-issue-120522.5_n515.rst | 2 +- configure.ac | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index f383f801fd345d..fb5353e1895bf9 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -33,7 +33,7 @@ Resource Locators. It supports the following URL schemes: ``file``, ``ftp``, passing Apple's App Store review process for the macOS and iOS App Stores. Handling for the ``itms-services`` scheme is always removed on iOS; on macOS, it *may* be removed if CPython has been built with the - ``--with-app-store-compliance`` option. + :option:`--with-app-store-compliance` option. The :mod:`urllib.parse` module defines functions that fall into two broad categories: URL parsing and URL quoting. These are covered in detail in diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 115e70c86562cd..44fb00de3733c5 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -204,7 +204,7 @@ The Python source tree contains :source:`a patch file ` that will remove all code that is known to cause issues with the App Store review process. This patch is applied automatically when CPython is configured with the -``--with-app-store-compliance`` option. +:option:`--with-app-store-compliance` option. This patch is not normally required to use CPython on a Mac; nor is it required if you are distributing an app *outside* the macOS App Store. It is *only* diff --git a/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst b/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst index b885de85960ba6..4a397a445ccc3b 100644 --- a/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst +++ b/Misc/NEWS.d/next/Build/2024-06-25-15-29-27.gh-issue-120522.5_n515.rst @@ -1,2 +1,2 @@ -Added a ``--with-app-store-compliance`` option to patch out known issues +Added a :option:`--with-app-store-compliance` option to patch out known issues with macOS/iOS App Store review processes. diff --git a/configure.ac b/configure.ac index 3def3cf3e7f9e8..67b168920a77b1 100644 --- a/configure.ac +++ b/configure.ac @@ -700,7 +700,7 @@ AC_MSG_CHECKING([for --with-app-store-compliance]) AC_ARG_WITH( [app_store_compliance], [AS_HELP_STRING( - [--with-app-store-compliance=@<:@=PATCH-FILE@:>@], + [--with-app-store-compliance=@<:@PATCH-FILE@:>@], [Enable any patches required for compiliance with app stores. Optional PATCH-FILE specifies the custom patch to apply.] )],[ @@ -713,15 +713,15 @@ AC_ARG_WITH( APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= ;; - *) AC_MSG_ERROR([No default app store compliance patch available for $ac_sys_system]) ;; + *) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;; esac - AC_MSG_RESULT(["applying default app store compliance patch"]) + AC_MSG_RESULT([applying default app store compliance patch]) ;; *) APP_STORE_COMPLIANCE_PATCH="${withval}" APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= - AC_MSG_RESULT(["applying custom app store compliance patch"]) + AC_MSG_RESULT([applying custom app store compliance patch]) ;; esac ],[ @@ -731,21 +731,21 @@ AC_ARG_WITH( APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= - AC_MSG_RESULT(["applying default app store compliance patch"]) + AC_MSG_RESULT([applying default app store compliance patch]) ;; Darwin) # Always *check* the compliance patch on macOS APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS="--dry-run" - AC_MSG_RESULT(["checking (not applying) default app store compliance patch"]) + AC_MSG_RESULT([checking (not applying) default app store compliance patch]) ;; *) # No app compliance patching on any other platform APP_STORE_COMPLIANCE_PATCH= APP_STORE_COMPLIANCE_PATCH_TARGET= APP_STORE_COMPLIANCE_PATCH_FLAGS= - AC_MSG_RESULT(["not patching for app store compliance"]) + AC_MSG_RESULT([not patching for app store compliance]) ;; esac ]) From 702466c337f3adb4a704df05928fc041aeb8f6aa Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 29 Jun 2024 14:43:01 +0800 Subject: [PATCH 10/11] Regenerate configure script. --- configure | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 4d59df9ea0ac99..826462ecc201be 100755 --- a/configure +++ b/configure @@ -1859,7 +1859,7 @@ Optional Packages: specify the name for the python framework on macOS only valid when --enable-framework is set. see Mac/README.rst (default is 'Python') - --with-app-store-compliance=[=PATCH-FILE] + --with-app-store-compliance=[PATCH-FILE] Enable any patches required for compiliance with app stores. Optional PATCH-FILE specifies the custom patch to apply. @@ -4454,17 +4454,17 @@ then : APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= ;; - *) as_fn_error $? "No default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; + *) as_fn_error $? "no default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; esac - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying default app store compliance patch\"" >&5 -printf "%s\n" "\"applying default app store compliance patch\"" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 +printf "%s\n" "applying default app store compliance patch" >&6; } ;; *) APP_STORE_COMPLIANCE_PATCH="${withval}" APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying custom app store compliance patch\"" >&5 -printf "%s\n" "\"applying custom app store compliance patch\"" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: applying custom app store compliance patch" >&5 +printf "%s\n" "applying custom app store compliance patch" >&6; } ;; esac @@ -4476,24 +4476,24 @@ else $as_nop APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS= - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"applying default app store compliance patch\"" >&5 -printf "%s\n" "\"applying default app store compliance patch\"" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 +printf "%s\n" "applying default app store compliance patch" >&6; } ;; Darwin) # Always *check* the compliance patch on macOS APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" APP_STORE_COMPLIANCE_PATCH_TARGET="build/app-store-compliant" APP_STORE_COMPLIANCE_PATCH_FLAGS="--dry-run" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"checking (not applying) default app store compliance patch\"" >&5 -printf "%s\n" "\"checking (not applying) default app store compliance patch\"" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: checking (not applying) default app store compliance patch" >&5 +printf "%s\n" "checking (not applying) default app store compliance patch" >&6; } ;; *) # No app compliance patching on any other platform APP_STORE_COMPLIANCE_PATCH= APP_STORE_COMPLIANCE_PATCH_TARGET= APP_STORE_COMPLIANCE_PATCH_FLAGS= - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"not patching for app store compliance\"" >&5 -printf "%s\n" "\"not patching for app store compliance\"" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not patching for app store compliance" >&5 +printf "%s\n" "not patching for app store compliance" >&6; } ;; esac From 87a8e72e4acd2d53f75bf4e80e13d796c2daac48 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 29 Jun 2024 14:55:32 +0800 Subject: [PATCH 11/11] Silence the patch echo output. --- Makefile.pre.in | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index 7061c40866f9fb..5f45f66fdfdbdb 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -936,13 +936,10 @@ $(BUILDPYTHON)-gdb.py: $(SRC_GDB_HOOKS) # applied in a dry-run mode (validating, but not applying the patch) on builds # that *have* a compliance patch, but where compliance has not been enabled. build/app-store-compliant: - patch @APP_STORE_COMPLIANCE_PATCH_FLAGS@ --forward --strip=1 --directory="$(srcdir)" --input "$(APP_STORE_COMPLIANCE_PATCH)" ; \ - if test "@APP_STORE_COMPLIANCE_PATCH_FLAGS@" == ""; then \ - echo "Source tree has been patched for app store compliance."; \ + patch @APP_STORE_COMPLIANCE_PATCH_FLAGS@ --forward --strip=1 --directory="$(srcdir)" --input "$(APP_STORE_COMPLIANCE_PATCH)" + @if test "@APP_STORE_COMPLIANCE_PATCH_FLAGS@" == ""; then \ mkdir -p build ; \ echo "$(APP_STORE_COMPLIANCE_PATCH)" > build/app-store-compliant ; \ - else \ - echo "App store compliance patch has been verified, but not applied."; \ fi # This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary