Skip to content

Add Python 3.11.3 #98

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

Merged
merged 8 commits into from
Apr 26, 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
8 changes: 4 additions & 4 deletions .github/workflows/build-python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ jobs:
include:
- prefix: ""
suffix: ""
version: "3.11.1"
version: "3.11.3"
- prefix: "wasmedge-"
suffix: "-wasmedge"
version: "3.11.1"
version: "3.11.3"
- prefix: "aio-"
suffix: "-aio"
version: "3.11.1"
version: "3.11.3"
- prefix: "aio-wasmedge-"
suffix: "-aio-wasmedge"
version: "3.11.1"
version: "3.11.3"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand Down
49 changes: 44 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,63 @@ oci-python-3.11.1: python/v3.11.1
docker build \
--platform wasm32/wasi \
--build-arg NAME=python-wasm \
--build-arg SUMMARY="CPython built for WASI+Wasmedge, by Wasm Labs" \
--build-arg ARTIFACTS_BASE_DIR=build-output/python/v3.11.1 \
--build-arg SUMMARY="CPython built for WASI, by Wasm Labs" \
--build-arg ARTIFACTS_BASE_DIR=python/v3.11.1 \
--build-arg PYTHON_BINARY=python.wasm \
-t ghcr.io/vmware-labs/python-wasm:3.11.1 \
-f images/python/Dockerfile \
.
build-output

.PHONY: oci-python-3.11.1-wasmedge
oci-python-3.11.1-wasmedge: python/wasmedge-v3.11.1
docker build \
--platform wasm32/wasi \
--build-arg NAME=python-wasm \
--build-arg SUMMARY="CPython built for WASI+WasmEdge, by Wasm Labs" \
--build-arg ARTIFACTS_BASE_DIR=build-output/python/v3.11.1-wasmedge \
--build-arg ARTIFACTS_BASE_DIR=python/v3.11.1-wasmedge \
--build-arg PYTHON_BINARY=python.wasm \
-t ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge \
-f images/python/Dockerfile \
.
build-output

.PHONY: python/wasmedge-v3.11.3
python/wasmedge-v3.11.3:
WLR_BUILD_FLAVOR=wasmedge \
make -C python $(subst python/wasmedge-,,$@)

.PHONY: python/aio-v3.11.3
python/aio-v3.11.3:
WLR_BUILD_FLAVOR=aio \
make -C python $(subst python/aio-,,$@)

.PHONY: python/aio-wasmedge-v3.11.3
python/aio-wasmedge-v3.11.3:
WLR_BUILD_FLAVOR=aio-wasmedge \
make -C python $(subst python/aio-wasmedge-,,$@)

.PHONY: oci-python-3.11.3
oci-python-3.11.3: python/v3.11.3
docker build \
--platform wasi/wasm32 \
--build-arg NAME=python-wasm \
--build-arg SUMMARY="CPython built for WASI, by Wasm Labs" \
--build-arg ARTIFACTS_BASE_DIR=python/v3.11.3 \
--build-arg PYTHON_BINARY=python.wasm \
-t ghcr.io/vmware-labs/python-wasm:3.11.3 \
-f images/python/Dockerfile \
build-output

.PHONY: oci-python-3.11.3-wasmedge
oci-python-3.11.3-wasmedge: python/wasmedge-v3.11.3
docker build \
--platform wasi/wasm32 \
--build-arg NAME=python-wasm \
--build-arg SUMMARY="CPython built for WASI+WasmEdge, by Wasm Labs" \
--build-arg ARTIFACTS_BASE_DIR=python/v3.11.3-wasmedge \
--build-arg PYTHON_BINARY=python.wasm \
-t ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge \
-f images/python/Dockerfile \
build-output

LIBS := \
bzip2 \
Expand Down
3 changes: 3 additions & 0 deletions images/python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ ARG PYTHON_BINARY
COPY ${ARTIFACTS_BASE_DIR}/bin/${PYTHON_BINARY} /python.wasm
COPY ${ARTIFACTS_BASE_DIR}/usr/ /usr

# Shadow the default linux PATH, which is irrelevant for Wasm
ENV PATH=

ENTRYPOINT [ "python.wasm" ]
5 changes: 4 additions & 1 deletion php/examples/wp-nginx-php-fcgi-mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ Step 4 | 2023-04-11T19:16:35+03:00 | Setup Wordpress DB 'WordPress' with user 'a
Step 5 | 2023-04-11T19:16:36+03:00 | Download Wordpress...
Step 6 | 2023-04-11T19:16:37+03:00 | Setup Wordpress...

