mirror of https://github.com/python/cpython
gh-120522: Apply App Store compliance patch during installation (#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.
This commit is contained in:
parent
5901d92739
commit
728432c804
|
@ -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
|
The module has been designed to match the internet RFC on Relative Uniform
|
||||||
Resource Locators. It supports the following URL schemes: ``file``, ``ftp``,
|
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``,
|
``news``, ``nntp``, ``prospero``, ``rsync``, ``rtsp``, ``rtsps``, ``rtspu``,
|
||||||
``sftp``, ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``,
|
``sftp``, ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``,
|
||||||
``telnet``, ``wais``, ``ws``, ``wss``.
|
``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
|
The :mod:`urllib.parse` module defines functions that fall into two broad
|
||||||
categories: URL parsing and URL quoting. These are covered in detail in
|
categories: URL parsing and URL quoting. These are covered in detail in
|
||||||
the following sections.
|
the following sections.
|
||||||
|
|
|
@ -945,6 +945,17 @@ See :source:`Mac/README.rst`.
|
||||||
Specify the name for the python framework on macOS only valid when
|
Specify the name for the python framework on macOS only valid when
|
||||||
:option:`--enable-framework` is set (default: ``Python``).
|
: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
|
iOS Options
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -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
|
* 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.
|
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.
|
||||||
|
|
|
@ -188,6 +188,28 @@ distributable application:
|
||||||
* `PyInstaller <https://pyinstaller.org/>`__: A cross-platform packaging tool that creates
|
* `PyInstaller <https://pyinstaller.org/>`__: A cross-platform packaging tool that creates
|
||||||
a single file or folder as a distributable artifact.
|
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
|
Other Resources
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|
|
@ -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',
|
|
@ -179,6 +179,9 @@ EXPORTSFROM= @EXPORTSFROM@
|
||||||
EXE= @EXEEXT@
|
EXE= @EXEEXT@
|
||||||
BUILDEXE= @BUILDEXEEXT@
|
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
|
# Short name and location for Mac OS X Python framework
|
||||||
UNIVERSALSDK=@UNIVERSALSDK@
|
UNIVERSALSDK=@UNIVERSALSDK@
|
||||||
PYTHONFRAMEWORK= @PYTHONFRAMEWORK@
|
PYTHONFRAMEWORK= @PYTHONFRAMEWORK@
|
||||||
|
@ -692,7 +695,7 @@ list-targets:
|
||||||
@grep -E '^[A-Za-z][-A-Za-z0-9]+:' Makefile | awk -F : '{print $$1}'
|
@grep -E '^[A-Za-z][-A-Za-z0-9]+:' Makefile | awk -F : '{print $$1}'
|
||||||
|
|
||||||
.PHONY: build_all
|
.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
|
gdbhooks Programs/_testembed scripts checksharedmods rundsymutil
|
||||||
|
|
||||||
.PHONY: build_wasm
|
.PHONY: build_wasm
|
||||||
|
@ -715,6 +718,16 @@ check-clean-src:
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
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 generation build must start from a clean tree.
|
||||||
profile-clean-stamp:
|
profile-clean-stamp:
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
|
@ -2570,6 +2583,14 @@ libinstall: all $(srcdir)/Modules/xxmodule.c
|
||||||
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py \
|
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py \
|
||||||
$(DESTDIR)$(LIBDEST); \
|
$(DESTDIR)$(LIBDEST); \
|
||||||
$(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
|
$(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)
|
@ # Build PYC files for the 3 optimization levels (0, 1, 2)
|
||||||
-PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
|
-PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
|
||||||
$(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \
|
$(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Added a :option:`--with-app-store-compliance` option to patch out known
|
||||||
|
issues with macOS/iOS App Store review processes.
|
|
@ -980,6 +980,7 @@ IPHONEOS_DEPLOYMENT_TARGET
|
||||||
EXPORT_MACOSX_DEPLOYMENT_TARGET
|
EXPORT_MACOSX_DEPLOYMENT_TARGET
|
||||||
CONFIGURE_MACOSX_DEPLOYMENT_TARGET
|
CONFIGURE_MACOSX_DEPLOYMENT_TARGET
|
||||||
_PYTHON_HOST_PLATFORM
|
_PYTHON_HOST_PLATFORM
|
||||||
|
APP_STORE_COMPLIANCE_PATCH
|
||||||
INSTALLTARGETS
|
INSTALLTARGETS
|
||||||
FRAMEWORKINSTALLAPPSPREFIX
|
FRAMEWORKINSTALLAPPSPREFIX
|
||||||
FRAMEWORKUNIXTOOLSPREFIX
|
FRAMEWORKUNIXTOOLSPREFIX
|
||||||
|
@ -1075,6 +1076,7 @@ enable_universalsdk
|
||||||
with_universal_archs
|
with_universal_archs
|
||||||
with_framework_name
|
with_framework_name
|
||||||
enable_framework
|
enable_framework
|
||||||
|
with_app_store_compliance
|
||||||
with_emscripten_target
|
with_emscripten_target
|
||||||
enable_wasm_dynamic_linking
|
enable_wasm_dynamic_linking
|
||||||
enable_wasm_pthreads
|
enable_wasm_pthreads
|
||||||
|
@ -1854,6 +1856,10 @@ Optional Packages:
|
||||||
specify the name for the python framework on macOS
|
specify the name for the python framework on macOS
|
||||||
only valid when --enable-framework is set. see
|
only valid when --enable-framework is set. see
|
||||||
Mac/README.rst (default is 'Python')
|
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]
|
--with-emscripten-target=[browser|node]
|
||||||
Emscripten platform
|
Emscripten platform
|
||||||
--with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty,
|
--with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty,
|
||||||
|
@ -4429,6 +4435,53 @@ fi
|
||||||
printf "%s\n" "#define _PYTHONFRAMEWORK \"${PYTHONFRAMEWORK}\"" >>confdefs.h
|
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
|
if test "$cross_compiling" = yes; then
|
||||||
case "$host" in
|
case "$host" in
|
||||||
|
|
41
configure.ac
41
configure.ac
|
@ -695,6 +695,47 @@ AC_SUBST([INSTALLTARGETS])
|
||||||
AC_DEFINE_UNQUOTED([_PYTHONFRAMEWORK], ["${PYTHONFRAMEWORK}"],
|
AC_DEFINE_UNQUOTED([_PYTHONFRAMEWORK], ["${PYTHONFRAMEWORK}"],
|
||||||
[framework name])
|
[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])
|
AC_SUBST([_PYTHON_HOST_PLATFORM])
|
||||||
if test "$cross_compiling" = yes; then
|
if test "$cross_compiling" = yes; then
|
||||||
case "$host" in
|
case "$host" in
|
||||||
|
|
Loading…
Reference in New Issue