From 3779f2b95ebf68e2d5f8ea27c7a7baa0879f5496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 28 Sep 2025 19:30:44 +0200 Subject: [PATCH 1/3] gh-139393: fix `_CALL_LEN` JIT tests for tuples (#139394) Fix a regression introduced in 7ce25edb8f41e527ed479bf61ef36dc9841b4ac5 where `_PY_NSMALLPOSINTS` was changed from 257 to 1025. --- Lib/test/test_capi/test_opt.py | 14 +++++++++++--- Modules/_testinternalcapi.c | 5 +++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index c3fed50cee9736..f121f27174875e 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -15,7 +15,7 @@ _testinternalcapi = import_helper.import_module("_testinternalcapi") -from _testinternalcapi import TIER2_THRESHOLD +from _testinternalcapi import _PY_NSMALLPOSINTS, TIER2_THRESHOLD #For test of issue 136154 GLOBAL_136154 = 42 @@ -2093,6 +2093,10 @@ def testfunc(n): self.assertNotIn("_GUARD_TOS_INT", uops) def test_call_len_known_length_small_int(self): + # Make sure that len(t) is optimized for a tuple of length 5. + # See https://github.com/python/cpython/issues/139393. + self.assertGreater(_PY_NSMALLPOSINTS, 5) + def testfunc(n): x = 0 for _ in range(n): @@ -2113,13 +2117,17 @@ def testfunc(n): self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_call_len_known_length(self): + # Make sure that len(t) is not optimized for a tuple of length 2048. + # See https://github.com/python/cpython/issues/139393. + self.assertLess(_PY_NSMALLPOSINTS, 2048) + def testfunc(n): class C: - t = tuple(range(300)) + t = tuple(range(2048)) x = 0 for _ in range(n): - if len(C.t) == 300: # comparison + guard removed + if len(C.t) == 2048: # comparison + guard removed x += 1 return x diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index d680711e5d828a..a4348e7e1497cd 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -34,6 +34,7 @@ #include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include "pycore_pylifecycle.h" // _PyInterpreterConfig_InitFromDict() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_runtime_structs.h" // _PY_NSMALLPOSINTS #include "pycore_unicodeobject.h" // _PyUnicode_TransformDecimalAndSpaceToASCII() #include "clinic/_testinternalcapi.c.h" @@ -2576,6 +2577,10 @@ module_exec(PyObject *module) return 1; } + if (PyModule_AddIntMacro(module, _PY_NSMALLPOSINTS) < 0) { + return 1; + } + return 0; } From 195d13c85e17ab5cf6ac2a6de098bbf514cae207 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 29 Sep 2025 05:50:46 +0800 Subject: [PATCH 2/3] gh-132006: Add support for handling XCPrivacy manifests (#139163) Adds a PrivacyInfo.xcprivacy file when packaging `_hashlib` and `_ssl` modules for iOS (based on the original OpenSSL sources); and adds handling to the build script to allow any app to add `xcprivacy` handling for a binary module. --- Apple/__main__.py | 20 ++++++++++++++++- .../testbed/Python.xcframework/build/utils.sh | 13 +++++++++++ Doc/using/ios.rst | 22 ++++++++++++++++++- ...-08-28-06-22-26.gh-issue-132006.eZQmc6.rst | 2 ++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst diff --git a/Apple/__main__.py b/Apple/__main__.py index fc19b31be97bb2..88b54e91ac84d6 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -316,7 +316,7 @@ def unpack_deps( for name_ver in [ "BZip2-1.0.8-2", "libFFI-3.4.7-2", - "OpenSSL-3.0.16-2", + "OpenSSL-3.0.17-1", "XZ-5.6.4-2", "mpdecimal-4.0.0-2", "zstd-1.5.7-1", @@ -577,6 +577,7 @@ def create_xcframework(platform: str) -> str: # Extract the package version from the merged framework version = package_version(package_path / "Python.xcframework") + version_tag = ".".join(version.split(".")[:2]) # On non-macOS platforms, each framework in XCframework only contains the # headers, libPython, plus an Info.plist. Other resources like the standard @@ -647,6 +648,23 @@ def create_xcframework(platform: str) -> str: slice_framework / f"Headers/pyconfig-{arch}.h", ) + # Apple identifies certain libraries as "security risks"; if you + # statically link those libraries into a Framework, you become + # responsible for providing a privacy manifest for that framework. + xcprivacy_file = { + "OpenSSL": subdir(host_triple) / "prefix/share/OpenSSL.xcprivacy" + } + print(f" - {multiarch} xcprivacy files") + for module, lib in [ + ("_hashlib", "OpenSSL"), + ("_ssl", "OpenSSL"), + ]: + shutil.copy( + xcprivacy_file[lib], + slice_path + / f"lib-{arch}/python{version_tag}/lib-dynload/{module}.xcprivacy", + ) + print(" - build tools") shutil.copytree( PYTHON_DIR / "Apple/testbed/Python.xcframework/build", diff --git a/Apple/testbed/Python.xcframework/build/utils.sh b/Apple/testbed/Python.xcframework/build/utils.sh index 9cfe74720f26d4..961c46d014b5f5 100755 --- a/Apple/testbed/Python.xcframework/build/utils.sh +++ b/Apple/testbed/Python.xcframework/build/utils.sh @@ -67,6 +67,9 @@ install_dylib () { # The name of the extension file EXT=$(basename "$FULL_EXT") + # The name and location of the module + MODULE_PATH=$(dirname "$FULL_EXT") + MODULE_NAME=$(echo $EXT | cut -d "." -f 1) # The location of the extension file, relative to the bundle RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} # The path to the extension file, relative to the install base @@ -94,6 +97,16 @@ install_dylib () { # Create a back reference to the .so file location in the framework echo "${RELATIVE_EXT%.so}.fwork" > "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin" + # If the framework provides an xcprivacy file, install it. + if [ -e "$MODULE_PATH/$MODULE_NAME.xcprivacy" ]; then + echo "Installing XCPrivacy file for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME" + XCPRIVACY_FILE="$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/PrivacyInfo.xcprivacy" + if [ -e "$XCPRIVACY_FILE" ]; then + rm -rf "$XCPRIVACY_FILE" + fi + mv "$MODULE_PATH/$MODULE_NAME.xcprivacy" "$XCPRIVACY_FILE" + fi + echo "Signing framework as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)..." /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" } diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst index c02dac444dd7cc..5e4033fb6cec7a 100644 --- a/Doc/using/ios.rst +++ b/Doc/using/ios.rst @@ -328,7 +328,12 @@ 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. +rules that inspect the submitted application bundle for problematic code. There +are some steps that must be taken to ensure that your app will be able to pass +these validation steps. + +Incompatible code in the standard library +----------------------------------------- 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 @@ -339,3 +344,18 @@ 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. + +Privacy manifests +----------------- + +In April 2025, Apple introduced a requirement for `certain third-party +libraries to provide a Privacy Manifest +`__. +As a result, if you have a binary module that uses one of the affected +libraries, you must provide an ``.xcprivacy`` file for that library. +OpenSSL is one library affected by this requirement, but there are others. + +If you produce a binary module named ``mymodule.so``, and use you the Xcode +build script described in step 7 above, you can place a ``mymodule.xcprivacy`` +file next to ``mymodule.so``, and the privacy manifest will be installed into +the required location when the binary module is converted into a framework. diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst b/Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst new file mode 100644 index 00000000000000..8e7910768648a0 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2025-08-28-06-22-26.gh-issue-132006.eZQmc6.rst @@ -0,0 +1,2 @@ +XCframeworks now include privacy manifests to satisfy Apple App Store +submission requirements. From d3e3b2b0ac23e30e3d246bd12432c37bccf66f5d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 28 Sep 2025 16:55:44 -0500 Subject: [PATCH 3/3] Edit outdated comment (#121152) A comment about a possible relaxation of how bytes URLs are treated in Python 3.3 is no longer relevant or useful. --- Lib/urllib/parse.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 67d9bbea0d3150..c7946d7625386d 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -97,11 +97,9 @@ def clear_cache(): _byte_quoter_factory.cache_clear() # Helpers for bytes handling -# For 3.2, we deliberately require applications that -# handle improperly quoted URLs to do their own -# decoding and encoding. If valid use cases are -# presented, we may relax this by using latin-1 -# decoding internally for 3.3 +# We deliberately require applications that +# handle improperly quoted URLs to do their +# own decoding and encoding. _implicit_encoding = 'ascii' _implicit_errors = 'strict'