Go to http://localhost:8080/wp-admin/ and login with user='wp_admin' password='wp_admin_password'!
Go to http://localhost:8080/wp-admin/ and login with the following credentials:

* User: `wp_admin`
* Password: `wp_admin_password`
```

# Under the hood
Expand Down
43 changes: 21 additions & 22 deletions python/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ But that is OK for most scenarios we are interested in, as `python.wasm` is like

### A WASI-compatible runtime

As `python.wasm` is built for WASI you will need to get a compatible WebAssembly runtime, such as [Wasmtime](https://wasmtime.dev/). We also provide an additional binary that will run on [WasmEdge](https://wasmedge.org/), which offers extended socket support on top of a modified WASI API. Since Docker+Wasm uses WasmEdge, this is the binary you will need if you want to build a WASM container image to use with Docker, as explained later in the article.
As `python.wasm` is built for WASI you will need to get a compatible WebAssembly runtime, such as [Wasmtime](https://wasmtime.dev/). We also provide an additional binary that will run on [WasmEdge](https://wasmedge.org/). WasmEdge offers extended socket support on top of a modified WASI API and [is not compliant with the `sock_accept` method](https://github.com/WasmEdge/WasmEdge/issues/2056#issuecomment-1308348306) from WASI Preview1. Since Docker+Wasm uses WasmEdge, this is the binary you will need if you want to build a WASM container image to use with Docker. Note that sockets will not work with the current release.

### Docker+Wasm

Expand All @@ -31,17 +31,17 @@ To try the examples with Docker you will need "Docker Desktop" + Wasm [version 4
If you take a look at the release assets, you will find a few flavors:

- `python-3.11.1.wasm` - WASI compliant interpreter and standard libs wrapped within a single Wasm binary
- `python-3.11.1-wasmedge.wasm` - WASI+WasmEdge compliant interpreter and standard libs wrapped within a single Wasm binary. WasmEdge extends WASI's socket API
- `python-3.11.1.tar.gz` - Both the WASI and WASI+WasmEdge interpreters as separate Wasm binaries. The standard libs are also available separately. All of these within the same archive.
- `python-3.11.1-wasmedge.wasm` - WASI+WasmEdge compliant interpreter and standard libs wrapped within a single Wasm binary.
- `python-3.11.1.tar.gz` - Both the WASI and WASI+WasmEdge interpreters as separate Wasm binaries. The standard libs are also available separately. All of these are within the same archive.

You would want to use the first two versions when convenience is the most important factor. You get a single binary and you don't have to manage how it uses the Python standard library. It all just works.

The last version is useful in more flexible configurations where a few running Wasm binaries may reuse the same set of standard library files.

Additionally, you can use two flavors of a Docker image:

- `ghcr.io/vmware-labs/python-wasm:3.11.1`, which can run on any WASI-compliant containerd runtime
- `ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge`, which can run on the WasmEdge containerd runtime (WasmEdge supports additional socket APIs)
- `ghcr.io/vmware-labs/python-wasm:3.11.3`, which can run on any WASI-compliant containerd runtime
- `ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge`, which can run on the WasmEdge containerd runtime

# Setup

Expand All @@ -60,7 +60,7 @@ curl -sL https://github.com/vmware-labs/webassembly-language-runtimes/releases/d

Now, let's look into what we downloaded. The `python-3.11.1-wasmedge.wasm` and `python-3.11.1.wasm` binaries inside `tmp` can be used as standalone interpreters, as they embed the Python standard libraries.

The ones in `tmp/unpacked/bin`, however, will need the files from `tmp/unpacked/usr/local/lib` to work. These files include a `python311.zip` archive of the standard libraries, a placeholder `python3.11/lib-dynload` and a `python3.11/os.py`. The last two are not strictly necessary but if omitted will cause dependency warnings whenever python runs.
The ones in `tmp/unpacked/bin`, however, will need the files from `tmp/unpacked/usr/local/lib` to work. These files include a `python311.zip` archive of the standard libraries, a placeholder `python3.11/lib-dynload` and a `python3.11/os.py`. The last two are not strictly necessary but if omitted will cause dependency warnings whenever Python runs.

```shell-session
tmp
Expand All @@ -78,7 +78,6 @@ tmp
│   └── [ 39K] os.py
└── [3.9M] python311.zip
```

# First time running python.wasm

Running the packed binaries is as easy as
Expand Down Expand Up @@ -153,7 +152,7 @@ Next, let's assume we have a Python app that has additional dependencies. For ex

To set up the dependencies we will need `pip3` (or `python3 -m pip`) on the development machine, to download and install the necessary dependencies. The most straightforward way of doing this is by running pip with `--target` pointing to the path that is already pre-compiled into the `python.wasm` binary. Namely, `usr/local/lib/python3.11/`

However, we could use this approach only with the version where the python interpreter is not packed with the standard libraries. In this case the host folder with the standard libraries (along with the extra dependencies that we installed) will be pre-opened to the proper location within the Wasm application at runtime.
However, we could use this approach only with the version where the Python interpreter is not packed with the standard libraries. In this case the host folder with the standard libraries (along with the extra dependencies that we installed) will be pre-opened to the proper location within the Wasm application at runtime.

```shell-session
pip3 install emoji -t tmp/unpacked/usr/local/lib/python3.11/
Expand Down Expand Up @@ -187,7 +186,7 @@ He will put on his 👖 and get out of the 🏠 for a walk.

