Skip to content

bump(main/python): 3.13#27739

Merged
thunder-coding merged 113 commits intomasterfrom
python313
Mar 3, 2026
Merged

bump(main/python): 3.13#27739
thunder-coding merged 113 commits intomasterfrom
python313

Conversation

@thunder-coding
Copy link
Member

@thunder-coding thunder-coding commented Dec 25, 2025

Mostly ready for review, waiting for CI to turn green and some testing to ensure nothing is broken. Every change is in python-fullrebuild branch, so it is recommend to review that branch. Branch python313 as well as python313-dep{1,2,...} branches are derived from the python-fullrebuild branch. The list of packages that needed to be rebuilt was generated using apt-file search lib/python3.12. Those packages were than later replaced with their parent package names (in case of subpackages), and then some scripts were used to intelligently sort the packages into buckets for rebuild. The list of packages was then saved to output/rebuildlist.txt

Script used to generate rebuild list. This script was specifically designed to take into account large packages that needed more disk space for rebuild as well as packages that depended on python and also were dependencies of other python packages:

#!/usr/bin/bash
set -eou pipefail

rm -f output/rebuildlist-*.txt

declare -a packages=()
while IFS= read -r package; do
	packages+=("$package")
done < output/rebuildlist.txt

orig_packages=("${packages[@]}")
orig_grep_str=""
for pkg in "${orig_packages[@]}"; do
	orig_grep_str+="|$pkg"
done
orig_grep_str="${orig_grep_str:1}"

current_index=1

