Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python 3.11 #199

Merged
merged 1 commit into from
Feb 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ jobs:
matrix:
arch: ${{ fromJson(needs.init.outputs.architectures_alpine) }}
version: ["3.14", "3.15", "3.16"]
python: ["3.8", "3.9", "3.10"]
python: ["3.8", "3.9", "3.10", "3.11"]
steps:
- name: Checkout the repository
uses: actions/checkout@v3
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ We support the latest 3 release with the latest 3 Alpine version.

| Image | OS | Tags | latest |
|-------|----|------|--------|
| armhf-base-python | Alpine | 3.8, 3.9, 3.10, 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16 | 3.10-alpine.3.16 |
| armv7-base-python | Alpine | 3.8, 3.9, 3.10, 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16 | 3.10-alpine.3.16 |
| aarch64-base-python | Alpine | 3.8, 3.9, 3.10, 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16 | 3.10-alpine.3.16 |
| amd64-base-python | Alpine | 3.8, 3.9, 3.10, 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16 | 3.10-alpine.3.16 |
| i386-base-python | Alpine | 3.8, 3.9, 3.10, 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16 | 3.10-alpine.3.16 |
| armhf-base-python | Alpine | 3.8, 3.9, 3.10, 3.11 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16, 3.11-alpine3.14, 3.11-alpine3.15, 3.11-alpine3.16 | 3.10-alpine.3.16 |
| armv7-base-python | Alpine | 3.8, 3.9, 3.10, 3.11 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16, 3.11-alpine3.14, 3.11-alpine3.15, 3.11-alpine3.16 | 3.10-alpine.3.16 |
| aarch64-base-python | Alpine | 3.8, 3.9, 3.10, 3.11 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16, 3.11-alpine3.14, 3.11-alpine3.15, 3.11-alpine3.16 | 3.10-alpine.3.16 |
| amd64-base-python | Alpine | 3.8, 3.9, 3.10, 3.11 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16, 3.11-alpine3.14, 3.11-alpine3.15, 3.11-alpine3.16 | 3.10-alpine.3.16 |
| i386-base-python | Alpine | 3.8, 3.9, 3.10, 3.11, 3.8-alpine3.14, 3.8-alpine3.15, 3.8-alpine3.16, 3.9-alpine3.14, 3.9-alpine3.15, 3.9-alpine3.16, 3.10-alpine3.14, 3.10-alpine3.15, 3.10-alpine3.16, 3.11-alpine3.14, 3.11-alpine3.15, 3.11-alpine3.16 | 3.10-alpine.3.16 |

## Others

Expand Down
132 changes: 132 additions & 0 deletions python/3.11/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
ARG BUILD_FROM
FROM $BUILD_FROM

ARG \
PYTHON_VERSION \
PIP_VERSION \
GPG_KEY \
QEMU_CPU

# ensure local python is preferred over distribution python
ENV PATH /usr/local/bin:$PATH

# Set shell
SHELL ["/bin/ash", "-o", "pipefail", "-c"]