### Using a virtual environment

Any more complex python application is likely to be using virtual environments. In that case, you will have a `venv` folder with all requirements pre-installed. All you need to leverage them is to:
Any more complex Python application is likely to be using virtual environments. In that case, you will have a `venv` folder with all requirements pre-installed. All you need to leverage them is to:

- Make sure this folder is pre-opened when running `python.wasm`
- Add it to the `PYTHONPATH` environment variable
Expand Down Expand Up @@ -234,18 +233,18 @@ wasmedge \

## Running the Docker container

Docker+WASM uses the WasmEdge runtime internally. To leverage it we have packaged the python-3.11.1-wasmedge.wasm binary in a container image available as `ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge`.
Docker+WASM first came with the WasmEdge runtime. To leverage it we have packaged the `python-3.11.3-wasmedge.wasm` binary in a container image available as `ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge`.

In case you need a WASI-compliant container that can run on other containerd runtimes, just use the `ghcr.io/vmware-labs/python-wasm:3.11.1` image.
In case you need a WASI-compliant container that can run on other containerd runtimes, just use the `ghcr.io/vmware-labs/python-wasm:3.11.3` image.

Here is an example of running the Python repl from this container image. As you can see from the output of the interactive session, the container includes only `python.wasm` and the standard libraries from `usr`. No base OS images, no extra environment variables, or any other clutter.

```shell-session
docker run --rm \
-i \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge \
--platform=wasi/wasm32 \
ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge \
-i

Python 3.11.1 (tags/v3.11.1:a7a450f, Feb 17 2023, 11:01:02) ... on wasi
Expand All @@ -268,8 +267,8 @@ You can also run the Docker container to execute a one-liner like this.
```shell-session
docker run --rm \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge \
--platform=wasi/wasm32 \
ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge \
-c "import os; print([k for k in os.environ.keys()])"

['PATH', 'HOSTNAME']
Expand All @@ -283,7 +282,7 @@ We need to do three things

1. Ensure that the `emoji` module installed in the `venv-emoji` folder is mounted in the running `python-wasm` container
2. Ensure that it is also on the `PYTHONPATH` within the running `python-wasm` container
3. Ensure that the python program and its data (in this case `workdir/emojize_text.py` and `workdir/source_text.txt`) are also mounted in the container
3. Ensure that the Python program and its data (in this case `workdir/emojize_text.py` and `workdir/source_text.txt`) are also mounted in the container

A vital piece of knowledge here is that whatever you mount in the running container gets automatically pre-opened by the WasmEdge runtime. Same goes for all environment variables that you pass to the container when you run it.

Expand All @@ -294,8 +293,8 @@ docker run --rm \
-v $PWD/tmp/venv-emoji/lib/python3.11/site-packages:/usr/local/lib/python3.11/site-packages \
-v $PWD/workdir/:/workdir/ \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge \
--platform=wasi/wasm32 \
ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge \
-- \
workdir/emojize_text.py workdir/source_text.txt

Expand All @@ -307,13 +306,13 @@ He will put on his 👖 and get out of the 🏠 for a walk.

## Wrapping it all in a new container image

This way of running your python application with the `python-wasm` container is too cumbersome. Luckily OCI and Docker already offer a way to package everything nicely.
This way of running your Python application with the `python-wasm` container is too cumbersome. Luckily OCI and Docker already offer a way to package everything nicely.

Let's first create a Dockerfile that steps on `python-wasm` to package our emojize_text.py app and its `venv` into a single image.