_generate_rebuild_list() {
	declare -a new_packages=()
	declare -a curr_packages=()
	local grep_str=""
	local -a args=("$@")
	for ((i = 0; i < $#; i++)); do
		pkg="${args[$i]}"
		grep_str+="|$pkg"
	done
	grep_str="${grep_str:1}"
	# echo "DEBUG: Grep string is ($grep_str)"
	for package in "${packages[@]}"; do
		local extra_dirs=()
		if [[ ! -f "packages/$package/build.sh" ]]; then
			extra_dirs+=("packages")
		elif [[ ! -f "x11-packages/$package/build.sh" ]]; then
			extra_dirs+=("x11-packages")
		elif [[ ! -f "root-packages/$package/build.sh" ]]; then
			extra_dirs+=("root-packages")
		fi
		for pkg in "$@"; do
			if [[ "$pkg" == "$package" ]]; then
				curr_packages+=("$package")
				continue 2
			fi
		done
		if ./scripts/buildorder.py ./*packages/"$package" "${extra_dirs[@]}" | grep -qE "($grep_str)$"; then
			curr_packages+=("$package")
			continue
		fi
		new_packages+=("$package")
	done

	local rebuild_list=()
	for pkg in "${curr_packages[@]}"; do
		local extra_dirs=()
		if [[ ! -f "packages/$pkg/build.sh" ]]; then
			extra_dirs+=("packages")
		elif [[ ! -f "x11-packages/$pkg/build.sh" ]]; then
			extra_dirs+=("x11-packages")
		elif [[ ! -f "root-packages/$pkg/build.sh" ]]; then
			extra_dirs+=("root-packages")
		fi
		for rebuild_pkg in $(./scripts/buildorder.py ./*packages/"$pkg" "${extra_dirs[@]}" | grep -oE "($orig_grep_str)$"); do
			rebuild_list+=("$rebuild_pkg")
		done
		rebuild_list+=("$pkg")
	done
	# Remove duplicates from rebuild_list
	rebuild_list=($(echo "${rebuild_list[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))

	echo "DEBUG: Dealt with $(( ${#packages[@]} - ${#new_packages[@]} )) packages, ${#new_packages[@]} remain. This step 

Script to generate python313-dep* branches:

#!/usr/bin/bash
set -eou pipefail

rm -f output/rebuildlist-*.txt

declare -a packages=()
while IFS= read -r package; do
	packages+=("$package")
done < output/rebuildlist.txt

orig_packages=("${packages[@]}")
orig_grep_str=""
for pkg in "${orig_packages[@]}"; do
	orig_grep_str+="|$pkg"
done
orig_grep_str="${orig_grep_str:1}"

current_index=1

_generate_rebuild_list() {
	declare -a new_packages=()
	declare -a curr_packages=()
	local grep_str=""
	local -a args=("$@")
	for ((i = 0; i < $#; i++)); do
		pkg="${args[$i]}"
		grep_str+="|$pkg"
	done
	grep_str="${grep_str:1}"
	# echo "DEBUG: Grep string is ($grep_str)"
	for package in "${packages[@]}"; do
		local extra_dirs=()
		if [[ ! -f "packages/$package/build.sh" ]]; then
			extra_dirs+=("packages")
		elif [[ ! -f "x11-packages/$package/build.sh" ]]; then
			extra_dirs+=("x11-packages")
		elif [[ ! -f "root-packages/$package/build.sh" ]]; then
			extra_dirs+=("root-packages")
		fi
		for pkg in "$@"; do
			if [[ "$pkg" == "$package" ]]; then
				curr_packages+=("$package")
				continue 2
			fi
		done
		if ./scripts/buildorder.py ./*packages/"$package" "${extra_dirs[@]}" | grep -qE "($grep_str)$"; then
			curr_packages+=("$package")
			continue
		fi
		new_packages+=("$package")
	done

	local rebuild_list=()
	for pkg in "${curr_packages[@]}"; do
		local extra_dirs=()
		if [[ ! -f "packages/$pkg/build.sh" ]]; then
			extra_dirs+=("packages")
		elif [[ ! -f "x11-packages/$pkg/build.sh" ]]; then
			extra_dirs+=("x11-packages")
		elif [[ ! -f "root-packages/$pkg/build.sh" ]]; then
			extra_dirs+=("root-packages")
		fi
		for rebuild_pkg in $(./scripts/buildorder.py ./*packages/"$pkg" "${extra_dirs[@]}" | grep -oE "($orig_grep_str)$"); do
			rebuild_list+=("$rebuild_pkg")
		done
		rebuild_list+=("$pkg")
	done
	# Remove duplicates from rebuild_list
	rebuild_list=($(echo "${rebuild_list[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))

	echo "DEBUG: Dealt with $(( ${#packages[@]} - ${#new_packages[@]} )) packages, ${#new_packages[@]} remain. This step rebuilds $((${#rebuild_list[@]} - ${#curr_packages[@]})) extra packages."

	for pkg in "${curr_packages[@]}"; do
		echo "$pkg"
	done > output/rebuildlist-$current_index.txt
	for pkg in "${rebuild_list[@]}"; do
		for curr_pkg in "${curr_packages[@]}"; do
			if [[ "$pkg" == "$curr_pkg" ]]; then
				continue 2
			fi
		done
		echo "$pkg"
	done > output/rebuildlist-$current_index-extra.txt

	packages=("${new_packages[@]}")
	((current_index++))
}
_generate_rebuild_list libllvm flang python-llvmlite python-libsass xapp asciidoc
_generate_rebuild_list python-torch pyqt5
_generate_rebuild_list pygobject pycairo opencv dbus-python python-lxml
_generate_rebuild_list libxml2
_generate_rebuild_list python-numpy python-greenlet python-msgpack python-brotli python-pillow python-scipy
_generate_rebuild_list boost 2ping borgbackup fetchmail speechd vapoursynth
_generate_rebuild_list python-cryptography python-skia-pathops python-pycryptodomex libunbound libsearpc
_generate_rebuild_list "${packages[@]}"

Only the python313 branch needs to be generated full from scratch before running the above script

Warning

As of writing this. the list below (list of todos along with rebuild list) is of the local changes I have, and may not be in sync with the branches and PRs on github.

The following is the significant part that needs to be done first:

  • Move away from Ubuntu's python when building cross python. We need to bootstrap same version of build-python first. Thankfully I had done this a few days ago for an unrelated project, so I have the build scripts with me for an older version that works, I just need to port it for Python 3.13
  • Fix ctypes builtin package not detecting packages for cross-python. ctypes.utils.find_package() isn't working. (Tracked down to python/cpython@1f8b24e)
  • Get all things building (tested locally for aarch64. Waiting for CI to turn green)
  • Get pip packages to build
  • Full test suite locally on Termux + termux-docker, like I do for nodejs

Caution

This is a huge BREAKING CHANGE. Seems like upstream changed a lot of stuff which is going to break a lot of stuff for users. Major breaking changes which I found will affect us most:

Note

Since nobody seems to have started this work since a long time, I am also thinking of taking up maintainership of python. Will try to keep this up to date with full test coverage.

`sys.platform` now reports `"android"`

Earlier versions of uptil 3.12 used to have sys.platform to "linux"

import sys

# Prints "android" on Python >= 3.13
# and    "linux"   on Python <= 3.12
print(sys.platform)

This will very likely break scripts that assume Android to just be Linux earlier. Might need new changes in packages downstream. This is going to be definitely a lot of fun to deal with. Although shouldn't be that much pain considering Android is now a supported platform

Rebuild Step 1 #27768 List of packages that will be rebuilt:
asciidoc
cinnamon
codelldb
flang
libllvm
python-libsass
python-llvmlite
python-xapp
termux-apt-repo
xapp

List of extra packages that need to be rebuilt 1 (due to extra dependencies):

at-spi2-core
dbus-python
libunbound
libxml2
pycairo
pygobject
python-lxml
python-pillow
xcb-proto
Rebuild Step 2 #27777 List of packages that will be rebuilt:
pyqt5
python-pyqtwebengine
python-qscintilla
python-torch
python-torchaudio
python-torchcodec
python-torchvision

List of extra packages that need to be rebuilt 2 (due to extra dependencies):

at-spi2-core
boost
libunbound
libxml2
python-lxml
python-numpy
python-pillow
xcb-proto
Rebuild Step 3 #27977 List of packages that will be rebuilt:
blueprint-compiler
dbus-python
gjots2
gnumeric
gst-python
libncnn
manim
meld
mlt
opencv
orca
pyatspi
pycairo
pygobject
python-lxml
python-opencv-python

List of extra packages that need to be rebuilt 3 (due to extra dependencies):

at-spi2-core
boost
libunbound
libxml2
python-numpy
python-pillow
python-scipy
python-skia-pathops
speechd
xcb-proto
Rebuild Step 4 #28180 List of packages that will be rebuilt:
at-spi2-core
gnucash
libxml2
nala
python-apt
python-cmake
recoll

List of extra packages that need to be rebuilt 4 (due to extra dependencies):

boost
libunbound
xcb-proto
Rebuild Step 5 #28181 List of packages that will be rebuilt:
libarrow-cpp
matplotlib
python-brotli
python-contourpy
python-greenlet
python-msgpack
python-numpy
python-onnxruntime
python-pillow
python-pynvim
python-scipy
python-tflite-runtime
python-yt-dlp

List of extra packages that need to be rebuilt 5 (due to extra dependencies):

boost
python-pycryptodomex
xcb-proto
Rebuild Step 6 #28182 List of packages that will be rebuilt:
2ping
boost
borgbackup
fetchmail
ledger
libtorrent-rasterbar
speechd
tizonia
vapoursynth

List of extra packages that need to be rebuilt 6 (due to extra dependencies):

xcb-proto
Rebuild Step 7 #28183 List of packages that will be rebuilt:
electrum
libsearpc
libunbound
python-cryptography
python-pycryptodomex
python-skia-pathops
seafile-client

List of extra packages that need to be rebuilt 7 (due to extra dependencies):

xcb-proto
Rebuild Step 8 #28184 List of packages that will be rebuilt:
frida
python-apsw
python-bcrypt
python-grpcio
python-lameenc
python-sabyenc3
python-tldp
python-xlib
ranger
rdiff-backup
ruff
udocker
xcb-proto
yt-dlp-ejs

List of extra packages that need to be rebuilt 8 (due to extra dependencies):

@robertkirkman
Copy link
Member

Since nobody seems to have touched this, I am also thinking of taking up maintainership of python.

Wonderful! I had been planning to do this, but only after finishing my current python PR. My current python PR is still not finished, so you can feel free to work on this.

Is there any specific reason this isn't the newest version, 3.14.2?

@thunder-coding
Copy link
Member Author

thunder-coding commented Dec 25, 2025

Is there any specific reason this isn't the newest version, 3.14.2?

I assume that python 3.14 might have some breaking changes that might not be suitable for everyone yet. Will upgrade to 3.13 now, then will target 3.14 in the next few months. I'm targeting python 3.13 by mid-January.

I'm delaying the target merge date for this PR to mid-February due to extra large size and need for extensive testing. Python 3.14 will likely be targeted by March-end.

@thunder-coding thunder-coding force-pushed the python313 branch 2 times, most recently from e304736 to 6c9ed54 Compare December 26, 2025 18:36
@robertkirkman
Copy link
Member

robertkirkman commented Dec 27, 2025

Python 3.13 Upstream Android support (PEP738) test notes

  • Appears to be working successfully (after working around the issue involving pip described above)
  • pip install may download native libraries prebuilt for Android from some PyPi packages rather than building them all from source
  • Whether some may include ADB-isms (like attempts to access absolute path /data/local/tmp), APK-isms (like attempts to access ANativeActivity or ANativeWindow), or Android-8-isms (like binaries built targeting a higher API level than 24 which then attempt to call functions like getloadavg()) remains unknown, but no cases of any of those have yet been observed
  • PyPi packages containing native libraries prebuilt for Android identified using this list: https://beeware.org/mobile-wheels/

Test 1: pip install pypdfium2

  • Worked without errors
  • Important: testing indicates that pypdfium2 has implemented Android native library support compatible with Python 3.12, meaning that some, but not all, PyPi packages already contain Android native libraries that are successfully deployed to Termux currently, without necessarily requiring Python 3.13. Because of that, the behavior of pip install pypdfium2 is the same regardless of whether this PR is applied.

Test 2: pip install optree

  • Worked without errors
  • Testing indicates that, unlike the case of pypdfium2, optree leverages PEP738 to deploy its Android native library, meaning that pip install optree does behave differently in Python 3.13 from how it does in Python 3.12.
  • Building wheel for optree did not print; instead, Downloading optree-0.18.0-cp313-cp313-android_24_x86_64.whl printed
  • A $PREFIX/lib/python3.13/site-packages/optree/_C.cpython-313-x86_64-linux-android.so was installed
  • file $PREFIX/lib/python3.13/site-packages/optree/_C.cpython-313-x86_64-linux-android.so prints this:
    • ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, for Android 24, built by NDK r27d (13750724), BuildID[sha1]=84f99286f68a16ce87232652f5558339de6ddb65, stripped
  • Since it was built by NDK r27d, not NDK r28 or newer, this suggests that a possible side effect could be incompatibility of some of these PEP738 wheels with 16KB-page-size-only devices.
  • optree basic program tested successfully:
#!/usr/bin/env python3

import optree

tree = {'b': (2, [3, 4]), 'a': 1, 'c': 5, 'd': 6}
optree.tree_flatten(tree)

Summary

  • Appears to be working, no Termux-specific interventions appear to be necessary at this time, unless a particular PyPi package is found to be bugged
  • Some PyPi packages may temporarily lose compatibility with 16KB-page-size-only devices until their respective upstreams upgrade to NDK r28 or newer; this seems minor, since there are very few 16KB-page-size-only devices.

@thunder-coding
Copy link
Member Author

Thanks for the brief. I havent started testing yet. Just pushed the changed I had for proper cross-compilation I has been holding since some time. Will be busy this month with some stuff. Wont be moving ahead without running tests for Python

@thunder-coding thunder-coding force-pushed the python313 branch 2 times, most recently from c571932 to e28b038 Compare December 28, 2025 08:49
@thunder-coding thunder-coding moved this from In Progress to Blocked in @thunder-coding's public tracker Dec 28, 2025
@thunder-coding thunder-coding force-pushed the python313 branch 2 times, most recently from b43981f to 8a0acfd Compare December 28, 2025 14:36
@thunder-coding thunder-coding force-pushed the python313 branch 2 times, most recently from 55b54bb to 6247dbc Compare December 28, 2025 19:09
@thunder-coding thunder-coding moved this from Blocked to In Progress in @thunder-coding's public tracker Dec 28, 2025
@thunder-coding thunder-coding force-pushed the python313 branch 2 times, most recently from e2473d3 to d4c16e0 Compare January 8, 2026 22:24
+ if api_level is None:
+ # Python 3.13 was the first version to return platform.system() == "Android",
+ # and also the first version to define platform.android_ver().
+ api_level = @@TERMUX_PKG_API_LEVEL@@ # type: ignore[attr-defined]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch fixed cross-pip throwing up with python 3.13. This should get all python packages built properly

@thunder-coding thunder-coding moved this from In Progress to Blockers in @thunder-coding's public tracker Jan 9, 2026
@thunder-coding thunder-coding force-pushed the python313 branch 2 times, most recently from fb5d6b8 to 9f13f43 Compare January 10, 2026 02:08
@thunder-coding

This comment was marked as outdated.

termux_setup_python_pip is called to ensure that cross-pip is used and
python library install path is detected properly by CMake, don't know
why this is needed when building with Python 3.13 on target, but not
when building with Python 3.12 on target. Maybe due to version mismatch
between host and target?
All packages in this before this commit(s) before the last CI run will
be rebuilt manually using github workflow dispatch. This commit just
acts as a marker for reference so that I don't get lost while trying to
figure out which ones are left and also to not myself mad while trying
to figure out the dependency tree so that packages aren't built in the
wrong order.

%ci:no-build
@thunder-coding thunder-coding merged commit 55920c0 into master Mar 3, 2026
7 of 11 checks passed
licy183 added a commit to termux-user-repository/tur that referenced this pull request Mar 4, 2026
- After termux/termux-packages#27739

---------

Co-authored-by: Chongyun Lee <45286352+licy183@users.noreply.github.com>
Mause pushed a commit to Mause/termux-packages that referenced this pull request Mar 14, 2026
pipewire-jack package never existed. I have no idea why it was even
there in the first place

This comment broke my script to compute rebuild order for python
packages. The script can be found in
termux#27739 (comment)

%ci:no-build
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

3 participants