Skip to content

Commit fba9635

Browse files
[3.12] 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 <[email protected]>
1 parent 08724bb commit fba9635

File tree

9 files changed

+207
-2
lines changed

9 files changed

+207
-2
lines changed

Doc/library/urllib.parse.rst

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,19 @@ to an absolute URL given a "base URL."
2222

2323
The module has been designed to match the internet RFC on Relative Uniform
2424
Resource Locators. It supports the following URL schemes: ``file``, ``ftp``,
25-
``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``mailto``, ``mms``,
25+
``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``itms-services``, ``mailto``, ``mms``,
2626
``news``, ``nntp``, ``prospero``, ``rsync``, ``rtsp``, ``rtsps``, ``rtspu``,
2727
``sftp``, ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``,
2828
``telnet``, ``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

+11
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,17 @@ See :source:`Mac/README.rst`.
673673
Specify the name for the python framework on macOS only valid when
674674
:option:`--enable-framework` is set (default: ``Python``).
675675

676+
.. option:: --with-app-store-compliance
677+
.. option:: --with-app-store-compliance=PATCH-FILE
678+
679+
The Python standard library contains strings that are known to trigger
680+
automated inspection tool errors when submitted for distribution by
681+
the macOS and iOS App Stores. If enabled, this option will apply the list of
682+
patches that are known to correct app store compliance. A custom patch
683+
file can also be specified. This option is disabled by default.
684+
685+
.. versionadded:: 3.13
686+
676687
iOS Options
677688
-----------
678689

Doc/using/ios.rst

+18
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,21 @@ modules in your app, some additional steps will be required:
323323

324324
* If you're using a separate folder for third-party packages, ensure that folder
325325
is included as part of the ``PYTHONPATH`` configuration in step 10.
326+
327+
App Store Compliance
328+
====================
329+
330+
The only mechanism for distributing apps to third-party iOS devices is to
331+
submit the app to the iOS App Store; apps submitted for distribution must pass
332+
Apple's app review process. This process includes a set of automated validation
333+
rules that inspect the submitted application bundle for problematic code.
334+
335+
The Python standard library contains some code that is known to violate these
336+
automated rules. While these violations appear to be false positives, Apple's
337+
review rules cannot be challenged; so, it is necessary to modify the Python
338+
standard library for an app to pass App Store review.
339+
340+
The Python source tree contains
341+
:source:`a patch file <Mac/Resources/app-store-compliance.patch>` that will remove
342+
all code that is known to cause issues with the App Store review process. This
343+
patch is applied automatically when building for iOS.

Doc/using/mac.rst

+22
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,28 @@ distributable application:
188188
* `PyInstaller <https://pyinstaller.org/>`__: A cross-platform packaging tool that creates
189189
a single file or folder as a distributable artifact.
190190

