From e8c75812feb1022f2886dfdafb1c57b65e4fe1a5 Mon Sep 17 00:00:00 2001 From: Ryan Kuester Date: Tue, 30 Sep 2025 12:10:28 -0500 Subject: [PATCH] feat(pypi): add support for Python 3.12 and 3.13 Add build configuration for Python 3.12 and 3.13 to the PyPI package. Update the BUILD file with new compatibility tags and config settings, extend pypi_build.sh to accept the new Python versions, and add build steps in the GitHub Actions workflow. Fix whl_test.sh to rename wheels with unstamped variable names before pip installation. The py_wheel rule creates the base :whl target with literal stamp variables like _BUILD_EMBED_LABEL_ in the filename for Bazel caching purposes. Pip 25.x, which ships with Python 3.12+, strictly validates wheel filenames and rejects these as invalid version specifiers. Use sed to replace the unstamped variables with a valid placeholder version (0.0.0) for testing purposes. Python 3.14 support is not included because Python 3.14 has not yet been released (scheduled for October 2025). Fixes: #3186 --- .github/workflows/pypi_build.yml | 6 ++++++ python/tflite_micro/BUILD | 22 ++++++++++++++++++++++ python/tflite_micro/pypi_build.sh | 4 +++- python/tflite_micro/whl_test.sh | 13 +++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pypi_build.yml b/.github/workflows/pypi_build.yml index 52a8075f05e..90eec1aba8f 100644 --- a/.github/workflows/pypi_build.yml +++ b/.github/workflows/pypi_build.yml @@ -38,6 +38,12 @@ jobs: - name: Build Wheel 3.11 run: | python/tflite_micro/pypi_build.sh cp311 + - name: Build Wheel 3.12 + run: | + python/tflite_micro/pypi_build.sh cp312 + - name: Build Wheel 3.13 + run: | + python/tflite_micro/pypi_build.sh cp313 - name: Check Directory Output run: | ls -l bazel-pypi-out diff --git a/python/tflite_micro/BUILD b/python/tflite_micro/BUILD index 085023fdb5e..615c8376f80 100644 --- a/python/tflite_micro/BUILD +++ b/python/tflite_micro/BUILD @@ -201,6 +201,8 @@ string_flag( values = [ "cp310_cp310_manylinux_2_28_x86_64", "cp311_cp311_manylinux_2_28_x86_64", + "cp312_cp312_manylinux_2_28_x86_64", + "cp313_cp313_manylinux_2_28_x86_64", "local", ], ) @@ -219,6 +221,20 @@ config_setting( }, ) +config_setting( + name = "cp312_cp312_manylinux_2_28_x86_64", + flag_values = { + ":compatibility_tag": "cp312_cp312_manylinux_2_28_x86_64", + }, +) + +config_setting( + name = "cp313_cp313_manylinux_2_28_x86_64", + flag_values = { + ":compatibility_tag": "cp313_cp313_manylinux_2_28_x86_64", + }, +) + config_setting( name = "local", flag_values = { @@ -235,6 +251,8 @@ py_wheel( abi = select({ ":cp310_cp310_manylinux_2_28_x86_64": "cp310", ":cp311_cp311_manylinux_2_28_x86_64": "cp311", + ":cp312_cp312_manylinux_2_28_x86_64": "cp312", + ":cp313_cp313_manylinux_2_28_x86_64": "cp313", ":local": "none", }), description_file = ":description_file", @@ -242,11 +260,15 @@ py_wheel( platform = select({ ":cp310_cp310_manylinux_2_28_x86_64": "manylinux_2_28_x86_64", ":cp311_cp311_manylinux_2_28_x86_64": "manylinux_2_28_x86_64", + ":cp312_cp312_manylinux_2_28_x86_64": "manylinux_2_28_x86_64", + ":cp313_cp313_manylinux_2_28_x86_64": "manylinux_2_28_x86_64", ":local": "any", }), python_tag = select({ ":cp310_cp310_manylinux_2_28_x86_64": "cp310", ":cp311_cp311_manylinux_2_28_x86_64": "cp311", + ":cp312_cp312_manylinux_2_28_x86_64": "cp312", + ":cp313_cp313_manylinux_2_28_x86_64": "cp313", ":local": "py3", }), requires = [ diff --git a/python/tflite_micro/pypi_build.sh b/python/tflite_micro/pypi_build.sh index 166071f783b..53e50ee2802 100755 --- a/python/tflite_micro/pypi_build.sh +++ b/python/tflite_micro/pypi_build.sh @@ -26,12 +26,14 @@ container. Uses bazel, but does not pollute the WORKSPACE's default cache. must be one of the supported interpreters: cp310 cp311 + cp312 + cp313 defaults to $OUT_DIR_DEFAULT. " case "$1" in - cp310|cp311) + cp310|cp311|cp312|cp313) PY_TAG=$1 OUTDIR=$(realpath ${2:-$OUT_DIR_DEFAULT}) mkdir -p $OUTDIR diff --git a/python/tflite_micro/whl_test.sh b/python/tflite_micro/whl_test.sh index f3e829314ec..718e614db74 100755 --- a/python/tflite_micro/whl_test.sh +++ b/python/tflite_micro/whl_test.sh @@ -21,6 +21,19 @@ set -e WHL="${1}" +# Rename wheel if it has unstamped variables in the filename. The py_wheel rule +# creates two outputs: the base :whl target with literal stamp variables in the +# filename (for Bazel caching), and :whl.dist with expanded variables. This test +# uses :whl as its data dependency because :whl.dist isn't a proper Bazel target +# that can be referenced in deps. Pip 25.x in Python 3.12+ strictly validates +# wheel filenames and rejects literal stamp variables like _BUILD_EMBED_LABEL_. +# Replace with a valid placeholder version for testing purposes. +if echo "${WHL}" | grep -q '_BUILD_EMBED_LABEL_'; then + RENAMED_WHL=$(echo "${WHL}" | sed 's/_BUILD_EMBED_LABEL_\.dev_STABLE_GIT_COMMIT_TIME_/0.0.0/') + cp "${WHL}" "${RENAMED_WHL}" + WHL="${RENAMED_WHL}" +fi + # Create venv for this test. python3 -m venv pyenv . pyenv/bin/activate