Skip to content

Commit 063f412

Browse files
committed
feat: add CPython 3.13
1 parent 69f1fb2 commit 063f412

File tree

8 files changed

+86
-31
lines changed

8 files changed

+86
-31
lines changed

.github/workflows/update-dependencies.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v4
1717
- uses: wntrblm/[email protected]
1818
with:
19-
python-versions: "3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12-dev"
19+
python-versions: "3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13-dev"
2020
- name: "Allow nox to run with python 3.6"
2121
run: pipx runpip nox install 'virtualenv<20.22.0'
2222
- name: "Setup bot user"

docker/Dockerfile

+5
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ FROM build_cpython AS build_cpython312
137137
COPY build_scripts/cpython-pubkey-312-313.txt /build_scripts/cpython-pubkeys.txt
138138
RUN manylinux-entrypoint /build_scripts/build-cpython.sh 3.12.3
139139

140+
FROM build_cpython AS build_cpython313
141+
COPY build_scripts/cpython-pubkey-312-313.txt /build_scripts/cpython-pubkeys.txt
142+
RUN manylinux-entrypoint /build_scripts/build-cpython.sh 3.13.0b1
143+
140144

141145
FROM runtime_base
142146
COPY --from=build_git /manylinux-rootfs /
@@ -149,6 +153,7 @@ RUN --mount=type=bind,target=/build_cpython36,from=build_cpython36 \
149153
--mount=type=bind,target=/build_cpython310,from=build_cpython310 \
150154
--mount=type=bind,target=/build_cpython311,from=build_cpython311 \
151155
--mount=type=bind,target=/build_cpython312,from=build_cpython312 \
156+
--mount=type=bind,target=/build_cpython313,from=build_cpython313 \
152157
mkdir -p /opt/_internal && \
153158
cp -rf /build_cpython*/opt/_internal/* /opt/_internal/ && \
154159
manylinux-entrypoint /opt/_internal/build_scripts/finalize.sh \

docker/build_scripts/build-cpython.sh

+11-5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ pushd Python-${CPYTHON_VERSION}
3333
PREFIX="/opt/_internal/cpython-${CPYTHON_VERSION}"
3434
mkdir -p ${PREFIX}/lib
3535
CFLAGS_EXTRA=""
36+
CONFIGURE_ARGS="--disable-shared --with-ensurepip=no"
37+
38+
if [ "${2:-}" == "nogil" ]; then
39+
PREFIX="${PREFIX}-nogil"
40+
CONFIGURE_ARGS="${CONFIGURE_ARGS} --disable-gil"
41+
fi
42+
3643
if [ "${CPYTHON_VERSION}" == "3.6.15" ]; then
3744
# https://github.com/python/cpython/issues/89863
3845
# gcc-12+ uses these 2 flags in -O2 but they were only enabled in -O3 with gcc-11
@@ -43,22 +50,21 @@ if [ "${AUDITWHEEL_POLICY}" == "manylinux2014" ] ; then
4350
export TCLTK_LIBS="-ltk8.6 -ltcl8.6"
4451
fi
4552

46-
OPENSSL_EXTRA=""
4753
OPENSSL_PREFIX=$(find /opt/_internal -maxdepth 1 -name 'openssl*')
4854
if [ "${OPENSSL_PREFIX}" != "" ]; then
49-
OPENSSL_EXTRA="--with-openssl=${OPENSSL_PREFIX}"
55+
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-openssl=${OPENSSL_PREFIX}"
5056
case "${CPYTHON_VERSION}" in
5157
3.8.*|3.9.*) export LD_RUN_PATH=${OPENSSL_PREFIX}/lib;;
52-
*) OPENSSL_EXTRA="${OPENSSL_EXTRA} --with-openssl-rpath=auto";;
58+
*) CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-openssl-rpath=auto";;
5359
esac
5460
fi
5561

5662
# configure with hardening options only for the interpreter & stdlib C extensions
5763
# do not change the default for user built extension (yet?)
5864
./configure \
5965
CFLAGS_NODIST="${MANYLINUX_CFLAGS} ${MANYLINUX_CPPFLAGS} ${CFLAGS_EXTRA}" \
60-
LDFLAGS_NODIST="${MANYLINUX_LDFLAGS}" ${OPENSSL_EXTRA} \
61-
--prefix=${PREFIX} --disable-shared --with-ensurepip=no > /dev/null
66+
LDFLAGS_NODIST="${MANYLINUX_LDFLAGS}" \
67+
--prefix=${PREFIX} ${CONFIGURE_ARGS} > /dev/null
6268
make > /dev/null
6369
make install > /dev/null
6470
popd

docker/build_scripts/finalize-one.sh

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if [ -e ${PREFIX}/bin/python3 ] && [ ! -e ${PREFIX}/bin/python ]; then
1515
fi
1616
PY_VER=$(${PREFIX}/bin/python -c "import sys; print('.'.join(str(v) for v in sys.version_info[:2]))")
1717
PY_IMPL=$(${PREFIX}/bin/python -c "import sys; print(sys.implementation.name)")
18+
PY_GIL=$(${PREFIX}/bin/python -c "import sysconfig; print('t' if sysconfig.get_config_vars().get('Py_GIL_DISABLED', 0) else '')")
1819

1920
# Install pinned packages for this python version.
2021
# Use the already intsalled cpython pip to bootstrap pip if available
@@ -32,6 +33,6 @@ ABI_TAG=$(${PREFIX}/bin/python ${MY_DIR}/python-tag-abi-tag.py)
3233
ln -s ${PREFIX} /opt/python/${ABI_TAG}
3334
# Make versioned python commands available directly in environment.
3435
if [[ "${PY_IMPL}" == "cpython" ]]; then
35-
ln -s ${PREFIX}/bin/python /usr/local/bin/python${PY_VER}
36+
ln -s ${PREFIX}/bin/python /usr/local/bin/python${PY_VER}${PY_GIL}
3637
fi
37-
ln -s ${PREFIX}/bin/python /usr/local/bin/${PY_IMPL}${PY_VER}
38+
ln -s ${PREFIX}/bin/python /usr/local/bin/${PY_IMPL}${PY_VER}${PY_GIL}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.13
3+
# by the following command:
4+
#
5+
# nox -s update_python_dependencies-3.13
6+
#
7+
build==1.2.1 \
8+
--hash=sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d \
9+
--hash=sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4
10+
# via -r requirements.in
11+
packaging==24.0 \
12+
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
13+
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
14+
# via
15+
# -r requirements.in
16+
# build
17+
pyproject-hooks==1.1.0 \
18+
--hash=sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965 \
19+
--hash=sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2
20+
# via build
21+
wheel==0.43.0 \
22+
--hash=sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85 \
23+
--hash=sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81
24+
# via -r requirements.in
25+
26+
# The following packages are considered to be unsafe in a requirements file:
27+
pip==24.0 \
28+
--hash=sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc \
29+
--hash=sha256:ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2
30+
# via -r requirements.in
31+
setuptools==69.5.1 \
32+
--hash=sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987 \
33+
--hash=sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32
34+
# via -r requirements.in

noxfile.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import nox
66

77

8-
@nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"])
8+
@nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"])
99
def update_python_dependencies(session):
1010
session.install("pip-tools")
1111
env = os.environ.copy()

tests/run_tests.sh

+12-11
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ else
1818
fi
1919

2020
if [ "${AUDITWHEEL_POLICY:0:10}" == "musllinux_" ]; then
21-
EXPECTED_PYTHON_COUNT=7
22-
EXPECTED_PYTHON_COUNT_ALL=7
21+
EXPECTED_PYTHON_COUNT=8
22+
EXPECTED_PYTHON_COUNT_ALL=8
2323
else
2424
if [ "${AUDITWHEEL_ARCH}" == "x86_64" ] || [ "${AUDITWHEEL_ARCH}" == "i686" ] || [ "${AUDITWHEEL_ARCH}" == "aarch64" ]; then
25-
EXPECTED_PYTHON_COUNT=11
26-
EXPECTED_PYTHON_COUNT_ALL=11
25+
EXPECTED_PYTHON_COUNT=12
26+
EXPECTED_PYTHON_COUNT_ALL=12
2727
else
28-
EXPECTED_PYTHON_COUNT=7
29-
EXPECTED_PYTHON_COUNT_ALL=7
28+
EXPECTED_PYTHON_COUNT=8
29+
EXPECTED_PYTHON_COUNT_ALL=8
3030
fi
3131
fi
3232
PYTHON_COUNT=$(manylinux-interpreters list --installed | wc -l)
@@ -58,27 +58,28 @@ for PYTHON in /opt/python/*/bin/python; do
5858
$PYTHON $MY_DIR/ssl-check.py
5959
IMPLEMENTATION=$(${PYTHON} -c "import sys; print(sys.implementation.name)")
6060
PYVERS=$(${PYTHON} -c "import sys; print('.'.join(map(str, sys.version_info[:2])))")
61+
PY_GIL=$(${PYTHON} -c "import sysconfig; print('t' if sysconfig.get_config_vars().get('Py_GIL_DISABLED', 0) else '')")
6162
if [ "${IMPLEMENTATION}" == "cpython" ]; then
6263
# Make sure sqlite3 module can be loaded properly and is the manylinux version one
6364
# c.f. https://github.com/pypa/manylinux/issues/1030
6465
$PYTHON -c 'import sqlite3; print(sqlite3.sqlite_version); assert sqlite3.sqlite_version_info[0:2] >= (3, 34)'
6566
# Make sure tkinter module can be loaded properly
6667
$PYTHON -c 'import tkinter; print(tkinter.TkVersion); assert tkinter.TkVersion >= 8.6'
6768
# cpython shall be available as python
68-
LINK_VERSION=$(python${PYVERS} -VV)
69+
LINK_VERSION=$(python${PYVERS}${PY_GIL} -VV)
6970
REAL_VERSION=$(${PYTHON} -VV)
7071
test "${LINK_VERSION}" = "${REAL_VERSION}"
7172
fi
7273
# cpythonX.Y / pypyX.Y shall be available directly in PATH
73-
LINK_VERSION=$(${IMPLEMENTATION}${PYVERS} -VV)
74+
LINK_VERSION=$(${IMPLEMENTATION}${PYVERS}${PY_GIL} -VV)
7475
REAL_VERSION=$(${PYTHON} -VV)
7576
test "${LINK_VERSION}" = "${REAL_VERSION}"
7677