```shell-session
cat > tmp/Dockerfile.emojize <<EOF
FROM ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge
FROM ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge

COPY tmp/venv-emoji/ /opt/venv-emoji/
COPY workdir/emojize_text.py /opt
Expand All @@ -328,7 +327,7 @@ Building the container is straightforward

```shell-session
docker build \
--platform=wasm32/wasi \
--platform=wasi/wasm32 \
-f tmp/Dockerfile.emojize \
-t emojize.py-wasm .
```
Expand All @@ -339,7 +338,7 @@ And to run it we only have to mount and provide the data file.
docker run --rm \
-v $PWD/workdir/source_text.txt:/source_text.txt \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
--platform=wasi/wasm32 \
emojize.py-wasm \
source_text.txt

Expand Down
14 changes: 7 additions & 7 deletions python/examples/run_all_snippets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ echo -e "\n\n>>>> Running the docker container"

docker run --rm \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge \
--platform=wasi/wasm32 \
ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge \
-c "import os; print([k for k in os.environ.keys()])"


Expand All @@ -87,15 +87,15 @@ docker run --rm \
-v $PWD/tmp/venv-emoji/lib/python3.11/site-packages:/usr/local/lib/python3.11/site-packages \
-v $PWD/workdir/:/workdir/ \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge \
--platform=wasi/wasm32 \
ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge \
-- \
workdir/emojize_text.py workdir/source_text.txt


echo -e "\n\n>>>> Wrapping it all in a new container image"
cat > tmp/Dockerfile.emojize <<EOF
FROM ghcr.io/vmware-labs/python-wasm:3.11.1-wasmedge
FROM ghcr.io/vmware-labs/python-wasm:3.11.3-wasmedge

COPY tmp/venv-emoji/ /opt/venv-emoji/
COPY workdir/emojize_text.py /opt
Expand All @@ -107,15 +107,15 @@ EOF


docker build \
--platform=wasm32/wasi \
--platform=wasi/wasm32 \
-f tmp/Dockerfile.emojize \
-t emojize.py-wasm .


docker run --rm \
-v $PWD/workdir/source_text.txt:/source_text.txt \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasm32/wasi \
--platform=wasi/wasm32 \
emojize.py-wasm \
source_text.txt

Expand Down
4 changes: 2 additions & 2 deletions python/v3.11.1/wlr-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ EOF

logStatus "Generating pkg-config file for libpython3.11.a"
DESCRIPTION="libpython3.11 allows embedding the CPython interpreter"
STACK_LINKER_FLAGS="-Wl,-z,stack-size=524288 -Wl,--stack-first -Wl,--initial-memory=10485760"
EXTRA_LINK_FLAGS="-lpython3.11 -Wl,-z,stack-size=524288 -Wl,--stack-first -Wl,--initial-memory=10485760"

wlr_pkg_config_create_pc_file "libpython3.11" "${WLR_PACKAGE_VERSION}" "${DESCRIPTION}" "${STACK_LINKER_FLAGS}" || exit 1
wlr_pkg_config_create_pc_file "libpython3.11" "${WLR_PACKAGE_VERSION}" "${DESCRIPTION}" "${EXTRA_LINK_FLAGS}" || exit 1

wlr_package_lib || exit 1
fi
Expand Down
20 changes: 20 additions & 0 deletions python/v3.11.3/wlr-build-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bash

if [ "${BASH_SOURCE-}" = "$0" ]; then
echo "You must source this script to add to CFLAGS and LDFLAGS: \$ source $0" >&2
return
fi

source ${WLR_REPO_ROOT}/scripts/build-helpers/wlr_dependencies.sh

wlr_dependencies_add "uuid" "libs/uuid/libuuid-1.0.3" "lib/wasm32-wasi/libuuid.a" \
"https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/libs%2Flibuuid%2F1.0.3%2B20230310-c46e363/libuuid-1.0.3-wasi-sdk-19.0.tar.gz"

wlr_dependencies_add "zlib" "libs/zlib/v1.2.13" "lib/wasm32-wasi/libz.a" \
"https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/libs%2Fzlib%2F1.2.13%2B20230310-c46e363/libz-1.2.13-wasi-sdk-19.0.tar.gz"

wlr_dependencies_add "SQLite" "libs/sqlite/version-3.41.2" "lib/wasm32-wasi/libsqlite3.a" \
"https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/libs%2Fsqlite%2F3.41.2%2B20230329-43f9aea/libsqlite-3.41.2-wasi-sdk-19.0.tar.gz"

wlr_dependencies_add "bzip2" "libs/bzip2/v1.0.8" "lib/wasm32-wasi/libbz2.a" \
"https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/libs%2Fbzip2%2F1.0.8%2B20230425-e1a7579/libbzip2-1.0.8-wasi-sdk-19.0.tar.gz"
Loading