https://github.com/python/cpython/commit/587a8f84ed568d496e9ceff45b02d28a52b6d137
commit: 587a8f84ed568d496e9ceff45b02d28a52b6d137
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: freakboy3742 <russ...@keith-magee.com>
date: 2024-07-22T08:13:34+08:00
summary:

[3.13] gh-120522: Apply App Store compliance patch during installation 
(GH-121947) (#122105)

gh-120522: Apply App Store compliance patch during installation (GH-121947)

Adds a --with-app-store-compliance configuration option that patches out code 
known to be an issue with App Store review processes. This option is applied 
automatically on iOS, and optionally on macOS.
(cherry picked from commit 728432c8043edc07bb8a24b180a70778fcd35878)

Co-authored-by: Russell Keith-Magee <russ...@keith-magee.com>

files:
A Mac/Resources/app-store-compliance.patch
A Misc/NEWS.d/next/Build/2024-07-18-07-53-07.gh-issue-120522.dg3o5A.rst
M Doc/library/urllib.parse.rst
M Doc/using/configure.rst
M Doc/using/ios.rst
M Doc/using/mac.rst
M Makefile.pre.in
M configure
M configure.ac

diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst
index 27909b763e9e43..fb5353e1895bf9 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``.
 
+.. 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 CPython has been built with the
+   :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
 the following sections.
diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst
index c765a29bf363cc..a69343d402eb8d 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 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.
+
+   .. versionadded:: 3.13
+
 iOS Options
 -----------
 
diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst
index 70a81fd8a53d29..5d0924be8d906d 100644
--- a/Doc/using/ios.rst
+++ b/Doc/using/ios.rst
@@ -323,3 +323,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; 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.
+
+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 <Mac/Resources/app-store-compliance.patch>` 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..44fb00de3733c5 100644
--- a/Doc/using/mac.rst
+++ b/Doc/using/mac.rst
@@ -188,6 +188,28 @@ distributable application:
 * `PyInstaller <https://pyinstaller.org/>`__: 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 <Mac/Resources/app-store-compliance.patch>` 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
+: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*
+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', 'g...@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 76653f399f411c..ab2a67040d1875 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -179,6 +179,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@
@@ -692,7 +695,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 check-app-store-compliance $(BUILDPYTHON) 
platform sharedmods \
                gdbhooks Programs/_testembed scripts checksharedmods rundsymutil
 
 .PHONY: build_wasm
@@ -715,6 +718,16 @@ check-clean-src:
                exit 1; \
        fi
 
+# Check that the app store compliance patch can be applied (if configured).
+# This is checked as a dry-run against the original library sources;
+# the patch will be actually applied during the install phase.
+.PHONY: check-app-store-compliance
+check-app-store-compliance:
+       @if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \
+               patch --dry-run --quiet --force --strip 1 --directory 
"$(abs_srcdir)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)"; \
+               echo "App store compliance patch can be applied."; \
+       fi
+
 # Profile generation build must start from a clean tree.
 profile-clean-stamp:
        $(MAKE) clean
@@ -2568,6 +2581,14 @@ libinstall:      all $(srcdir)/Modules/xxmodule.c
        $(INSTALL_DATA) `cat 
pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py \
                $(DESTDIR)$(LIBDEST); \
        $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
+       @ # If app store compliance has been configured, apply the patch to the
+       @ # installed library code. The patch has been previously validated 
against
+       @ # the original source tree, so we can ignore any errors that are 
raised
+       @ # due to files that are missing because of --disable-test-modules etc.
+       @if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \
+               echo "Applying app store compliance patch"; \
+               patch --force --reject-file 
"$(abs_builddir)/app-store-compliance.rej" --strip 2 --directory 
"$(DESTDIR)$(LIBDEST)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)" || 
true ; \
+       fi
        @ # Build PYC files for the 3 optimization levels (0, 1, 2)
        -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
                $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \
diff --git 
a/Misc/NEWS.d/next/Build/2024-07-18-07-53-07.gh-issue-120522.dg3o5A.rst 
b/Misc/NEWS.d/next/Build/2024-07-18-07-53-07.gh-issue-120522.dg3o5A.rst
new file mode 100644
index 00000000000000..e90c625a886b65
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2024-07-18-07-53-07.gh-issue-120522.dg3o5A.rst
@@ -0,0 +1,2 @@
+Added a :option:`--with-app-store-compliance` option to patch out known
+issues with macOS/iOS App Store review processes.
diff --git a/configure b/configure
index bff4f6ceb4ae3e..dcca9612f26a3d 100755
--- a/configure
+++ b/configure
@@ -982,6 +982,7 @@ IPHONEOS_DEPLOYMENT_TARGET
 EXPORT_MACOSX_DEPLOYMENT_TARGET
 CONFIGURE_MACOSX_DEPLOYMENT_TARGET
 _PYTHON_HOST_PLATFORM
+APP_STORE_COMPLIANCE_PATCH
 INSTALLTARGETS
 FRAMEWORKINSTALLAPPSPREFIX
 FRAMEWORKUNIXTOOLSPREFIX
@@ -1077,6 +1078,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
@@ -1856,6 +1858,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,
@@ -4431,6 +4437,53 @@ 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|iOS)
+          # iOS is able to share the macOS patch
+          APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
+          ;;
+        *) 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}"
+      { 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="Mac/Resources/app-store-compliance.patch"
+        { 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; }
+        ;;
+      *)
+        # No default app compliance patching on any other platform
+        APP_STORE_COMPLIANCE_PATCH=
+        { 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 65975732f72efc..1459a3ce62c787 100644
--- a/configure.ac
+++ b/configure.ac
@@ -695,6 +695,47 @@ 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|iOS)
+          # iOS is able to share the macOS patch
+          APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
+          ;;
+        *) 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}"
+      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="Mac/Resources/app-store-compliance.patch"
+        AC_MSG_RESULT([applying default app store compliance patch])
+        ;;
+      *)
+        # No default app compliance patching on any other platform
+        APP_STORE_COMPLIANCE_PATCH=
+        AC_MSG_RESULT([not patching for app store compliance])
+        ;;
+    esac
+])
+AC_SUBST([APP_STORE_COMPLIANCE_PATCH])
+
 AC_SUBST([_PYTHON_HOST_PLATFORM])
 if test "$cross_compiling" = yes; then
        case "$host" in

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to