7778
# check a simple project can be built
78-
SRC_DIR=/tmp/forty-two-${IMPLEMENTATION}${PYVERS}
79-
DIST_DIR=/tmp/dist-${IMPLEMENTATION}${PYVERS}
80-
cp -rf ${MY_DIR}/forty-two ${SRC_DIR}
8179
PY_ABI_TAGS=$(basename $(dirname $(dirname $PYTHON)))
80+
SRC_DIR=/tmp/forty-two-${PY_ABI_TAGS}
81+
DIST_DIR=/tmp/dist-${PY_ABI_TAGS}
82+
cp -rf ${MY_DIR}/forty-two ${SRC_DIR}
8283
EXPECTED_WHEEL_NAME=forty_two-0.1.0-${PY_ABI_TAGS}-linux_${AUDITWHEEL_ARCH}.whl
8384
${PYTHON} -m build -w -o ${DIST_DIR} ${SRC_DIR}
8485
if [ ! -f ${DIST_DIR}/${EXPECTED_WHEEL_NAME} ]; then

tools/update_native_dependencies.py

+19-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import re
44
import subprocess
55

6+
from collections import defaultdict
67
from pathlib import Path
78

89
import requests
@@ -30,23 +31,30 @@ def _sha256(url):
3031

3132
def _update_cpython(dry_run):
3233
lines = DOCKERFILE.read_text().splitlines()
33-
re_ = re.compile(r"^RUN.*/build-cpython.sh (?P<version>.*)$")
34+
re_ = re.compile(r"^RUN.*/build-cpython.sh .*$")
35+
updates = defaultdict(list)
3436
for i in range(len(lines)):
3537
match = re_.match(lines[i])
3638
if match is None:
3739
continue
38-
current_version = Version(match["version"])
40+
version = lines[i].strip().split()[3]
41+
current_version = Version(version)
3942
latest_version = latest("python/cpython", major=f'{current_version.major}.{current_version.minor}', pre_ok=current_version.is_prerelease)
4043
if latest_version > current_version:
41-
root = f"Python-{latest_version}"
42-
url = f"https://www.python.org/ftp/python/{latest_version.major}.{latest_version.minor}.{latest_version.micro}"
43-
_sha256(f"{url}/{root}.tar.xz")
44-
lines[i] = lines[i].replace(match["version"], str(latest_version))
45-
message = f"Bump CPython {current_version}{latest_version}"
46-
print(message)
47-
if not dry_run:
48-
DOCKERFILE.write_text("\n".join(lines) + "\n")
49-
subprocess.check_call(["git", "commit", "-am", message])
44+
key = (version, str(latest_version))
45+
if len(updates[key]) == 0:
46+
root = f"Python-{latest_version}"
47+
url = f"https://www.python.org/ftp/python/{latest_version.major}.{latest_version.minor}.{latest_version.micro}"
48+
_sha256(f"{url}/{root}.tar.xz")
49+
updates[key].append(i)
50+
for key in updates:
51+
for i in updates[key]:
52+
lines[i] = lines[i].replace(key[0], key[1])
53+
message = f"Bump CPython {key[0]}{key[1]}"
54+
print(message)
55+
if not dry_run:
56+
DOCKERFILE.write_text("\n".join(lines) + "\n")
57+
subprocess.check_call(["git", "commit", "-am", message])
5058

5159

5260
def _update_with_root(tool, dry_run):

0 commit comments

Comments
 (0)