Skip to content

Commit 23b1fd3

Browse files
[3.10] pythongh-120522: Apply App Store compliance patch during installation (pythonGH-121947) (python#122105)
pythongh-120522: Apply App Store compliance patch during installation (pythonGH-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 728432c) Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
1 parent 6b7958f commit 23b1fd3

8 files changed

Lines changed: 222 additions & 6 deletions

File tree

Doc/library/urllib.parse.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ Resource Locators. It supports the following URL schemes: ``file``, ``ftp``,
2727
``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``, ``telnet``,
2828
``wais``, ``ws``, ``wss``.
2929

30+
.. impl-detail::
31+
32+
The inclusion of the ``itms-services`` URL scheme can prevent an app from
33+
passing Apple's App Store review process for the macOS and iOS App Stores.
34+
Handling for the ``itms-services`` scheme is always removed on iOS; on
35+
macOS, it *may* be removed if CPython has been built with the
36+
:option:`--with-app-store-compliance` option.
37+
3038
The :mod:`urllib.parse` module defines functions that fall into two broad
3139
categories: URL parsing and URL quoting. These are covered in detail in
3240
the following sections.

Doc/using/configure.rst

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,75 @@ See ``Mac/README.rst``.
506506
Specify the name for the python framework on macOS only valid when
507507
:option:`--enable-framework` is set (default: ``Python``).
508508

509+
.. option:: --with-app-store-compliance
510+
.. option:: --with-app-store-compliance=PATCH-FILE
511+
512+
The Python standard library contains strings that are known to trigger
513+
automated inspection tool errors when submitted for distribution by
514+
the macOS and iOS App Stores. If enabled, this option will apply the list of
515+
patches that are known to correct app store compliance. A custom patch
516+
file can also be specified. This option is disabled by default.
517+
518+
.. versionadded:: 3.13
519+
520+
iOS Options
521+
-----------
522+
523+
See :source:`iOS/README.rst`.
524+
525+
.. option:: --enable-framework=INSTALLDIR
526+
527+
Create a Python.framework. Unlike macOS, the *INSTALLDIR* argument
528+
specifying the installation path is mandatory.
529+
530+
.. option:: --with-framework-name=FRAMEWORK
531+
532+
Specify the name for the framework (default: ``Python``).
533+
534+
535+
Cross Compiling Options
536+
-----------------------
537+
538+
Cross compiling, also known as cross building, can be used to build Python
539+
for another CPU architecture or platform. Cross compiling requires a Python
540+
interpreter for the build platform. The version of the build Python must match
541+
the version of the cross compiled host Python.
542+
543+
.. option:: --build=BUILD
544+
545+
configure for building on BUILD, usually guessed by :program:`config.guess`.
546+
547+
.. option:: --host=HOST
548+
549+
cross-compile to build programs to run on HOST (target platform)
550+
551+
.. option:: --with-build-python=path/to/python
552+
553+
path to build ``python`` binary for cross compiling
554+
555+
.. versionadded:: 3.11
556+
557+
.. option:: CONFIG_SITE=file
558+
559+
An environment variable that points to a file with configure overrides.
560+
561+
Example *config.site* file:
562+
563+
.. code-block:: ini
564+
565+
# config.site-aarch64
566+
ac_cv_buggy_getaddrinfo=no
567+
ac_cv_file__dev_ptmx=yes
568+
ac_cv_file__dev_ptc=no
569+
570+
571+
Cross compiling example::
572+
573+
CONFIG_SITE=config.site-aarch64 ../configure \
574+
--build=x86_64-pc-linux-gnu \
575+
--host=aarch64-unknown-linux-gnu \
576+
--with-build-python=../x86_64/python
577+
509578

510579
Python Build System
511580
===================

Doc/using/mac.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,28 @@ The standard tool for deploying standalone Python applications on the Mac is
164164
at https://pypi.org/project/py2app/.
165165

166166

167+
App Store Compliance
168+
--------------------
169+
170+
Apps submitted for distribution through the macOS App Store must pass Apple's
171+
app review process. This process includes a set of automated validation rules
172+
that inspect the submitted application bundle for problematic code.
173+
174+
The Python standard library contains some code that is known to violate these
175+
automated rules. While these violations appear to be false positives, Apple's
176+
review rules cannot be challenged. Therefore, it is necessary to modify the
177+
Python standard library for an app to pass App Store review.
178+
179+
The Python source tree contains
180+
:source:`a patch file <Mac/Resources/app-store-compliance.patch>` that will remove
181+
all code that is known to cause issues with the App Store review process. This
182+
patch is applied automatically when CPython is configured with the
183+
:option:`--with-app-store-compliance` option.
184+
185+
This patch is not normally required to use CPython on a Mac; nor is it required
186+
if you are distributing an app *outside* the macOS App Store. It is *only*
187+
required if you are using the macOS App Store as a distribution channel.
188+
167189
Other Resources
168190
===============
169191

Mac/Resources/app-store-compliance.patch

Whitespace-only changes.

Makefile.pre.in

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ EXPORTSFROM= @EXPORTSFROM@
170170
EXE= @EXEEXT@
171171
BUILDEXE= @BUILDEXEEXT@
172172

173+
# Name of the patch file to apply for app store compliance
174+
APP_STORE_COMPLIANCE_PATCH=@APP_STORE_COMPLIANCE_PATCH@
175+
173176
# Short name and location for Mac OS X Python framework
174177
UNIVERSALSDK=@UNIVERSALSDK@
175178
PYTHONFRAMEWORK= @PYTHONFRAMEWORK@
@@ -481,7 +484,7 @@ DTRACE_DEPS = \
481484

482485
# Default target
483486
all: @DEF_MAKE_ALL_RULE@
484-
build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \
487+
build_all: check-clean-src check-app-store-compliance $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \
485488
Programs/_testembed python-config
486489

487490
# Check that the source is clean when building out of source.
@@ -493,6 +496,16 @@ check-clean-src:
493496
exit 1; \
494497
fi
495498

499+
# Check that the app store compliance patch can be applied (if configured).
500+
# This is checked as a dry-run against the original library sources;
501+
# the patch will be actually applied during the install phase.
502+
.PHONY: check-app-store-compliance
503+
check-app-store-compliance:
504+
@if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \
505+
patch --dry-run --quiet --force --strip 1 --directory "$(abs_srcdir)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)"; \
506+
echo "App store compliance patch can be applied."; \
507+
fi
508+
496509
# Profile generation build must start from a clean tree.
497510
profile-clean-stamp:
498511
$(MAKE) clean
@@ -1677,7 +1690,16 @@ libinstall: build_all $(srcdir)/Modules/xxmodule.c
16771690
$(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \
16781691
$(DESTDIR)$(LIBDEST)/distutils/tests ; \
16791692
fi
1680-
-PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
1693+
@ # If app store compliance has been configured, apply the patch to the
1694+
@ # installed library code. The patch has been previously validated against
1695+
@ # the original source tree, so we can ignore any errors that are raised
1696+
@ # due to files that are missing because of --disable-test-modules etc.
1697+
@if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \
1698+
echo "Applying app store compliance patch"; \
1699+
patch --force --reject-file "$(abs_builddir)/app-store-compliance.rej" --strip 2 --directory "$(DESTDIR)$(LIBDEST)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)" || true ; \
1700+
fi
1701+
@ # Build PYC files for the 3 optimization levels (0, 1, 2)
1702+
-PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
16811703
$(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \
16821704
-j0 -d $(LIBDEST) -f \
16831705
-x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Added a :option:`--with-app-store-compliance` option to patch out known
2+
issues with macOS/iOS App Store review processes.

configure

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ IPHONEOS_DEPLOYMENT_TARGET
742742
EXPORT_MACOSX_DEPLOYMENT_TARGET
743743
CONFIGURE_MACOSX_DEPLOYMENT_TARGET
744744
_PYTHON_HOST_PLATFORM
745+
APP_STORE_COMPLIANCE_PATCH
745746
INSTALLTARGETS
746747
FRAMEWORKINSTALLAPPSPREFIX
747748
FRAMEWORKUNIXTOOLSPREFIX
@@ -825,6 +826,7 @@ enable_universalsdk
825826
with_universal_archs
826827
with_framework_name
827828
enable_framework
829+
with_app_store_compliance
828830
with_cxx_main
829831
with_suffix
830832
enable_shared
@@ -1536,6 +1538,10 @@ Optional Packages:
15361538
specify the name for the python framework on macOS
15371539
only valid when --enable-framework is set. see
15381540
Mac/README.rst (default is 'Python')
1541+
--with-app-store-compliance=[PATCH-FILE]
1542+
Enable any patches required for compiliance with app
1543+
stores. Optional PATCH-FILE specifies the custom
1544+
patch to apply.
15391545
--with-cxx-main[=COMPILER]
15401546
compile main() and link Python executable with C++
15411547
compiler specified in COMPILER (default is $CXX)
@@ -3485,6 +3491,52 @@ cat >>confdefs.h <<_ACEOF
34853491
_ACEOF
34863492

34873493

3494+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-app-store-compliance" >&5
3495+
$as_echo_n "checking for --with-app-store-compliance... " >&6; }
3496+
3497+
# Check whether --with-app_store_compliance was given.
3498+
if test "${with_app_store_compliance+set}" = set; then :
3499+
withval=$with_app_store_compliance;
3500+
case "$withval" in
3501+
yes)
3502+
case $ac_sys_system in
3503+
Darwin|iOS)
3504+
# iOS is able to share the macOS patch
3505+
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
3506+
;;
3507+
*) as_fn_error $? "no default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;;
3508+
esac
3509+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5
3510+
$as_echo "applying default app store compliance patch" >&6; }
3511+
;;
3512+
*)
3513+
APP_STORE_COMPLIANCE_PATCH="${withval}"
3514+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: applying custom app store compliance patch" >&5
3515+
$as_echo "applying custom app store compliance patch" >&6; }
3516+
;;
3517+
esac
3518+
3519+
else
3520+
3521+
case $ac_sys_system in
3522+
iOS)
3523+
# Always apply the compliance patch on iOS; we can use the macOS patch
3524+
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
3525+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5
3526+
$as_echo "applying default app store compliance patch" >&6; }
3527+
;;
3528+
*)
3529+
# No default app compliance patching on any other platform
3530+
APP_STORE_COMPLIANCE_PATCH=
3531+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not patching for app store compliance" >&5
3532+
$as_echo "not patching for app store compliance" >&6; }
3533+
;;
3534+
esac
3535+
3536+
fi
3537+
3538+
3539+
34883540