COPY *.patch /usr/src/
RUN set -ex \
&& export PYTHON_VERSION=${PYTHON_VERSION} \
&& apk add --no-cache --virtual .fetch-deps \
gnupg \
openssl \
tar \
xz \
\
&& curl -L -o python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \
&& curl -L -o python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& echo "disable-ipv6" >> "$GNUPGHOME/dirmngr.conf" \
&& gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "${GPG_KEY}" \
&& gpg --batch --verify python.tar.xz.asc python.tar.xz \
&& { command -v gpgconf > /dev/null && gpgconf --kill all || :; } \
&& rm -rf "$GNUPGHOME" python.tar.xz.asc \
&& mkdir -p /usr/src/python \
&& tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \
&& rm python.tar.xz \
\
&& apk add --no-cache --virtual .build-deps \
patch \
bzip2-dev \
coreutils \
dpkg-dev dpkg \
expat-dev \
findutils \
build-base \
gdbm-dev \
libc-dev \
libffi-dev \
libnsl-dev \
openssl \
openssl-dev \
libtirpc-dev \
linux-headers \
make \
mpdecimal-dev \
ncurses-dev \
pax-utils \
readline-dev \
sqlite-dev \
tcl-dev \
tk \
tk-dev \
xz-dev \
zlib-dev \
bluez-dev \
# add build deps before removing fetch deps in case there's overlap
&& apk del .fetch-deps \
\
&& for i in /usr/src/*.patch; do \
patch -d /usr/src/python -p 1 < "${i}"; done \
&& cd /usr/src/python \
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
&& ./configure \
--build="$gnuArch" \
--enable-loadable-sqlite-extensions \
--enable-optimizations \
--enable-option-checking=fatal \
--enable-shared \
--with-lto \
--with-system-libmpdec \
--with-system-expat \
--with-system-ffi \
--without-ensurepip \
--without-static-libpython \
&& make -j "$(nproc)" \
LDFLAGS="-Wl,--strip-all" \
CFLAGS="-fno-semantic-interposition -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free" \
# set thread stack size to 1MB so we don't segfault before we hit sys.getrecursionlimit()
# https://github.com/alpinelinux/aports/commit/2026e1259422d4e0cf92391ca2d3844356c649d0
EXTRA_CFLAGS="-DTHREAD_STACK_SIZE=0x100000" \
&& make install \
\
&& find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec scanelf --needed --nobanner --format '%n#p' '{}' ';' \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
| xargs -rt apk add --no-cache --virtual .python-rundeps \
&& apk del .build-deps \
\
&& find /usr/local -depth \
\( \
-type d -a \( -name test -o -name tests \) \
\) -exec rm -rf '{}' + \
&& rm -rf /usr/src/python \
&& rm -f /usr/src/*.patch

# make some useful symlinks that are expected to exist
RUN cd /usr/local/bin \
&& ln -s idle3 idle \
&& ln -s pydoc3 pydoc \
&& ln -s python3 python \
&& ln -s python3-config python-config

RUN set -ex; \
\
apk add --no-cache --virtual .fetch-deps openssl; \
\
curl -L -o get-pip.py 'https://bootstrap.pypa.io/get-pip.py'; \
\
apk del .fetch-deps; \
\
python get-pip.py \
--disable-pip-version-check \
--no-cache-dir \
pip==${PIP_VERSION} \
; \
pip --version; \
\
find /usr/local -depth \
\( \
-type d -a \( -name test -o -name tests \) \
\) -exec rm -rf '{}' +; \
rm -f get-pip.py
17 changes: 17 additions & 0 deletions python/3.11/arm-alignment.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Author: Dave Jones <[email protected]>
Description: Use aligned access for _sha3 module on ARM.
--- a/Modules/_sha3/sha3module.c
+++ b/Modules/_sha3/sha3module.c
@@ -64,6 +64,12 @@
#define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#endif

+/* Bus error on 32-bit ARM due to un-aligned memory accesses; 64-bit ARM
+ * doesn't complain but un-aligned memory accesses are sub-optimal */
+#if defined(__arm__) || defined(__aarch64__)
+#define NO_MISALIGNED_ACCESSES
+#endif
+
/* mangle names */
#define KeccakF1600_FastLoop_Absorb _PySHA3_KeccakF1600_FastLoop_Absorb
#define Keccak_HashFinal _PySHA3_Keccak_HashFinal
18 changes: 18 additions & 0 deletions python/3.11/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
image: homeassistant/{arch}-base-python
shadow_repository: ghcr.io/home-assistant
build_from:
aarch64: "homeassistant/aarch64-base:"
armv7: "homeassistant/armv7-base:"
armhf: "homeassistant/armhf-base:"
amd64: "homeassistant/amd64-base:"
i386: "homeassistant/i386-base:"
codenotary:
signer: [email protected]
base_image: [email protected]
args:
PYTHON_VERSION: 3.11.2
PIP_VERSION: 23.0.0
GPG_KEY: A035C8C19219BA821ECEA86B64E628F8D684696D
labels:
io.hass.base.name: python
org.opencontainers.image.source: https://github.com/home-assistant/docker-base
15 changes: 15 additions & 0 deletions python/3.11/fix-xattrs-glibc.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 12f72f5..d54d085 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -234,8 +234,9 @@ corresponding Unix manual entries for more information on calls.");
# undef HAVE_SCHED_SETAFFINITY
#endif

-#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
+#if defined(HAVE_SYS_XATTR_H) && defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
# define USE_XATTRS
+# include <linux/limits.h>
#endif

#ifdef USE_XATTRS
45 changes: 45 additions & 0 deletions python/3.11/musl-find_library.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
diff -ru Python-2.7.12.orig/Lib/ctypes/util.py Python-2.7.12/Lib/ctypes/util.py
--- Python-2.7.12.orig/Lib/ctypes/util.py 2016-06-26 00:49:30.000000000 +0300
+++ Python-2.7.12/Lib/ctypes/util.py 2016-11-03 16:05:46.954665040 +0200
@@ -204,6 +204,41 @@
def find_library(name, is64 = False):
return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name))

+ elif True:
+
+ # Patched for Alpine Linux / musl - search manually system paths
+ def _is_elf(filepath):
+ try:
+ with open(filepath, 'rb') as fh:
+ return fh.read(4) == b'\x7fELF'
+ except:
+ return False
+
+ def find_library(name):
+ from glob import glob
+ # absolute name?
+ if os.path.isabs(name):
+ return name
+ # special case for libm, libcrypt and libpthread and musl
+ if name in ['m', 'crypt', 'pthread']:
+ name = 'c'
+ elif name in ['libm.so', 'libcrypt.so', 'libpthread.so']:
+ name = 'libc.so'
+ # search in standard locations (musl order)
+ paths = ['/lib', '/usr/local/lib', '/usr/lib']
+ if 'LD_LIBRARY_PATH' in os.environ:
+ paths = os.environ['LD_LIBRARY_PATH'].split(':') + paths
+ for d in paths:
+ f = os.path.join(d, name)
+ if _is_elf(f):
+ return os.path.basename(f)
+
+ prefix = os.path.join(d, 'lib'+name)
+ for suffix in ['.so', '.so.*']:
+ for f in glob('{0}{1}'.format(prefix, suffix)):
+ if _is_elf(f):
+ return os.path.basename(f)
+
else:

def _findSoname_ldconfig(name):