191+
App Store Compliance
192+
--------------------
193+
194+
Apps submitted for distribution through the macOS App Store must pass Apple's
195+
app review process. This process includes a set of automated validation rules
196+
that inspect the submitted application bundle for problematic code.
197+
198+
The Python standard library contains some code that is known to violate these
199+
automated rules. While these violations appear to be false positives, Apple's
200+
review rules cannot be challenged. Therefore, it is necessary to modify the
201+
Python standard library for an app to pass App Store review.
202+
203+
The Python source tree contains
204+
:source:`a patch file <Mac/Resources/app-store-compliance.patch>` that will remove
205+
all code that is known to cause issues with the App Store review process. This
206+
patch is applied automatically when CPython is configured with the
207+
:option:`--with-app-store-compliance` option.
208+
209+
This patch is not normally required to use CPython on a Mac; nor is it required
210+
if you are distributing an app *outside* the macOS App Store. It is *only*
211+
required if you are using the macOS App Store as a distribution channel.
212+
191213
Other Resources
192214
===============
193215

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
2+
index d6c83a75c1c..19ed4e01091 100644
3+
--- a/Lib/test/test_urlparse.py
4+
+++ b/Lib/test/test_urlparse.py
5+
@@ -237,11 +237,6 @@ def test_roundtrips(self):
6+
'','',''),
7+
('git+ssh', '[email protected]','/user/project.git',
8+
'', '')),
9+
- ('itms-services://?action=download-manifest&url=https://example.com/app',
10+
- ('itms-services', '', '', '',
11+
- 'action=download-manifest&url=https://example.com/app', ''),
12+
- ('itms-services', '', '',
13+
- 'action=download-manifest&url=https://example.com/app', '')),
14+
('+scheme:path/to/file',
15+
('', '', '+scheme:path/to/file', '', '', ''),
16+
('', '', '+scheme:path/to/file', '', '')),
17+
diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py
18+
index 8f724f907d4..148caf742c9 100644
19+
--- a/Lib/urllib/parse.py
20+
+++ b/Lib/urllib/parse.py
21+
@@ -59,7 +59,7 @@
22+
'imap', 'wais', 'file', 'mms', 'https', 'shttp',
23+
'snews', 'prospero', 'rtsp', 'rtsps', 'rtspu', 'rsync',
24+
'svn', 'svn+ssh', 'sftp', 'nfs', 'git', 'git+ssh',
25+
- 'ws', 'wss', 'itms-services']
26+
+ 'ws', 'wss']
27+
28+
uses_params = ['', 'ftp', 'hdl', 'prospero', 'http', 'imap',
29+
'https', 'shttp', 'rtsp', 'rtsps', 'rtspu', 'sip',

Makefile.pre.in

+22-1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ EXPORTSFROM= @EXPORTSFROM@
178178
EXE= @EXEEXT@
179179
BUILDEXE= @BUILDEXEEXT@
180180

181+
# Name of the patch file to apply for app store compliance
182+
APP_STORE_COMPLIANCE_PATCH=@APP_STORE_COMPLIANCE_PATCH@
183+
181184
# Short name and location for Mac OS X Python framework
182185
UNIVERSALSDK=@UNIVERSALSDK@
183186
PYTHONFRAMEWORK= @PYTHONFRAMEWORK@
@@ -622,7 +625,7 @@ all: @DEF_MAKE_ALL_RULE@
622625
.PHONY: all
623626

624627
.PHONY: build_all
625-
build_all: check-clean-src $(BUILDPYTHON) platform sharedmods \
628+
build_all: check-clean-src check-app-store-compliance $(BUILDPYTHON) platform sharedmods \
626629
gdbhooks Programs/_testembed scripts checksharedmods rundsymutil
627630

628631
.PHONY: build_wasm
@@ -645,6 +648,16 @@ check-clean-src:
645648
exit 1; \
646649
fi
647650

651+
# Check that the app store compliance patch can be applied (if configured).
652+
# This is checked as a dry-run against the original library sources;
653+
# the patch will be actually applied during the install phase.
654+
.PHONY: check-app-store-compliance
655+
check-app-store-compliance:
656+
@if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \
657+
patch --dry-run --quiet --force --strip 1 --directory "$(abs_srcdir)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)"; \
658+
echo "App store compliance patch can be applied."; \
659+
fi
660+
648661
# Profile generation build must start from a clean tree.
649662
profile-clean-stamp:
650663
$(MAKE) clean
@@ -2404,6 +2417,14 @@ libinstall: all $(srcdir)/Modules/xxmodule.c
24042417
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py \
24052418
$(DESTDIR)$(LIBDEST); \
24062419
$(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
2420+
@ # If app store compliance has been configured, apply the patch to the
2421+
@ # installed library code. The patch has been previously validated against
2422+
@ # the original source tree, so we can ignore any errors that are raised
2423+
@ # due to files that are missing because of --disable-test-modules etc.
2424+
@if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \
2425+
echo "Applying app store compliance patch"; \
2426+
patch --force --reject-file "$(abs_builddir)/app-store-compliance.rej" --strip 2 --directory "$(DESTDIR)$(LIBDEST)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)" || true ; \
2427+
fi
24072428
@ # Build PYC files for the 3 optimization levels (0, 1, 2)
24082429
-PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
24092430
$(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \
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

+53
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure.ac

+41
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,47 @@ AC_SUBST([INSTALLTARGETS])
694694
AC_DEFINE_UNQUOTED([_PYTHONFRAMEWORK], ["${PYTHONFRAMEWORK}"],
695695
[framework name])
696696

697+
dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output
698+
AC_MSG_CHECKING([for --with-app-store-compliance])
699+
AC_ARG_WITH(
700+
[app_store_compliance],
701+
[AS_HELP_STRING(
702+
[--with-app-store-compliance=@<:@PATCH-FILE@:>@],
703+
[Enable any patches required for compiliance with app stores.
704+
Optional PATCH-FILE specifies the custom patch to apply.]
705+
)],[
706+
case "$withval" in
707+
yes)
708+
case $ac_sys_system in
709+
Darwin|iOS)
710+
# iOS is able to share the macOS patch
711+
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
712+
;;
713+
*) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;;
714+
esac
715+
AC_MSG_RESULT([applying default app store compliance patch])
716+
;;
717+
*)
718+
APP_STORE_COMPLIANCE_PATCH="${withval}"
719+
AC_MSG_RESULT([applying custom app store compliance patch])
720+
;;
721+
esac
722+
],[
723+
case $ac_sys_system in
724+
iOS)
725+
# Always apply the compliance patch on iOS; we can use the macOS patch
726+
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
727+
AC_MSG_RESULT([applying default app store compliance patch])
728+
;;
729+
*)
730+
# No default app compliance patching on any other platform
731+
APP_STORE_COMPLIANCE_PATCH=
732+
AC_MSG_RESULT([not patching for app store compliance])
733+
;;
734+
esac
735+
])
736+
AC_SUBST([APP_STORE_COMPLIANCE_PATCH])
737+
697738
AC_SUBST([_PYTHON_HOST_PLATFORM])
698739
if test "$cross_compiling" = yes; then
699740
case "$host" in

0 commit comments

Comments
 (0)