34893541

34903542
# Set name for machine-dependent library files
@@ -3580,12 +3632,12 @@ if test "$cross_compiling" = yes; then
35803632
_host_device=${_host_device:=os}
35813633

35823634
# IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version
3583-
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking iOS deployment target" >&5
3584-
printf %s "checking iOS deployment target... " >&6; }
3635+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking iOS deployment target" >&5
3636+
$as_echo_n "checking iOS deployment target... " >&6; }
35853637
IPHONEOS_DEPLOYMENT_TARGET=${_host_os:3}
35863638
IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=13.0}
3587-
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $IPHONEOS_DEPLOYMENT_TARGET" >&5
3588-
printf "%s\n" "$IPHONEOS_DEPLOYMENT_TARGET" >&6; }
3639+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $IPHONEOS_DEPLOYMENT_TARGET" >&5
3640+
$as_echo "$IPHONEOS_DEPLOYMENT_TARGET" >&6; }
35893641

35903642
case "$host_cpu" in
35913643
aarch64)

configure.ac

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,47 @@ AC_SUBST([INSTALLTARGETS])
541541

542542
AC_DEFINE_UNQUOTED(_PYTHONFRAMEWORK, "${PYTHONFRAMEWORK}", [framework name])
543543

544+
dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output
545+
AC_MSG_CHECKING([for --with-app-store-compliance])
546+
AC_ARG_WITH(
547+
[app_store_compliance],
548+
[AS_HELP_STRING(
549+
[--with-app-store-compliance=@<:@PATCH-FILE@:>@],
550+
[Enable any patches required for compiliance with app stores.
551+
Optional PATCH-FILE specifies the custom patch to apply.]
552+
)],[
553+
case "$withval" in
554+
yes)
555+
case $ac_sys_system in
556+
Darwin|iOS)
557+
# iOS is able to share the macOS patch
558+
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
559+
;;
560+
*) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;;
561+
esac
562+
AC_MSG_RESULT([applying default app store compliance patch])
563+
;;
564+
*)
565+
APP_STORE_COMPLIANCE_PATCH="${withval}"
566+
AC_MSG_RESULT([applying custom app store compliance patch])
567+
;;
568+
esac
569+
],[
570+
case $ac_sys_system in
571+
iOS)
572+
# Always apply the compliance patch on iOS; we can use the macOS patch
573+
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
574+
AC_MSG_RESULT([applying default app store compliance patch])
575+
;;
576+
*)
577+
# No default app compliance patching on any other platform
578+
APP_STORE_COMPLIANCE_PATCH=
579+
AC_MSG_RESULT([not patching for app store compliance])
580+
;;
581+
esac
582+
])
583+
AC_SUBST([APP_STORE_COMPLIANCE_PATCH])
584+
544585
AC_SUBST([_PYTHON_HOST_PLATFORM])
545586

546587
# Set name for machine-dependent library files

0 commit comments

Comments
 (0)