Merge branch 'main' into henryiii/chore/iminuit

This commit is contained in:
Agriya Khetarpal 2024-08-14 19:12:57 +05:30 committed by GitHub
commit e1542f4334
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
328 changed files with 27989 additions and 14287 deletions

View File

@ -17,9 +17,6 @@ defaults: &defaults
# Disable the compression of wheels, so they are better compressed by the CDN
PYODIDE_ZIP_COMPRESSION_LEVEL: 0
orbs:
macos: circleci/macos@2.3.6
jobs:
build-core:
parameters:
@ -108,7 +105,7 @@ jobs:
name: Zip build directory
command: |
tar cjf pyodide.tar.gz dist
tar cjf pyodide-core.tar.gz dist/pyodide{.js,.mjs,.asm.js,.asm.wasm} dist/{package,pyodide-lock}.json dist/python_stdlib.zip
tar cjf pyodide-core.tar.gz dist/pyodide{.js,.mjs,.asm.js,.asm.wasm} dist/*.d.ts dist/{package,pyodide-lock}.json dist/python_stdlib.zip
tar cjf pyodide-static-libs.tar.gz -C cpython/installs .
- store_artifacts:
@ -166,7 +163,7 @@ jobs:
name: Zip build directory
command: |
tar cjf pyodide.tar.gz dist
tar cjf pyodide-core.tar.gz dist/pyodide{.js,.mjs,.asm.js,.asm.wasm} dist/{package,pyodide-lock}.json dist/python_stdlib.zip
tar cjf pyodide-core.tar.gz dist/pyodide{.js,.mjs,.asm.js,.asm.wasm} dist/*.d.ts dist/{package,pyodide-lock}.json dist/python_stdlib.zip
tar cjf build-logs.tar.gz packages/build-logs
- run:
@ -229,8 +226,8 @@ jobs:
- run:
name: create xbuild environment
command: |
pip install -e ./pyodide-build
pyodide xbuildenv create .
make pyodide_build
python tools/create_xbuildenv.py .
- run:
name: Zip xbuild environment
@ -257,12 +254,12 @@ jobs:
name: Install requirements
command: |
pip install -r requirements.txt
pip install -e ./pyodide-build
make pyodide_build
- run:
name: Py-compile packages
command: |
pyodide py-compile --compression-level 0 dist/
make py-compile
rm -f dist/snapshot.bin
make dist/snapshot.bin
@ -303,7 +300,7 @@ jobs:
make npm-link
mkdir test-results
pip install -r requirements.txt
pip install -e ./pyodide-build
make pyodide_build
if [ -z "<< parameters.cache-dir >>" ]; then
export CACHE_DIR=".test_cache/.pytest_cache_$(echo $RANDOM | md5sum | head -c 10)"
else
@ -322,66 +319,6 @@ jobs:
- store_test_results:
path: test-results
test-main-macos:
parameters:
test-params:
description: The tests to run.
type: string
cache-dir:
description: pytest-cache-dir.
type: string
default: ""
resource_class: macos.x86.medium.gen2
macos:
xcode: 15.0.0
working_directory: ~/repo
steps:
- attach_workspace:
at: .
# The standard way of enabling safaridriver no longer works for Safari 14+
# https://blog.bytesguy.com/enabling-remote-automation-in-safari-14
- macos/add-safari-permissions
- run:
name: install miniforge
command: |
curl -L -O https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-x86_64.sh
bash Miniforge3-MacOSX-x86_64.sh -b && rm -f Miniforge3-MacOSX-x86_64.sh
~/miniforge3/bin/conda create -n pyodide python=3.12 -y
- run:
name: install dependencies
command: |
export PATH="$HOME/miniforge3/bin:$PATH"
conda create -n pyodide python=3.12 -y
source activate pyodide
python -m pip install -r requirements.txt
pip install -e ./pyodide-build
- run:
name: show safari version
command: |
safari_version=$(defaults read /Applications/Safari.app/Contents/Info.plist CFBundleShortVersionString)
echo "Safari Version: $safari_version"
- run:
name: test safari
command: |
export PATH="$HOME/miniforge3/bin:$PATH"
source activate pyodide
mkdir test-results
if [ -z "<< parameters.cache-dir >>" ]; then
export CACHE_DIR=".test_cache/.pytest_cache_$(echo $RANDOM | md5sum | head -c 10)"
else
export CACHE_DIR=".test_cache/<< parameters.cache-dir >>"
fi
echo "pytest cache dir: $CACHE_DIR"
tools/pytest_wrapper.py \
--junitxml=test-results/junit.xml \
--verbose \
--durations 50 \
<< parameters.test-params >> \
-o cache_dir=$CACHE_DIR
- store_test_results:
path: test-results
benchmark-stack-size:
<<: *defaults
steps:
@ -442,6 +379,7 @@ jobs:
export PYODIDE_ROOT=$(pwd)
echo $PYODIDE_ROOT
source pyodide_env.sh
make pyodide_build
cd ~
mkdir test
cd test
@ -450,7 +388,7 @@ jobs:
python -m venv .venv-host
source .venv-host/bin/activate
pip install $PYODIDE_ROOT/pyodide-build
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
@ -507,7 +445,7 @@ jobs:
- run:
name: Install requirements
command: |
python3 -m pip install -e "./pyodide-build[deploy]"
python3 -m pip install -r requirements-deploy.txt
wget https://github.com/tcnksm/ghr/releases/download/v0.16.2/ghr_v0.16.2_linux_amd64.tar.gz
tar xzf ghr_v0.16.2_linux_amd64.tar.gz
@ -516,13 +454,14 @@ jobs:
- run:
name: Deploy Github Releases
command: |
make clean-dist-dir
mkdir -p /tmp/ghr/dist
cp -r dist /tmp/ghr/pyodide
cp -r xbuildenv /tmp/ghr/xbuildenv
cp -r cpython/installs /tmp/ghr/static-libraries
cd /tmp/ghr
tar cjf dist/pyodide-${CIRCLE_TAG}.tar.bz2 pyodide/
tar cjf dist/pyodide-core-${CIRCLE_TAG}.tar.bz2 pyodide/pyodide{.js,.mjs,.asm.js,.asm.wasm} pyodide/{package,pyodide-lock}.json pyodide/python_stdlib.zip
tar cjf dist/pyodide-core-${CIRCLE_TAG}.tar.bz2 pyodide/pyodide{.js,.mjs,.asm.js,.asm.wasm} pyodide/*.d.ts pyodide/{package,pyodide-lock}.json pyodide/python_stdlib.zip
tar cjf dist/xbuildenv-${CIRCLE_TAG}.tar.bz2 xbuildenv/
tar cjf dist/static-libraries-${CIRCLE_TAG}.tar.bz2 static-libraries/
@ -582,7 +521,7 @@ jobs:
- run:
name: Install requirements
command: |
python3 -m pip install -e "./pyodide-build[deploy]"
python3 -m pip install -r requirements-deploy.txt
- run:
name: Set PYODIDE_BASE_URL
command: |
@ -609,6 +548,7 @@ jobs:
# Unlike the release version, we upload the dev version to S3 not to GitHub.
name: Deploy release files to S3
command: |
make clean-dist-dir
mkdir -p /tmp/ghr/dist
cp -r dist /tmp/ghr/pyodide
cp -r xbuildenv /tmp/ghr/xbuildenv
@ -737,7 +677,7 @@ workflows:
- test-main:
name: test-core-node-nodylink
test-params: --runtime=node-no-host -m 'not requires_dynamic_linking' -k "not cmdline_runner" src packages/micropip packages/fpcast-test packages/sharedlib-test-py/ packages/cpp-exceptions-test/ pyodide-build/pyodide_build/tests
test-params: --runtime=node-no-host -m 'not requires_dynamic_linking' -k "not cmdline_runner" src packages/micropip packages/fpcast-test packages/sharedlib-test-py/ packages/cpp-exceptions-test/
requires:
- build-core-nodylink
filters:
@ -764,16 +704,7 @@ workflows:
- test-main:
name: test-core-node
test-params: --runtime=node-no-host src packages/micropip packages/fpcast-test packages/sharedlib-test-py/ packages/cpp-exceptions-test/ pyodide-build/pyodide_build/tests
requires:
- build-core
filters:
tags:
only: /.*/
- test-main-macos:
name: test-core-safari
test-params: --runtime=safari-no-host src packages/micropip packages/fpcast-test packages/sharedlib-test-py/ packages/cpp-exceptions-test/
test-params: --runtime=node-no-host src packages/micropip packages/fpcast-test packages/sharedlib-test-py/ packages/cpp-exceptions-test/
requires:
- build-core
filters:
@ -876,32 +807,6 @@ workflows:
tags:
only: /.*/
- test-main-macos:
name: test-packages-safari-no-numpy-dependents
test-params: --runtime=safari-no-host -k "not webworker" packages/*/test*.py
cache-dir: .pytest_cache_safari
requires:
- build-packages-no-numpy-dependents
filters:
tags:
only: /.*/
post-steps:
- persist_to_workspace:
root: .
paths:
- ./.test_cache
- test-main-macos:
name: test-packages-safari
test-params: --runtime=safari-no-host -k "not webworker" packages/*/test*.py --skip-passed
cache-dir: .pytest_cache_safari
requires:
- test-packages-safari-no-numpy-dependents
- build-packages
filters:
tags:
only: /.*/
- test-js:
requires:
- build-core

View File

@ -29,7 +29,7 @@ ln -sf "$PYODIDE_RECIPE_BUILD_DIR" packages/.build || echo "Note: Could not crea
conda run -n pyodide-env --live-stream pip install -r requirements.txt
# https://pyodide.org/en/stable/development/new-packages.html#prerequisites
conda run -n pyodide-env --live-stream pip install -e ./pyodide-build
make pyodide_build
# Building emsdk and cpython takes a few minutes to run, so we do not run it here.
#

View File

@ -3,14 +3,14 @@
# Do not keep running on errors
set -e
# https://pyodide.org/en/stable/development/new-packages.html#prerequisites
pip install -e ./pyodide-build
export PYODIDE_RECIPE_BUILD_DIR=/tmp/pyodide-build
mkdir -p "$PYODIDE_RECIPE_BUILD_DIR"
echo "export PYODIDE_RECIPE_BUILD_DIR=$PYODIDE_RECIPE_BUILD_DIR" >> ~/.bashrc
ln -sf "$PYODIDE_RECIPE_BUILD_DIR" packages/.build || echo "Note: Could not create convenience symlink packages/.build"
# https://pyodide.org/en/stable/development/new-packages.html#prerequisites
make pyodide_build
# Building emsdk and cpython takes a few minutes to run, so we do not run it here.
#
# make -C emsdk

View File

@ -3,6 +3,6 @@ contact_links:
- name: Ask a Question
url: https://github.com/pyodide/pyodide/discussions
about: Ask and answer Pyodide related questions
- name: 💬 Gitter
url: https://gitter.im/pyodide/community
- name: 💬 Discord
url: https://discord.gg/cRxMCG5kJQ
about: Chat with Pyodide community

View File

@ -6,10 +6,22 @@ labels: new package request
assignees: ""
---
<!-- Important Note: You can install pure python package wheels through micropip.install(...) -->
<!--
Important Note:
Opening a new package request doesn't mean that Pyodide maintainers will look into it immediately.
In most cases, the maintainer will have no idea about the package you're asking for, and you're probably the most knowledgeable person about it.
Therefore, a way to speed up your progress is to read the documentation, try building the package yourself, and report any issues you encounter.
-->
## 🐍 Package Request
- Package Name and Version <!-- (e.g. pandas / latest) -->:
- Package URL <!-- (e.g. github link, PyPI link) -->:
- Package Dependencies that needs to be resolved first:
## Checklists
- [ ] I have tried to install the package using `micropip.install(...)` and encountered the issue.
- [ ] I have read the [documentation](https://pyodide.org/en/stable/development/building-and-testing-packages.html) and tried building the package myself.

View File

@ -4,37 +4,6 @@ on:
release:
types: [published]
jobs:
deploy-pyodide-build-pypi:
runs-on: ubuntu-latest
environment: PyPi
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: python -m pip install build twine
- name: Build wheel
run: |
cd pyodide-build/
python -m build .
- name: Check wheel
run: |
twine check pyodide-build/dist/*
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: pyodide-build/dist/
deploy-pyodide-py-pypi:
runs-on: ubuntu-latest
environment: PyPi

View File

@ -45,7 +45,7 @@ jobs:
echo "::set-output name=tag::$TAG"
- name: Build and push Docker image to Docker Hub
id: build
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
file: ./Dockerfile
push: true
@ -83,7 +83,7 @@ jobs:
echo "::set-output name=tag::$TAG"
- name: Build and push Docker image to ${{ env.GHCR_REGISTRY }}
id: build
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
file: ./Dockerfile
push: true

View File

@ -19,22 +19,20 @@ jobs:
id: get_python_version
run: |
echo "PYVERSION=$(git grep 'export PYVERSION ?=' Makefile.envs | cut -d' ' -f4)" >> "$GITHUB_OUTPUT"
test-python:
runs-on: ubuntu-latest
needs: get_python_version
steps:
- uses: actions/checkout@v4
- name: Setup Python ${{ needs.get_python_version.outputs.PYVERSION }}
uses: actions/setup-python@v5
- uses: actions/setup-python@v5
with:
python-version: ${{ needs.get_python_version.outputs.PYVERSION }}
- name: Install requirements
shell: bash -l {0}
run: |
mkdir test-results
cd pyodide-build && python3 -m pip install -e ".[test,deploy]" && cd ..
python3 -m pip install pytest-cov hypothesis pytz
python3 -m pip install -r requirements.txt -r requirements-deploy.txt
make pyodide_build
- name: Run tests
shell: bash -l {0}
run: |
@ -43,7 +41,7 @@ jobs:
--verbose \
--runtime=host \
--cov=pyodide_build --cov=pyodide \
src pyodide-build packages/micropip/ packages/_tests tools/
src packages/_tests tools/
- uses: codecov/codecov-action@v4
with:
fail_ci_if_error: false
@ -52,8 +50,13 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14]
include:
- os: ubuntu-latest
pyodide_packages: "tag:core,numpy${{ needs.test-scipy-trigger.outputs.test-scipy == 'true' && ',scipy' || '' }}"
- os: macos-14
pyodide_packages: "tag:core,numpy"
runs-on: ${{ matrix.os }}
needs: [test-scipy-trigger]
env:
EMSDK_NUM_CORES: 3
EMCC_CORES: 3
@ -124,13 +127,13 @@ jobs:
make -C cpython
ccache -s
- name: build Pyodide core + numpy
- name: build Pyodide with packages ${{ matrix.pyodide_packages }}
shell: bash -l {0}
run: |
# This is necessary to use the ccache from emsdk
source pyodide_env.sh
ccache -z
PYODIDE_PACKAGES="tag:core,numpy" make
PYODIDE_PACKAGES=${{ matrix.pyodide_packages }} make
ccache -s
- name: check-size
@ -157,10 +160,9 @@ jobs:
strategy:
fail-fast: false
matrix:
# os: [ubuntu-latest, macos-latest] # FIXME: macos + playwright is very unstable.
os: [ubuntu-latest]
runner: [playwright]
browser: [chrome]
os: [macos-14]
runner: [selenium]
browser: [safari]
steps:
- uses: actions/checkout@v4
@ -180,9 +182,13 @@ jobs:
- name: install test requirements
shell: bash -l {0}
run: |
pip install -r requirements.txt
pip install -e ./pyodide-build
python -m playwright install
pip install -r requirements.txt -r requirements-deploy.txt
make pyodide_build
- uses: pyodide/pyodide-actions/install-browser@v1
with:
runner: ${{ matrix.runner }}
browser: ${{ matrix.browser }}
- name: run core tests
env:
@ -192,7 +198,7 @@ jobs:
run: |
ls -lh
ls -lh dist/
tools/pytest_wrapper.py src packages/micropip/ \
tools/pytest_wrapper.py src packages/micropip/ tools/ \
-v \
-k "not webworker" \
--runtime="${BROWSER}-no-host" \
@ -222,6 +228,84 @@ jobs:
paths: "test-results/*.xml"
if: always()
test-scipy-trigger:
name: test-scipy-trigger
runs-on: ubuntu-latest
outputs:
test-scipy: ${{ steps.check-build-trigger.outputs.trigger }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- id: check-build-trigger
name: Check build trigger
run: bash tools/check_build_trigger.sh
test-scipy:
runs-on: ${{ matrix.os }}
needs: [test-scipy-trigger, build-core]
if: needs.test-scipy-trigger.outputs.test-scipy
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: core-build-${{ runner.os }}
path: ./dist/
- name: run scipy tests inside node
shell: bash -l {0}
run: |
npm install pyodide
cp -f dist/* node_modules/pyodide
# This uses conftest.py on the current working directory to
# skip/xfail tests in scipy
cd packages/scipy
# XXX for some unknown reason adding a conftest.py in the repo throws off the
# other tests trying to import from conftest they find the scipy one ...
mv scipy-conftest.py conftest.py
node scipy-pytest.js --pyargs scipy -m 'not slow' -ra -v
test-bun:
runs-on: ${{ matrix.os }}
needs: [build-core]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: core-build-${{ runner.os }}
path: ./dist/
- uses: oven-sh/setup-bun@v2
- name: install test requirements
working-directory: src/test-bun
run: |
bun --version
bun install
- name: run bun tests
working-directory: src/test-bun
run: bun smoke-test.js
test-deno:
runs-on: ${{ matrix.os }}

View File

@ -23,17 +23,17 @@ jobs:
- name: Install pyodide-build
run: |
python -m pip install --upgrade pip
pip install ./pyodide-build
make pyodide_build
- name: Get version number (release)
if: github.event_name == 'release'
run: |
echo "VERSION=${{ github.event.release.name }}" > $GITHUB_ENV
echo "VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
- name: Get version number (workflow_dispatch)
if: github.event_name == 'workflow_dispatch'
run: |
echo "VERSION=${{ github.event.inputs.version }}" > $GITHUB_ENV
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Update cross-build metadata file
working-directory: tools
@ -44,10 +44,10 @@ jobs:
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update cross-build metadata file for version ${{ env.VERSION }}
commit-message: Update cross-build metadata file for version ${{ env.VERSION }} [skip ci]
title: Update cross-build metadata file for version ${{ env.VERSION }}
body: |
This PR updates the cross-build metadata file.
This PR updates the cross-build metadata file for version ${{ env.VERSION }}
branch: update-cross-build-metadata-${{ env.VERSION }}
base: main
branch-suffix: timestamp

View File

@ -17,14 +17,14 @@ repos:
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.3.5"
rev: "v0.5.0"
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v18.1.3"
rev: "v18.1.8"
hooks:
- id: clang-format
types_or: [c++, c, cuda]
@ -45,18 +45,18 @@ repos:
exclude: ^src/templates/python$
- repo: https://github.com/codespell-project/codespell
rev: "v2.2.6"
rev: "v2.3.0"
hooks:
- id: codespell
args:
[
"--ignore-words-list",
"ags,aray,asend,ba,classs,crate,falsy,feld,inflight,lits,nd,slowy,te,oint",
"ags,aray,asend,ba,crate,falsy,feld,inflight,lits,nd,slowy,te,oint,conveniant,atmost",
]
exclude: ^(benchmark/benchmarks/pystone_benchmarks/pystone\.py|src/js/package-lock\.json)$
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.9.0"
rev: "v1.11.0"
hooks:
- id: mypy
files: ^(packages/.*/src|src|pyodide-build/pyodide_build)
@ -81,7 +81,7 @@ repos:
- id: mypy
name: mypy-tests
args: [--ignore-missing-imports]
files: ^(packages/|docs|/conftest.py|src/tests|pyodide-build/pyodide_build/tests)
files: ^(packages/|docs|/conftest.py|src/tests)
exclude: (^packages/.*/setup.py|/src|^packages/aiohttp/aiohttp_patch.py$)
additional_dependencies: *mypy-deps

View File

@ -8,7 +8,9 @@ version: 2
sphinx:
configuration: docs/conf.py
formats: all
formats:
- htmlzip
# we can't build epub / pdf
python:
install:

View File

@ -28,12 +28,11 @@ RUN wget https://mirrors.sarata.com/gnu/autoconf/autoconf-2.71.tar.xz \
&& rm -rf autoconf-2.71
ADD requirements.txt docs/requirements-doc.txt /
ADD pyodide-build /pyodide-build
WORKDIR /
RUN pip3 --no-cache-dir install -r requirements.txt \
&& pip3 --no-cache-dir install -r requirements-doc.txt \
&& rm -rf requirements.txt requirements-doc.txt pyodide-build
&& rm -rf requirements.txt requirements-doc.txt
# Get Chrome and Firefox (borrowed from https://github.com/SeleniumHQ/docker-selenium)

View File

@ -158,14 +158,22 @@ node_modules/.installed : src/js/package.json src/js/package-lock.json
ln -sfn src/js/node_modules/ node_modules
touch $@
dist/pyodide.js src/js/generated/_pyodide.out.js: \
src/js/generated/_pyodide.out.js: \
src/js/*.ts \
src/js/*.js \
src/js/common/* \
src/js/vendor/* \
src/js/generated/pyproxy.ts \
src/js/generated/python2js_buffer.js \
src/js/generated/js2python.js \
node_modules/.installed
cd src/js && npm run build && cd -
cd src/js && npm run build-inner && cd -
dist/pyodide.js: \
src/js/pyodide.ts \
src/js/compat.ts \
src/js/emscripten-settings.ts \
src/js/version.ts
cd src/js && npm run build
src/core/stack_switching/stack_switching.out.js : src/core/stack_switching/*.mjs
node src/core/stack_switching/esbuild.config.mjs
@ -217,10 +225,10 @@ $(eval $(call preprocess-js,pyproxy.ts))
$(eval $(call preprocess-js,python2js_buffer.js))
$(eval $(call preprocess-js,js2python.js))
.PHONY: pyodide_build
pyodide_build:
@echo "Ensuring editable pyodide-build is installed"
./tools/check_editable_pyodide_build.py || $(HOSTPYTHON) -m pip install -e ./pyodide-build
@echo "Ensuring required pyodide-build version is installed"
./tools/check_and_install_pyodide_build.py "$(PYODIDE_BUILD_COMMIT)" --repo "$(PYODIDE_BUILD_REPO)"
@which pyodide >/dev/null
@ -261,6 +269,23 @@ dist/module_webworker_dev.js: src/templates/module_webworker.js
dist/webworker_dev.js: src/templates/webworker.js
cp $< $@
# Prepare the dist directory for the release by removing unneeded files
.PHONY: clean-dist-dir
clean-dist-dir:
# Remove snapshot files
rm dist/makesnap.mjs
rm dist/snapshot.bin
rm dist/module_test.html dist/test.html
# TODO: Remove webworker.js too? Would require updating the docs I think.
rm dist/module_webworker_dev.js dist/webworker_dev.js
# TODO: Source maps aren't useful outside of debug builds I don't think. But
# removing them adds "missing sourcemap" warnings to JS console. We should
# not generate them in the first place?
# rm dist/*.map
.PHONY: lint
lint:
pre-commit run -a --show-diff-on-failure
@ -334,3 +359,7 @@ check-emcc: emsdk/emsdk/.complete
debug :
EXTRA_CFLAGS+=" -D DEBUG_F" \
make
.PHONY: py-compile
py-compile:
pyodide py-compile --compression-level "$(PYODIDE_ZIP_COMPRESSION_LEVEL)" --exclude "$(PYCOMPILE_EXCLUDE_FILES)" dist/

View File

@ -1,9 +1,19 @@
export PYVERSION ?= 3.12.1
export PYODIDE_EMSCRIPTEN_VERSION ?= 3.1.58
export PYODIDE_VERSION ?= 0.26.0.dev0
export PYODIDE_VERSION ?= 0.27.0.dev0
export PYODIDE_ABI_VERSION ?= 2024_0
export PYTHON_ARCHIVE_SHA256=d01ec6a33bc10009b09c17da95cc2759af5a580a7316b3a446eb4190e13f97b2
# Update the following variables when you want to update the version of the
# pyodide-build version used in the build process. If you want to make breaking
# changes in pyodide-build, it is also useful to change the repository URL
# to your fork to test the changes are working as expected.
# v0.27.3
export PYODIDE_BUILD_COMMIT=fac0109aa2acf14469320b049d710dd42639bf94
export PYODIDE_BUILD_REPO=https://github.com/pyodide/pyodide-build
ifdef CPYTHON_DEBUG
export CPYTHON_ABI_FLAGS=d
endif
@ -77,6 +87,12 @@ export PYZIP_EXCLUDE_FILES=\
export PYZIP_JS_STUBS=\
webbrowser.py
export PYCOMPILE_EXCLUDE_FILES=\
RobotRaconteur- \
astropy- \
opencv_python- \
test-
export DBGFLAGS_NODEBUG=-g0
export DBGFLAGS_WASMDEBUG=-g2
export DBGFLAGS_SOURCEMAPDEBUG=-g3
@ -132,7 +148,6 @@ export MAIN_MODULE_LDFLAGS= $(LDFLAGS_BASE) \
-s EXPORT_EXCEPTION_HANDLING_HELPERS \
-s EXCEPTION_CATCHING_ALLOWED=['we only want to allow exception handling in side modules'] \
-sEXPORTED_RUNTIME_METHODS='wasmTable,ERRNO_CODES' \
-s DEMANGLE_SUPPORT=1 \
-s USE_ZLIB \
-s USE_BZIP2 \
-s FORCE_FILESYSTEM=1 \
@ -160,6 +175,7 @@ export MAIN_MODULE_LDFLAGS= $(LDFLAGS_BASE) \
-lGL \
-legl.js \
-lwebgl.js \
-lhtml5.js \
-lhtml5_webgl.js \
-lsdl.js \
-sGL_WORKAROUND_SAFARI_GETCONTEXT_BUG=0

View File

@ -5,7 +5,7 @@
</div>
[![NPM Latest Release](https://img.shields.io/npm/v/pyodide)](https://www.npmjs.com/package/pyodide)
[![PyPI Latest Release](https://img.shields.io/pypi/v/pyodide-build.svg)](https://pypi.org/project/pyodide-build/)
[![PyPI Latest Release](https://img.shields.io/pypi/v/pyodide-py.svg)](https://pypi.org/project/pyodide-py/)
[![Build Status](https://circleci.com/gh/pyodide/pyodide.png)](https://circleci.com/gh/pyodide/pyodide)
[![Documentation Status](https://readthedocs.org/projects/pyodide/badge/?version=stable)](https://pyodide.readthedocs.io/?badge=stable)
@ -77,9 +77,9 @@ governance](https://pyodide.org/en/stable/project/governance.html).
- Blog: [blog.pyodide.org](https://blog.pyodide.org/)
- Mailing list: [mail.python.org/mailman3/lists/pyodide.python.org/](https://mail.python.org/mailman3/lists/pyodide.python.org/)
- Gitter: [gitter.im/pyodide/community](https://gitter.im/pyodide/community)
- Twitter: [twitter.com/pyodide](https://twitter.com/pyodide)
- Stack Overflow: [stackoverflow.com/questions/tagged/pyodide](https://stackoverflow.com/questions/tagged/pyodide)
- Discord: [Pyodide Discord](https://discord.gg/cRxMCG5kJQ)
## License

View File

@ -14,43 +14,83 @@ import pytest
ROOT_PATH = pathlib.Path(__file__).parents[0].resolve()
DIST_PATH = ROOT_PATH / "dist"
sys.path.append(str(ROOT_PATH / "pyodide-build"))
sys.path.append(str(ROOT_PATH / "src" / "py"))
import pytest_pyodide.runner
# importing this fixture has a side effect of making the safari webdriver reused during the session
from pytest_pyodide import get_global_config
from pytest_pyodide.runner import use_global_safari_service # noqa: F401
from pytest_pyodide.utils import package_is_built as _package_is_built
os.environ["IN_PYTEST"] = "1"
pytest_pyodide.runner.CHROME_FLAGS.extend(
[
"--enable-features=WebAssemblyExperimentalJSPI",
"--enable-experimental-webassembly-features",
]
)
pytest_pyodide.runner.NODE_FLAGS.extend(["--experimental-wasm-stack-switching"])
# There are a bunch of global objects that occasionally enter the hiwire cache
# but never leave. The refcount checks get angry about them if they aren't preloaded.
# We need to go through and touch them all once to keep everything okay.
pytest_pyodide.runner.INITIALIZE_SCRIPT = """
pyodide.globals.get;
pyodide.runPython("import pyodide_js._api; del pyodide_js");
pyodide._api.importlib.invalidate_caches;
pyodide._api.package_loader.unpack_buffer;
pyodide._api.package_loader.get_dynlibs;
pyodide._api.pyodide_code.eval_code;
pyodide._api.pyodide_code.eval_code_async;
pyodide._api.pyodide_code.relaxed_call
pyodide._api.pyodide_code.find_imports;
pyodide._api.pyodide_ffi.register_js_module;
pyodide._api.pyodide_ffi.unregister_js_module;
pyodide.pyimport("pyodide.ffi.wrappers").destroy();
pyodide.pyimport("pyodide.http").destroy();
pyodide.pyimport("pyodide_js._api");
"""
def set_configs():
pytest_pyodide_config = get_global_config()
pytest_pyodide_config.set_flags(
"chrome",
pytest_pyodide_config.get_flags("chrome")
+ [
"--enable-features=WebAssemblyExperimentalJSPI",
"--enable-experimental-webassembly-features",
],
)
pytest_pyodide_config.set_flags(
"node",
pytest_pyodide_config.get_flags("node")
+ ["--experimental-wasm-stack-switching"],
)
# There are a bunch of global objects that occasionally enter the hiwire cache
# but never leave. The refcount checks get angry about them if they aren't preloaded.
# We need to go through and touch them all once to keep everything okay.
pytest_pyodide_config.set_initialize_script("""
pyodide.globals.get;
pyodide.runPython("import pyodide_js._api.config; del pyodide_js");
pyodide._api.importlib.invalidate_caches;
pyodide._api.package_loader.get_install_dir;
pyodide._api.package_loader.unpack_buffer;
pyodide._api.package_loader.get_dynlibs;
pyodide._api.pyodide_code.eval_code;
pyodide._api.pyodide_code.eval_code_async;
pyodide._api.pyodide_code.relaxed_call
pyodide._api.pyodide_code.find_imports;
pyodide._api.pyodide_ffi.register_js_module;
pyodide._api.pyodide_ffi.unregister_js_module;
pyodide.pyimport("pyodide.ffi.wrappers").destroy();
pyodide.pyimport("pyodide.http").destroy();
pyodide.pyimport("pyodide_js._api");
""")
pytest_pyodide_config.set_load_pyodide_script(
"chrome",
"""
let pyodide = await loadPyodide({
fullStdLib: false,
jsglobals : self,
enableRunUntilComplete: true,
});
""",
)
pytest_pyodide_config.set_load_pyodide_script(
"node",
"""
const {readFileSync} = require("fs");
let snap = readFileSync("snapshot.bin");
snap = new Uint8Array(snap.buffer);
let pyodide = await loadPyodide({
fullStdLib: false,
jsglobals: self,
_loadSnapshot: snap,
enableRunUntilComplete: true,
});
""",
)
set_configs()
only_node = pytest.mark.xfail_browsers(
chrome="node only", firefox="node only", safari="node only"
@ -254,6 +294,9 @@ def extra_checks_test_wrapper(browser, trace_hiwire_refs, trace_pyproxies, item)
with contextlib.suppress(Exception) if err else contextlib.nullcontext():
browser.disable_pyproxy_tracing()
browser.restore_state()
# The method_call_singleton holds onto the last called JS method,
# clear it so we don't fail refcount check
browser.run_js("pyodide._module._clear_method_call_singleton();")
if browser.force_test_fail:
raise Exception("Test failure explicitly requested but no error was raised.")
@ -297,23 +340,3 @@ def strip_assertions_stderr(messages: Sequence[str]) -> list[str]:
continue
res.append(msg)
return res
from pytest_pyodide.runner import NodeRunner
def patched_load_pyodide(self):
self.run_js(
"""
const {readFileSync} = require("fs");
let snap = readFileSync("snapshot.bin");
snap = new Uint8Array(snap.buffer);
let pyodide = await loadPyodide({ fullStdLib: false, jsglobals : self, _loadSnapshot: snap });
self.pyodide = pyodide;
globalThis.pyodide = pyodide;
pyodide._api.inTestHoist = true; // improve some error messages for tests
"""
)
NodeRunner.load_pyodide = patched_load_pyodide

View File

@ -48,6 +48,7 @@ def adjust_sysconfig(config_vars: dict[str, str]):
CXX="c++",
LDCXXSHARED="c++",
)
config_vars["PYODIDE_ABI_VERSION"] = os.environ["PYODIDE_ABI_VERSION"]
for [key, val] in config_vars.items():
if not isinstance(val, str):
continue

View File

@ -1,7 +1,7 @@
From d32ad19aa3e0c8b5524c999219d294d235a47602 Mon Sep 17 00:00:00 2001
From 3fe0bfb78022df996fb88da1791d1c8410c07610 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Sun, 17 Jul 2022 14:40:39 +0100
Subject: [PATCH 1/6] Public pymain_run_python
Subject: [PATCH 1/7] Public pymain_run_python
Discussion here:
https://discuss.python.org/t/unstable-api-for-pymain-run-python-run-python-cli-but-dont-finalize-interpreter/44675
@ -10,7 +10,7 @@ https://discuss.python.org/t/unstable-api-for-pymain-run-python-run-python-cli-b
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Modules/main.c b/Modules/main.c
index 1b189b4561..8c082f3b65 100644
index 1b189b45616..8c082f3b65e 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -546,7 +546,7 @@ pymain_repl(PyConfig *config, int *exitcode)
@ -23,5 +23,5 @@ index 1b189b4561..8c082f3b65 100644
{
PyObject *main_importer_path = NULL;
--
2.25.1
2.34.1

View File

@ -1,7 +1,7 @@
From 55c6694ccc7cd62f2aecbc15f72df89e437adf57 Mon Sep 17 00:00:00 2001
From a68778f7d8d2fa121ff4cab402f2a862e5cb1afe Mon Sep 17 00:00:00 2001
From: ryanking13 <def6488@gmail.com>
Date: Fri, 2 Dec 2022 11:36:44 +0000
Subject: [PATCH 3/6] Add emscripten platform support to
Subject: [PATCH 2/7] Add emscripten platform support to
ctypes.util.find_library
---
@ -9,7 +9,7 @@ Subject: [PATCH 3/6] Add emscripten platform support to
1 file changed, 24 insertions(+)
diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index 0c2510e161..c8875ec009 100644
index 0c2510e1619..c8875ec0099 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -80,6 +80,30 @@ def find_library(name):
@ -44,5 +44,5 @@ index 0c2510e161..c8875ec009 100644
# AIX has two styles of storing shared libraries
# GNU auto_tools refer to these as svr4 and aix
--
2.25.1
2.34.1

View File

@ -1,17 +1,16 @@
From 3228232e38b3aee5023231b518750d8de38a9de7 Mon Sep 17 00:00:00 2001
From cfda6ef57f6c49a3bd8a14ebb989c9e2222f10a6 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Mon, 19 Dec 2022 09:09:14 -0800
Subject: [PATCH 4/6] Allow multiprocessing.connection top level import
Subject: [PATCH 3/7] Allow multiprocessing.connection top level import
Upstream PR:
https://github.com/python/cpython/pull/114808
---
Lib/multiprocessing/connection.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py
index dbbf106f68..e92edf6c30 100644
index dbbf106f680..e92edf6c302 100644
--- a/Lib/multiprocessing/connection.py
+++ b/Lib/multiprocessing/connection.py
@@ -19,7 +19,10 @@
@ -27,5 +26,5 @@ index dbbf106f68..e92edf6c30 100644
from . import util
--
2.25.1
2.34.1

View File

@ -1,7 +1,7 @@
From ed163b0cf72c4cae56274db02b44b7f7bc8e6d2d Mon Sep 17 00:00:00 2001
From a3f1217f7527907c237085c5e900c950c7d2603a Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Wed, 28 Jun 2023 10:46:19 -0700
Subject: [PATCH 5/6] Make Emscripten trampolines work with JSPI
Subject: [PATCH 4/7] Make Emscripten trampolines work with JSPI
There is a WIP proposal to enable webassembly stack switching which have been
implemented in v8:
@ -25,7 +25,6 @@ was negatively affected.
Upstreamed here:
https://github.com/python/cpython/pull/106219
---
.../internal/pycore_emscripten_trampoline.h | 67 +++++++++++++++++
Include/internal/pycore_object.h | 28 +------
@ -43,7 +42,7 @@ https://github.com/python/cpython/pull/106219
diff --git a/Include/internal/pycore_emscripten_trampoline.h b/Include/internal/pycore_emscripten_trampoline.h
new file mode 100644
index 0000000000..900d527e48
index 00000000000..900d527e48d
--- /dev/null
+++ b/Include/internal/pycore_emscripten_trampoline.h
@@ -0,0 +1,67 @@
@ -115,7 +114,7 @@ index 0000000000..900d527e48
+#endif // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
+#endif // ndef Py_EMSCRIPTEN_SIGNAL_H
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 7a2f13a21b..3d8ad0c7f2 100644
index 7a2f13a21bd..3d8ad0c7f21 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -10,6 +10,7 @@ extern "C" {
@ -161,7 +160,7 @@ index 7a2f13a21b..3d8ad0c7f2 100644
}
#endif
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index 99c4b0760b..8ceb6b72ec 100644
index 99c4b0760bf..8ceb6b72ec1 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -77,6 +77,11 @@ typedef struct pyruntimestate {
@ -177,7 +176,7 @@ index 99c4b0760b..8ceb6b72ec 100644
is called again.
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 72ac470394..c62672d619 100644
index 72ac4703949..c62672d6196 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -2,6 +2,7 @@
@ -216,7 +215,7 @@ index 72ac470394..c62672d619 100644
static void
descr_dealloc(PyDescrObject *descr)
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 51752dec3d..af4794a913 100644
index 51752dec3dd..af4794a9137 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -550,10 +550,3 @@ cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
@ -232,7 +231,7 @@ index 51752dec3d..af4794a913 100644
-#endif
diff --git a/Python/emscripten_trampoline.c b/Python/emscripten_trampoline.c
new file mode 100644
index 0000000000..8d29393bd8
index 00000000000..8d29393bd87
--- /dev/null
+++ b/Python/emscripten_trampoline.c
@@ -0,0 +1,74 @@
@ -311,7 +310,7 @@ index 0000000000..8d29393bd8
+
+#endif
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index a0130fde15..aec638e85e 100644
index a0130fde15d..aec638e85eb 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -4,6 +4,7 @@
@ -333,7 +332,7 @@ index a0130fde15..aec638e85e 100644
diff --git a/Python/pystate.c b/Python/pystate.c
index 1337516aa5..1043e1f2fe 100644
index 1337516aa59..1043e1f2fee 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2,6 +2,7 @@
@ -353,7 +352,7 @@ index 1337516aa5..1043e1f2fe 100644
PyStatus
diff --git a/configure b/configure
index 99dd1fe595..fe73b21a62 100755
index 99dd1fe5958..fe73b21a62d 100755
--- a/configure
+++ b/configure
@@ -17432,8 +17432,8 @@ PLATFORM_OBJS=
@ -368,7 +367,7 @@ index 99dd1fe595..fe73b21a62 100755
*) :
;;
diff --git a/configure.ac b/configure.ac
index bd2be94b47..6bb201e0b3 100644
index bd2be94b47c..6bb201e0b3b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4811,8 +4811,8 @@ PLATFORM_OBJS=
@ -383,5 +382,5 @@ index bd2be94b47..6bb201e0b3 100644
)
AC_SUBST([PLATFORM_HEADERS])
--
2.25.1
2.34.1

View File

@ -1,7 +1,7 @@
From b6369c9a0192a617548812203b78862da8a49e52 Mon Sep 17 00:00:00 2001
From 986bb199865ea5ec81aaec40e02a51d90f339da4 Mon Sep 17 00:00:00 2001
From: ryanking13 <def6488@gmail.com>
Date: Fri, 12 Jan 2024 00:52:57 +0900
Subject: [PATCH 6/6] Fix LONG_BIT constant to be always 32bit
Subject: [PATCH 5/7] Fix LONG_BIT constant to be always 32bit
Starting from Emscripten 3.1.50, there is an issue where LONG_BIT is
calculated to 64 for some reason. This is very strange because LONG_MAX
@ -17,7 +17,7 @@ Related: https://github.com/emscripten-core/emscripten/pull/20752
1 file changed, 1 insertion(+)
diff --git a/Include/pyport.h b/Include/pyport.h
index 35eca7234c..1c277e2377 100644
index 35eca7234ca..1c277e23770 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -573,6 +573,7 @@ extern char * _getpty(int *, int, mode_t, int);
@ -29,5 +29,5 @@ index 35eca7234c..1c277e2377 100644
#define LONG_BIT (8 * SIZEOF_LONG)
#endif
--
2.25.1
2.34.1

View File

@ -1,5 +1,14 @@
diff --git a/Lib/zoneinfo/_common.pyold b/Lib/zoneinfo/_common.py
index 98cdfe37..75f8fd2b 100644
From 2643d68535a5ab6c8b4d9105257e53f3a2498b46 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Thu, 25 Jul 2024 14:28:57 +0200
Subject: [PATCH 6/7] Warn if ZoneInfo is imported without tzdata
---
Lib/zoneinfo/_common.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Lib/zoneinfo/_common.py b/Lib/zoneinfo/_common.py
index 98cdfe37ca6..35d19eae9f0 100644
--- a/Lib/zoneinfo/_common.py
+++ b/Lib/zoneinfo/_common.py
@@ -11,6 +11,12 @@ def load_tzdata(key):
@ -15,3 +24,6 @@ index 98cdfe37..75f8fd2b 100644
# There are three types of exception that can be raised that all amount
# to "we cannot find this key":
#
--
2.34.1

View File

@ -0,0 +1,61 @@
From 0f4f4f02bda0f6ee4efd24e8c2670e8bc80194a8 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Thu, 25 Jul 2024 14:41:37 +0200
Subject: [PATCH 7/7] Add call to `JsProxy_GetMethod` to help remove temporary
_PyObject_GetMethod is a special attribute lookup function that won't call the
`__get__` descriptor on a method to avoid creating a temporary PyMethodObject.
We also want to optimize away a temporary JsProxy in a special way. In order to
do this, we patch the behavior of `_PyObject_GetMethod` to use
`JsProxy_GetMethod`.
In order to avoid linker errors when used with just Python and not with
libpyodide.a, we declare a dummy JsProxy_GetMethod with weak linkage that does
nothing. When linked to libpyodide.a it will get overridden by the real
function. Otherwise, this patch does nothing.
See the definition of `JsProxy_GetMethod` in `jsproxy.c` and particularly
`JsMethodCallSingleton` for how this is used.
---
Objects/object.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/Objects/object.c b/Objects/object.c
index aac707d6a26..91fb068eab3 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1279,6 +1279,18 @@ _PyObject_NextNotImplemented(PyObject *self)
}
+
+PyObject* __attribute__((weak))
+JsProxy_GetAttr(PyObject* self, PyObject* attr) {
+ return NULL;
+}
+
+PyObject* __attribute__((weak))
+JsProxy_GetMethod(PyObject* obj, PyObject* name) {
+ return NULL;
+}
+
+
/* Specialized version of _PyObject_GenericGetAttrWithDict
specifically for the LOAD_METHOD opcode.
@@ -1303,6 +1315,11 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
}
}
+ if (tp->tp_getattro == JsProxy_GetAttr) {
+ *method = JsProxy_GetMethod(obj, name);
+ return 0;
+ }
+
if (tp->tp_getattro != PyObject_GenericGetAttr || !PyUnicode_CheckExact(name)) {
*method = PyObject_GetAttr(obj, name);
return 0;
--
2.34.1

View File

@ -113,6 +113,8 @@ pygments_style = None
# -- Options for HTML output -------------------------------------------------
html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "")
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
@ -158,9 +160,7 @@ IN_READTHEDOCS_LATEST = (
base_dir = Path(__file__).resolve().parent.parent
extra_sys_path_dirs = [
str(base_dir),
str(base_dir / "pyodide-build"),
str(base_dir / "src/py"),
str(base_dir / "packages/micropip/src"),
]
@ -267,6 +267,21 @@ def write_console_html(app):
atexit.register(remove_console_html)
def write_examples(app):
"""Preprocess the examples HTML files and copy them to the output directory"""
example_outdir = Path(app.outdir) / "examples"
example_outdir.mkdir(exist_ok=True, parents=True)
example_html_dir = Path("./usage/examples")
for example in example_html_dir.glob("*.html"):
text = example.read_text()
text = text.replace("{{ PYODIDE_BASE_URL }}", app.config.CDN_URL)
output_path = example_outdir / example.name
output_path.write_text(text)
def ensure_typedoc_on_path():
if shutil.which("typedoc"):
return
@ -359,5 +374,6 @@ def setup(app):
calculate_pyodide_version(app)
ensure_typedoc_on_path()
write_console_html(app)
write_examples(app)
prune_docs()
Path("../src/js/generated/pyproxy.ts").unlink(missing_ok=True)

View File

@ -79,9 +79,9 @@ Pyodide follows [semantic versioning](http://semver.org/) - major versions for
breaking changes (x.0.0), minor versions for new features (0.x.0), and patches
for bug fixes (0.0.x).
We keep a file, {ref}`docs/changelog.md <changelog>`, outlining changes to
Pyodide in each release. We like to think of the audience for changelogs as
non-developers who primarily run the latest stable. So the change log will
We keep a file, {ref}`docs/project/changelog.md <changelog>`, outlining changes
to Pyodide in each release. We like to think of the audience for changelogs
as non-developers who primarily run the latest stable. So the change log will
primarily outline user-visible changes such as new features and deprecations,
and will exclude things that might otherwise be inconsequential to the end user
experience, such as infrastructure or refactoring.
@ -197,10 +197,6 @@ information, as well as Mozilla's
[MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/) if you need further
clarification on what is and isn't permitted.
## Get in Touch
- **Gitter:** [#pyodide](https://gitter.im/pyodide/community) channel at gitter.im
[tl;drlegal entry]: https://tldrlegal.com/license/mozilla-public-license-2.0-(mpl-2)
```{eval-rst}

View File

@ -191,6 +191,11 @@ to update all packages and make a pull request with these changes. There will be
build/test failures, revert the packages that fail the build or tests and make a
note to update them independently.
## Updating pyodide-build
to change the version of pyodide-build, update the PYODIDE_BUILD_REPO and PYODIDE_BUILD_COMMIT
variables in `Makefile.envs`.
## Upgrading pyodide to a new version of CPython
### Prerequisites
@ -222,7 +227,6 @@ If doing a major version update, save time by {ref}`updating-packages` first.
- `docs/development/building-and-testing-packages.md`
- `environment.yml`
- `.pre-commit-config.yaml`
- `pyodide-build/pyodide_build/tools/pyo3_config.ini` (two places)
- `pyproject.toml`
(TODO: make this list shorter.)

View File

@ -75,18 +75,13 @@ This will mount the current working directory as `/src` within the container so
if you build the package within the container the files created will persist in
the directory after you exit the container.
You should install `pyodide-build`:
```bash
pip install -e ./pyodide-build
```
If you want to build the package, you will need to build Python which you can do
as follows:
```bash
make -C emsdk
make -C cpython
make pyodide_build
```
This also builds the appropriate version of Emscripten.

View File

@ -27,11 +27,9 @@ and third-party applications that use Pyodide.
pytest
```
There are 3 test locations that are collected by pytest,
There are 2 test locations that are collected by pytest,
- `src/tests/`: general Pyodide tests and tests running the CPython test suite
- `pyodide-build/pyodide_build/tests/`: tests related to Pyodide build system
(do not require selenium or playwright to run)
- `packages/*/test_*`: package specific tests.
You can run the tests from a specific file with:

View File

@ -51,6 +51,7 @@ Using Pyodide
usage/streams.md
usage/api-reference.md
usage/faq.md
usage/examples.md
Development
^^^^^^^^^^^

View File

@ -45,7 +45,7 @@ list from there with "The Pyodide development team" like in the example below:
month = aug,
year = 2021,
publisher = {Zenodo},
version = {0.25.0},
version = {0.26.0},
doi = {10.5281/zenodo.5156931},
url = {https://doi.org/10.5281/zenodo.5156931}
}
@ -55,9 +55,9 @@ list from there with "The Pyodide development team" like in the example below:
- Blog: [blog.pyodide.org](https://blog.pyodide.org/)
- Mailing list: [mail.python.org/mailman3/lists/pyodide.python.org/](https://mail.python.org/mailman3/lists/pyodide.python.org/)
- Gitter: [gitter.im/pyodide/community](https://gitter.im/pyodide/community)
- Twitter: [twitter.com/pyodide](https://twitter.com/pyodide)
- Stack Overflow: [stackoverflow.com/questions/tagged/pyodide](https://stackoverflow.com/questions/tagged/pyodide)
- Discord: [Pyodide Discord](https://discord.gg/cRxMCG5kJQ)
## Donations

View File

@ -16,64 +16,194 @@ myst:
## Unreleased
- {{ Enhancement }} `pyodide.loadPackage` now checks if the cache directory exists and calls `mkdir` only when it doesn't to avoid an error on read-only file systems in Node.js environment.
{pr}`4738`
- {{ Enhancement }} Add unix-timezones module, which installs Unix compatible
timezone data in /usr/share/zoneinfo, for use with C/C++ libraries which do
timezone handling.
{pr}`4889`
- {{ Fix }} pyodide-build now use response file when passing list of exported symbols to `emcc`.
This Fixes "Argument list too long" error.
- {{ Enhancement }} `HttpStatusError` now store their the corresponding request
`status`, `status_message` and `url`
{pr}`4974`.
- {{ Fix }} Pass through `-E` (command mode) arguments in CMake wrapper {pr}`4705`.
- {{ Breaking }} Shared libraries are now loaded locally. This means that packages that
depend on shared libraries link to the shared libraries explicitly.
{pr}`4876`
- {{ Fix }} Fix exception handling in dynamic linking of int64 functions {pr}`4698`.
- {{ Enhancement }} Added implementation to abort `pyfetch` and `FetchResponse`
manually or automatically.
{pr}`4846`
- {{ Enhancement }} `str(jsproxy)` has been adjusted to not raise an error if
`jsproxy.toString` is undefined. Instead, it will use
`Object.prototype.toString` in this case. If `jsproxy.toString` is defined and
throws or is not defined but `jsproxy[Symbol.toStringTag]` is defined and
throws, then `str` will still raise.
{pr}`4574`
- {{ Enhancement }} Unvendored stdlibs are now packaged in a wheel format
{pr}`4902`
- {{ Enhancement }} Improved support for stack switching.
{pr}`4532`, {pr}`4547`
- {{ Performance }} Attribute lookup on a `JsProxy` is now about 40% faster.
{pr}`4961`
- Upgraded Python to v3.12.1
- {{ Performance }} Method calls on a `JsProxy` are now much faster. If the
method has no arguments and no return value, it is about 80% faster. The
speedup for methods with arguments is less drastic but still quite a lot.
{pr}`4961`
- {{ Breaking }} Prebuilt third-party libraries like `openblas`, `openssl`, `zlib` are
not included in the cross-build env anymore.
{pr}`4995`
- {{ Fix }} `pyimport("a.b")` won't fail when `a` is removed by `del sys.modules["a"]`
{pr}`4993`
### Packages
- Upgraded `scikit-learn` to 1.5.0 {pr}`4823`
- Upgraded `libcst` to 1.4.0 {pr}`4856`
- Upgraded `lakers` to 0.3.3 {pr}`4885`
- Upgraded `bokeh` to 3.4.2 {pr}`4888`
- Upgraded `pandas` to 2.2.2 {pr}`4893`
- Upgraded `zengl` to 2.5.0 {pr}`4894`
- Upgraded `sourmash` to 4.8.11 {pr}`4980`
- Upgraded `scipy` to 1.13.0 {pr}`4719`
- Upgraded `scikit-image` to 0.24.0 {pr}`5003`
- Added `casadi` 3.6.5 {pr}`4936`
- Added `rasterio` 1.13.10, `affine` 2.4.0 {pr}`4983`
## Version 0.26.2
_July 26, 2024_
- {{ Fix }} Don't leak the values in a dictionary when applying `to_js` to it.
{pr}`4853`
- {{ Fix }} Loading of dynamic libraries now works slightly better in the cli
runner. Resolved {issue}`3865`.
{pr}`4871`
- {{ Fix }} Restored the pre-0.26.0 behavior of calling `exit()` or raising
`SystemExit`. In 0.26.0 and 0.26.1, `exit()` shuts down the Python
interpreter. In all other versions of Pyodide it does not.
{pr}`4867`
- {{ Fix }} Fixed a weird regression occurring in difficult to describe
circumstances introduced by {pr}`4837`. See {issue}`4861`.
{pr}`4861`
- {{ Fix }} Recursive fortran functions now work correctly in scipy {issue}`4818`.
{pr}`4822`
- {{ Enhancement }} Allow setting `dont_inherit` and `optimize` for `compile`
in `CodeRunner` and `Console`.
{pr}`4897`
- {{ Fix }} Fixed a bug that caused `Console`'s `formatted_traceback` being truncated
unexpectedly when `filename` is specified.
{pr}`4905`
- {{ Fix }} Locked `PyodideConsole.runcode` to block `loadPackagesFromImports`.
{pr}`4905`
- {{ Enhancement }} Added `checkAPIVersion` option to `loadPyodide` to allow
bootstrapping pyodide with a different version.
{pr}`4907`
- {{ Enhancement }} Added `can_run_sync` to test whether or not `run_sync`
should work.
{pr}`4913`
- {{ Fix }} Fixed a bug with the JSPI that made it interact incorrectly with
JavaScript code that iterates a `PyProxy`.
{pr}`4919`
- {{ Fix }} Pyodide now loads correctly when `define` and `define.amd` are
defined in the global scope.
{pr}`4866`
- {{ Fix }} Fixed keyboard input handling in SDL-based packages.
{pr}`4865`
### Packages
- Added `duckdb` 1.0.0 {pr}`4684`
## Version 0.26.1
_June 7, 2024_
### Build system
- {{ Fix }} Fix `pyodide config` command printing extra output.
{pr}`4814`
- {{ Enhancement }} Added implementation to read build settings from `pyproject.toml`.
{pr}`4831`
- {{ Fix }} In the Pyodide virtual environment, pip sees `platform.system()` as
"Emscripten" and not as "emscripten".
{pr}`4812`
- {{ Fix }} Resolution of JavaScript symbols in dynamic libraries doesn't fail
anymore in the command line runner.
{pr}`4836`
- {{ Fix }} Pyodide virtual environments now work correctly in Fedora and other
platforms with platlibdir not equal to "lib".
{pr}`4844`
### Runtime / FFI
- {{ Enhancement }} Added the `enableRunUntilComplete` option to `loadPyodide`
which makes `run_until_complete` block using stack switching, or crash if
stack switching is disabled.
{pr}`4817`
- {{ Fix }} Resolved an issue where string keys in `PyProxyJsonAdaptor` were
unexpectedly cast to numbers.
{pr}`4825`
- {{ Fix }} When a `Future` connected to a `Promise` is cancelled, don't raise
`InvalidStateError`.
{pr}`4837`
### Packages
- New Packages: `pytest-asyncio` {pr}`4819`
## Version 0.26.0
_May 27, 2024_
### General
- {{ Update }} Upgraded Python to v3.12.1
{pr}`4431` {pr}`4435`
- {{ Update }} The wheel tag for Pyodide wheels has changed to pyodide_2024_0_wasm32.
{pr}`4777`, {pr}`4780`
- {{ Enhancement }} ABI Break: Updated Emscripten to version 3.1.58
{pr}`4399` {pr}`4715`
- {{ Breaking }} `pyodide-build` entrypoint is removed in favor of `pyodide`.
This entrypoint was deprecated since 0.22.0.
{pr}`4368`
- {{ Enhancement }} Added apis to discard extra arguments when calling Python
functions.
{pr}`4392`
- {{ Breaking }} Pyodide will not fallback to `node-fetch` anymore when `fetch`
is not available in the Node.js < 18 environment.
{pr}`4417`
- {{ Enhancement }} Updated `pyimport` to support `pyimport("module.attribute")`.
{pr}`4395`
- {{ Enhancement }} Improved support for stack switching.
{pr}`4532`, {pr}`4547`, {pr}`4615`, {pr}`4639`
- {{ Breaking }} The `--no-deps` option to `pyodide build-recipes` has been
replaced with a separate subcommand `pyodide build-recipes-no-deps`.
{pr}`4443`
- {{ Enhancement }} The `build/post` script now runs under the directory
where the built wheel is unpacked.
{pr}`4481`
- {{ Breaking }} The experimental `callSyncifying` method was renamed to
`callPromising`.
{pr}`4608`
- {{ Fix }} `dup` now works correctly in the Node filesystem.
{pr}`4554`
- {{ Enhancement }} Fixed a memory leak when iterating over a PyProxy.
{pr}`4546`
- {{ Enhancement }} `asyncio.sleep(0)` now runs the next task a lot faster.
{pr}`4590`
### JavaScript APIs
- {{ Enhancement }} `pyodide.loadPackage` now checks if the cache directory
exists and calls `mkdir` only when it doesn't to avoid an error on read-only
file systems in Node.js environment.
{pr}`4738`
- {{ Fix }} `pyodide.mountNativeFS` will no longer silently overwrite an
existing nonempty directory. Also it throws much clearer error messages when
it fails.
@ -83,6 +213,21 @@ myst:
directory into the Pyodide file system when running in node.
{pr}`4561`
- {{ Enhancement }} Updated `pyimport` to support `pyimport("module.attribute")`.
{pr}`4395`
### FFI
- {{ Enhancement }} `str(jsproxy)` has been adjusted to not raise an error if
`jsproxy.toString` is undefined. Instead, it will use
`Object.prototype.toString` in this case. If `jsproxy.toString` is defined and
throws or is not defined but `jsproxy[Symbol.toStringTag]` is defined and
throws, then `str` will still raise.
{pr}`4574`
- {{ Enhancement }} Fixed a memory leak when iterating over a PyProxy.
{pr}`4546`
- {{ Enhancement }} When a dictionary is converted to JavaScript with `toJs` the
result is now a `LiteralMap`. String keys are accessible via direct property
access unless they match a function on the `Map` prototype.
@ -91,17 +236,41 @@ myst:
- {{ Fix }} `toJs` now works as expected on subclasses of `dict`.
{pr}`4637`
- {{ Enhancement }} Added `PyProxy.asJsonAdaptor` method to adapt between Python
JSON (lists and dicts) and JavaScript JSON (Arrays and Objects).
- {{ Enhancement }} Added `PyProxy.asJsJson` method to adapt between Python JSON
(lists and dicts) and JavaScript JSON (Arrays and Objects).
{pr}`4666`
- {{ Breaking }} The experimental `callSyncifying` method was renamed to
`callPromising`.
- {{ Enhancement }} Added a new `callRelaxed` to PyProxies of callables that
discards extra arguments rather than raising a `TypeError``.
{pr}`4392`
- {{ Enhancement }} A new `callWithOptions` method was added to PyProxies of
callables.
{pr}`4608`
- {{ Enhancement }} A new `callWithOptions` method was added to PyProxies of a
callable.
{pr}`4608`
### Build
- {{ Fix }} pyodide-build now use response file when passing list of exported symbols to `emcc`.
This fixes "Argument list too long" error.
{pr}`4717``
- {{ Fix }} Pass through `-E` (command mode) arguments in CMake wrapper
{pr}`4705`.
- {{ Fix }} Fix exception handling in dynamic linking of int64 functions
{pr}`4698`.
- {{ Breaking }} `pyodide-build` entrypoint is removed in favor of `pyodide`.
This entrypoint was deprecated since 0.22.0.
{pr}`4368`
- {{ Breaking }} The `--no-deps` option to `pyodide build-recipes` has been
replaced with a separate subcommand `pyodide build-recipes-no-deps`.
{pr}`4443`
- {{ Enhancement }} The `build/post` script now runs under the directory
where the built wheel is unpacked.
{pr}`4481`
### Packages
@ -111,7 +280,7 @@ myst:
`pure_eval`, `stack_data`, `traitlets`, `wcwidth` {pr}`4452`, `altair` {pr}`4580`,
`cvxpy` {pr}`4587`, `clarabel` {pr}`4587`, `matplotlib-inline` {pr}`4626`,
`pygame-ce` {pr}`4602`, `libcst` {pr}`4665`, `mmh3`, `pyiceberg` {pr}`4648`,
`lakers-python` {pr}`4763`
`lakers-python` {pr}`4763`, `crc32c` {pr}`4789`, `zstandard` {pr}`4792`
- Upgraded `contourpy` to 1.2.1 {pr}`4680`
- Upgraded `sourmash` to 4.8.8 {pr}`4683`

View File

@ -22,12 +22,15 @@
[IDE](https://futurecoder.io/course/#ide) with a REPL,
debuggers, and automatic installation of
any imported packages supported by Pyodide's `micropip`.
- [PyRepl.io](https://pyrepl.io) uses Pyodide for a Python interpreter in your browser. PyRepl is made for creating and sharing code snippets. Embed interactive Python examples in your documentation, blog posts, presentations and more.
- [react-py Playground](https://elilambnz.github.io/react-py/playground) uses Pyodide as part of the `react-py` package documentation. Try out code snippets and packages directly in your browser without logging in.
- [marimo](https://github.com/marimo-team/marimo) is a reactive notebook that is compatible with Pyodide with an [online editor](https://marimo.app/) that runs entirely in the browser. These notebooks can also run as standalone applications or embedded in blogs.
- [quarto-pyodide](https://github.com/coatless-quarto/pyodide) uses Pyodide
to create interactive code cells and documents within a variety of
[Quarto](https://quarto.org/) document formats like
HTML Documents, RevealJS, Books, and Websites.
- [PyCafe](https://py.cafe) lets you host, edit, and share Python apps in your browser with a single click.
- [quarto-live](https://github.com/r-wasm/quarto-live) uses Pyodide
to create interactive Python code cells and exercises in [Quarto](https://quarto.org/) documents.
## Workarounds for common WASM and browser limitations
@ -40,6 +43,8 @@
- [WebDash](https://github.com/ibdafna/webdash) is a Plotly Dash distribution
that runs entirely in the browser, using Pyodide.
- [Flet](https://flet.dev) is a UI framework for your Pyodide apps based on Flutter.
- [stlite](https://github.com/whitphx/stlite) is a serverless version of [Streamlit](https://streamlit.io/) running on Pyodide.
- [Gradio-Lite](https://www.gradio.app/guides/gradio-lite) is a serverless version of [Gradio](https://www.gradio.app/) running on Pyodide.
## Other projects

View File

@ -16,10 +16,10 @@ sphinx-click @ git+https://github.com/hoodmane/sphinx-click@271ebdb3e5855f2901f5
sphinx-autodoc-typehints>=1.21.7
sphinx-design>=0.3.0
pydantic
# Packages that we want to document as part of the Pyodide CLI
./pyodide-build/
# TODO: separate document for pyodide-build?
pyodide-build>=0.27.3
# Version should be consistent with packages/micropip/meta.yaml
micropip==0.2.2
jinja2>=3.0
ruamel.yaml
sphinx-js @ git+https://github.com/pyodide/sphinx-js-fork@a012f65542eb09664eec7f85b0c79cdca7e37588
sphinx-js @ git+https://github.com/pyodide/sphinx-js-fork@14958086d51939ae4078751abec004e1f3fea1fe

View File

@ -56,3 +56,35 @@ services.
For additional suggestions for optimizing the size and load time for Pyodide,
see the [Emscripten documentation about
deployments](https://emscripten.org/docs/compiling/Deploying-Pages.html).
## Contents of Pyodide Github releases
### Files in `pyodide-core-{{VERSION}}.tar.bz2`
| File Name | Description |
| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| pyodide.asm.js | The JavaScript half of the main "binary". Direct output from the Emscripten compiler. Contains the Emscripten bootstrap code + all JavaScript libraries used by C + the JavaScript/Wasm runtime interop APIs. |
| pyodide.asm.wasm | The WebAssembly half of the main "binary". Direct output from the Emscripten compiler. Contains all C library code that is statically linked. Also includes enough of libcxx to support things like exceptions in extension modules that use C++. |
| pyodide.js | Exports loadPyodide on globalThis. Legacy support for people who can't use es6 modules for whatever reason. Prefer pyodide.mjs. |
| pyodide.mjs | A small JS loader shim which exports loadPyodide. It manages downloading the runtime and handling user settings. |
| python_stdlib.zip | The Python Standard Library for pyodide. A zip file consisting of the Python Lib folder (except a few things we've unvendored) and the Pyodide Python runtime libraries. Mounted directly into the Pyodide FS and imported using ZipImporter. |
| package.json | Tells node how to use Pyodide, since pyodide-core was primarily intended for use with node. |
| pyodide-lock.json | Lockfile for Python packages, used by pyodide.loadPackage and micropip.install. Necessary in all cases. |
### Additional Files in `pyodide-{{VERSION}}.tar.bz2`
| File Name | Description |
| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| fonts/ | Used by matplotlib-pyodide. |
| ffi.d.ts | Typescript type definitions, useful if you want to use Pyodide in a typescript project. |
| pyodide.d.ts | Typescript type definitions, useful if you want to use Pyodide in a typescript project. |
| \*.whl | Contains various Python Wheels like NumPy, Pandas, SciPy, etc. When downloading and including in a project, these no longer need to be loaded from Pyodide's online wheel repository during runtime. |
| \*.metadata | Information about the included wheels, such as name, author, license, dependencies, etc. Allows more efficient package resolution, specified in [PEP 658](https://peps.python.org/pep-0658/). |
| \*.zip | These are shared libraries and unvendored Python standard library modules. |
| |
| python | Bash/node polyglot. Only needed for node < 18. |
| pyodide.js.map | Source maps to improve tracebacks. Not really that useful to people outside of the project, probably should be only included in debug builds. |
| pyodide.mjs.map | Source maps to improve tracebacks. Not really that useful to people outside of the project, probably should be only included in debug builds. |
| \*-tests.tar | Unvendored tests from wheels. If a wheel includes a test folder, we take them out and put them here. |
| console.html | The Pyodide repl. |
| webworker.js | Mentioned in the docs. Developers should probably implement their own Web Worker. |

25
docs/usage/examples.md Normal file
View File

@ -0,0 +1,25 @@
# Community Examples
(examples)=
This section contains a collection of examples using Pyodide, contributed by the community.
## Examples
- [Black formatter](../examples/black.html){.external} - by [@ryanking13](https://github.com/ryanking13)
<!-- Contribution Guide -->
<!--
We welcome contributions to this section.
If you have an example you would like to share, please submit a pull request in the Pyodide repository.
To add an example, create a new file in the `examples` directory, we expect the example is a single HTML file
that contains everything needed to run the example, so people can easily download and run it locally.
You can start with copying the template file (`examples/examples.html.tmpl`). Note that the template file contains
a placeholder URL {{ PYODIDE_BASE_URL }} that will be replaced by the actual URL when the documentation is built.
So please do not remove it.
After you have added the example, please add a link to it in the list above.
Feel free to add some description to the example if you like and add your name as the author.
-->

View File

@ -0,0 +1,98 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script src="{{ PYODIDE_BASE_URL }}pyodide.js"></script>
<style>
pre {
background-color: #f7f7f7;
padding: 10px;
}
</style>
</head>
<body>
<h1>Using black formatter in Pyodide</h1>
<div>
<textarea id="codeblock" rows="45" cols="80" spellcheck="false">
from pyodide import hello, Pyodide
x = { 'a':37,'b':42,
'c':927}
x = 123456789.123456789E123456789
if very_long_variable_name is not None and \
very_long_variable_name.field > 0:
z = 'hello '+'world'
else:
world = 'world'
a = 'hello {}'.format(world)
f = rf'hello {world}'
if (this
and that): y = 'hello ''world'
class Foo ( object ):
def f (self ):
return 37*-2
def g(self, x,y=42):
return y
def f ( a: List[ int ]) :
return 37-a[42-u : y**3]
def very_important_function(template: str,*variables,file: os.PathLike,debug:bool=False,):
"""Applies \`variables\` to the \`template\` and writes to \`file\`."""
with open(file, "w") as f:
...
# fmt: off
custom_formatting = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
]
# fmt: on
regular_formatting = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
]
</textarea
>
</div>
<div>
<button id="formatButton" onclick="format()" disabled>
Loading Pyodide...
</button>
</div>
<script type="text/javascript">
let formatStr = () => {};
const format = () => {
const code = document.getElementById("codeblock").value;
const formattedCode = formatStr(code);
document.getElementById("codeblock").value = formattedCode;
};
async function init() {
const pyodide = await loadPyodide({
packages: ["micropip"],
});
const micropip = pyodide.pyimport("micropip");
await micropip.install("black");
formatStr = pyodide.runPython(`
import black
def format_str(code):
return black.format_str(code, mode=black.FileMode())
format_str
`);
const button = document.getElementById("formatButton");
button.disabled = false;
button.innerText = "Format Me!";
}
init();
</script>
</body>
</html>

View File

@ -0,0 +1,23 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script src="{{ PYODIDE_BASE_URL }}pyodide.js"></script>
</head>
<body>
<h1>TITLE GOES HERE</h1>
<script type="text/javascript">
async function init() {
const pyodide = await loadPyodide();
pyodide.runPython(`
print("Hello from Python!");
`);
}
init();
</script>
</body>
</html>

View File

@ -74,6 +74,15 @@ pyodide.runPython(`
Micropip implements file integrity validation by checking the hash of the
downloaded wheel against pre-recorded hash digests from the PyPI JSON API.
(micropip-installing-from-other-indexes)=
### Installing wheels from different indexes
By default micropip will look for wheel on [pypi](https://pypi.org). It is
possible to provide a list of indexes url to the install commands via the
[`index_urls`](https://micropip.pyodide.org/en/stable/project/api.html#micropip.install)
parameter of the `install` command.
(micropip-installing-from-arbitrary-urls)=
### Installing wheels from arbitrary URLs

View File

@ -10,34 +10,58 @@ project.
## Vite
```{note}
The following instructions have been tested with Pyodide 0.25.0 and Vite 5.1.4.
The following instructions have been tested with Pyodide 0.26.0 and Vite 5.2.13.
```
If you have installed Pyodide via npm, you can use it in Vite as follows. First,
the Pyodide npm package currently uses [`node-fetch`][] to load some files,
which does not work in a browser; to resolve this, install the
[`isomorphic-fetch`][] package so that Pyodide does not try to load `node-fetch`
in the browser:
First, install the Pyodide npm package:
```
$ npm install --save isomorphic-fetch@^3
$ npm install pyodide
```
Then, exclude Pyodide from [Vite's dependency pre-bundling][optimizedeps] by
setting `optimizeDeps.exclude` in your `vite.config.js` file:
Then, in your `vite.config.js` file, exclude Pyodide from [Vite's dependency
pre-bundling][optimizedeps] by setting `optimizeDeps.exclude` and ensure that
all Pyodide files will be available in `dist/assets` for production builds by
using a Vite plugin:
```js
import { defineConfig } from "vite";
import { copyFile, mkdir } from "fs/promises";
import { join } from "path";
export default defineConfig({ optimizeDeps: { exclude: ["pyodide"] } });
export default defineConfig({
optimizeDeps: { exclude: ["pyodide"] },
plugins: [
{
name: "vite-plugin-pyodide",
generateBundle: async () => {
const assetsDir = "dist/assets";
await mkdir(assetsDir, { recursive: true });
const files = [
"pyodide-lock.json",
"pyodide.asm.js",
"pyodide.asm.wasm",
"python_stdlib.zip",
];
for (const file of files) {
await copyFile(
join("node_modules/pyodide", file),
join(assetsDir, file),
);
}
},
},
],
});
```
You can test your setup with this `index.html` file:
```html
<!doctype html>
<html>
<html lang="en">
<head>
<title>Vite + Pyodide</title>
<script type="module" src="/src/main.js"></script>
</head>
</html>
@ -58,29 +82,18 @@ hello_python().then((result) => {
});
```
This should be sufficient for Vite dev mode:
Make sure this works both in Vite's dev mode:
```
$ npx vite
npx vite
```
For a production build, you must also manually make sure that all Pyodide files
will be available in `dist/assets`, by first copying them to `public/assets`
before building:
And as a production build:
```
$ mkdir -p public/assets/
$ cp node_modules/pyodide/* public/assets/
$ npx vite build
npx vite build
npx vite preview
```
Then you can view this production build to verify that it works:
```
$ npx vite preview
```
[`isomorphic-fetch`]: https://www.npmjs.com/package/isomorphic-fetch
[`node-fetch`]: https://www.npmjs.com/package/node-fetch
[optimizedeps]: https://vitejs.dev/guide/dep-pre-bundling.html
[pyodide webpack plugin]: https://github.com/pyodide/pyodide-webpack-plugin

View File

@ -1,7 +1,7 @@
From 137dae4dbdf9a192551582cdae827b085510956f Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Fri, 2 Jun 2023 11:59:32 -0700
Subject: [PATCH 1/5] Add back fs.findObject and fs.readFile in loadLibData
Subject: [PATCH 1/6] Add back fs.findObject and fs.readFile in loadLibData
See upstream PR:
https://github.com/emscripten-core/emscripten/pull/19513

View File

@ -1,7 +1,7 @@
From e0cb884277200310eba263dcce5a7b1c4567bae6 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Fri, 19 May 2023 12:19:00 -0700
Subject: [PATCH 2/5] Add useful error when symbol resolution fails
Subject: [PATCH 2/6] Add useful error when symbol resolution fails
Currently if symbol resolution fails, we get:
```js

View File

@ -1,7 +1,7 @@
From d4d5d35072b6d28c5f98b77a0d578e01bd25ef7e Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Thu, 22 Jun 2023 18:53:22 -0700
Subject: [PATCH 3/5] Changes for JSPI
Subject: [PATCH 3/6] Changes for JSPI
---
src/library.js | 2 +-

View File

@ -1,7 +1,7 @@
From 9352fac9a4618603fbe5ce7ad97a26a3963704bd Mon Sep 17 00:00:00 2001
From: Joe Marshall <joe.marshall@nottingham.ac.uk>
Date: Sat, 13 Apr 2024 21:41:11 +0100
Subject: [PATCH 4/5] Upstream PR:
Subject: [PATCH 4/6] Upstream PR:
https://github.com/emscripten-core/emscripten/pull/21759
---

View File

@ -1,7 +1,7 @@
From 44983793a7f67009c228c5c95899f6fe735fd1c5 Mon Sep 17 00:00:00 2001
From: ryanking13 <def6488@gmail.com>
Date: Sat, 20 Jan 2024 19:02:32 +0900
Subject: [PATCH 5/5] Raise when no argument is given
Subject: [PATCH 5/6] Raise when no argument is given
Emscripten 3.1.51 does not raise an error when no argument is given.
Some build tools (e.g. ffmpeg) relies on this behavior, so we should

View File

@ -0,0 +1,46 @@
From 4a3956693056b3ad4f6541589c5ab44df7a7fc39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?=
<msorvig@users.noreply.github.com>
Date: Wed, 12 Jun 2024 20:10:35 +0200
Subject: [PATCH 6/6] Make RTLD_LOCAL work correctly for preloaded DSOs
(#21985)
Copied from: https://github.com/emscripten-core/emscripten/pull/21985
This patch can be removed when updating Emscripten version to >= 3.1.62
Follow-up to commit c9a5e63c, for the FS.createPreloadedFile()
case.
Make sure loadWebAssemblyModule() and loadDynamicLibrary()
are called with a valid 'localScope' object when invoked
from the .so file type preload handler.
---
src/library_dylink.js | 4 ++--
test/test_core.py | 46 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/src/library_dylink.js b/src/library_dylink.js
index 965b119a4..211f4030c 100644
--- a/src/library_dylink.js
+++ b/src/library_dylink.js
@@ -26,7 +26,7 @@ var LibraryDylink = {
// than just running the promises in parallel, this makes a chain of
// promises to run in series.
wasmPlugin['promiseChainEnd'] = wasmPlugin['promiseChainEnd'].then(
- () => loadWebAssemblyModule(byteArray, {loadAsync: true, nodelete: true}, name)).then(
+ () => loadWebAssemblyModule(byteArray, {loadAsync: true, nodelete: true}, name, {})).then(
(exports) => {
#if DYLINK_DEBUG
dbg(`registering preloadedWasm: ${name}`);
@@ -877,7 +877,7 @@ var LibraryDylink = {
if (flags.loadAsync) {
return metadata.neededDynlibs
.reduce((chain, dynNeeded) => chain.then(() =>
- loadDynamicLibrary(dynNeeded, flags)
+ loadDynamicLibrary(dynNeeded, flags, localScope)
), Promise.resolve())
.then(loadModule);
}
--
2.29.2.windows.2

View File

@ -3,7 +3,7 @@ channels:
- conda-forge
dependencies:
- python=3.12
- nodejs>=18
- nodejs>=18,<22.5 # Node.js 22.5 has some issues with installing packages https://github.com/nodejs/node/issues/53902
- ccache
- f2c
- swig

View File

@ -97,7 +97,7 @@ def test_import(
def _import_pkg():
for import_name in import_names:
selenium_standalone.run_async("import %s" % import_name)
selenium_standalone.run_async(f"import {import_name}")
benchmark(_import_pkg)

16
packages/affine/meta.yaml Normal file
View File

@ -0,0 +1,16 @@
package:
name: affine
version: 2.4.0
top-level:
- affine
source:
url: https://files.pythonhosted.org/packages/0b/f7/85273299ab57117850cc0a936c64151171fac4da49bc6fba0dad984a7c5f/affine-2.4.0-py3-none-any.whl
sha256: 8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92
about:
home: ""
PyPI: https://pypi.org/project/affine
summary: Matrices describing affine transformation of the plane
license: ""
extra:
recipe-maintainers:
- kjmalek

View File

@ -1,16 +1,14 @@
package:
name: awkward-cpp
version: "32"
version: "37"
top-level:
- awkward_cpp
source:
url: https://files.pythonhosted.org/packages/e4/64/f95efa6441d08284e760a394545d6ac3ede2811011d24f0797d786cb2570/awkward-cpp-32.tar.gz
sha256: ad8c5af86206fb0f434b16749cc5cca69a15a88e16ca43e91e56c5cca77421f0
url: https://files.pythonhosted.org/packages/3d/40/fa115d845bfd9bb0b69646a2f1f2321fee3bd82cc286eaa202cb5179fbf5/awkward_cpp-37.tar.gz
sha256: 6dff5fce4afcadb492bbf7cb20908572d99bdc32aa2bea8681bacfb69b2aa86d
build:
script: |
export CMAKE_ARGS="${CMAKE_ARGS} -DEMSCRIPTEN=1"
exports: requested
requirements:

View File

@ -4,12 +4,14 @@ package:
top-level:
- Bio
- BioSQL
requirements:
run:
- numpy
source:
sha256: 78e6bfb78de63034037afd35fe77cb6e0a9e5b62706becf78a7d922b16ed83f7
url: https://files.pythonhosted.org/packages/cc/d4/3d8848191a7a37187704c382e6dfda4d6a47d05a14cd64f004c55a3cd5a1/biopython-1.83.tar.gz
patches:
- "patches/0001-Remove-error-message-if-wheel-is-not-installed.patch"
requirements:
run:
- numpy
about:
home: https://biopython.org/
PyPI: https://pypi.org/project/biopython

View File

@ -0,0 +1,37 @@
From 434770dc707c5192159249d098e6dbc660fa6556 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Thu, 20 Jun 2024 12:31:15 -0700
Subject: [PATCH] Remove error message if wheel is not installed
Since pypa/setuptools#4369 was merged, wheel is vendored into setuptools and no
longer needs to be installed for `bdist_wheel` to work.
Upstream PR:
https://github.com/biopython/biopython/pull/4749
---
setup.py | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/setup.py b/setup.py
index 530b413a9..6cfc48de5 100644
--- a/setup.py
+++ b/setup.py
@@ -37,15 +37,6 @@ except ImportError:
"Try running: python -m ensurepip"
)
-if "bdist_wheel" in sys.argv:
- try:
- import wheel # noqa: F401
- except ImportError:
- sys.exit(
- "We need both setuptools AND wheel packages installed "
- "for bdist_wheel to work. Try running: pip install wheel"
- )
-
# Make sure we have the right Python version.
MIN_PY_VER = (3, 9)
--
2.34.1

View File

@ -1,6 +1,6 @@
package:
name: bokeh
version: 3.4.1
version: 3.4.2
top-level:
- bokeh
requirements:
@ -16,8 +16,8 @@ requirements:
- pyyaml
- xyzservices
source:
sha256: d824961e4265367b0750ce58b07e564ad0b83ca64b335521cd3421e9b9f10d89
url: https://files.pythonhosted.org/packages/d6/9d/c8a7842fbf0e3542a6108b6025e906a18ebe977fdbca9763fd01a3330670/bokeh-3.4.1.tar.gz
sha256: a16d5cc0abb93d2d270d70fc35851f3e1b9208814a985a4678e0ba5ef2d9cd42
url: https://files.pythonhosted.org/packages/d4/91/df53287e2f34c7cd6262b3b31c4dd4d274c78b7ece20cf0736bc4a21ab85/bokeh-3.4.2.tar.gz
about:
home: https://github.com/bokeh/bokeh
PyPI: https://pypi.org/project/bokeh

35
packages/casadi/meta.yaml Normal file
View File

@ -0,0 +1,35 @@
package:
name: casadi
version: 3.6.5
top-level:
- casadi
source:
url: https://files.pythonhosted.org/packages/5a/97/ca40c4d7d36162ddfd0bb96a89206469a95b925faf67046ba6e4b5b78283/casadi-3.6.5.tar.gz
sha256: 409a5f6725eadea40fddfb8ba2321139b5252edac8bc115a72f68e648631d56a
patches:
- patches/0001-fix-python-include-dir.patch # can be removed with version 3.6.6
- patches/0002-disable-size-max-check.patch # https://github.com/casadi/casadi/pull/3785
- patches/0003-disable-rtld_deepbind.patch # https://github.com/casadi/casadi/pull/3785
requirements:
host:
- numpy
run:
- numpy
- python-dateutil
- pytz
build:
exports: requested
cflags: |
-fexceptions -frtti
cxxflags: |
-fexceptions -frtti
ldflags: |
-fexceptions
about:
home: http://casadi.org
PyPI: https://pypi.org/project/casadi
summary: CasADi -- framework for algorithmic differentiation and numeric optimization
license: GNU Lesser General Public License v3 or later (LGPLv3+)
extra:
recipe-maintainers:
- agriyakhetarpal

View File

@ -0,0 +1,41 @@
From 6241d84b52702ad9535781e0a8f4eea130323fd4 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Thu, 18 Jul 2024 02:08:07 +0530
Subject: [PATCH 1/3] Fix the location of the Python include directory
CasADi's setup code used an incorrect location for the Python include
directory via the use of self.include_dirs[0], which isn't guaranteed
to return the correct interpreter used during compilation. This patch
replaces it with sysconfig.get_path('include').
This patch can be safely removed when the next release of CasADi comes
out, i.e., version 3.6.6. The relevant PR is
https://github.com/casadi/casadi/pull/3759
---
setup.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index d7506513..42b8affb 100644
--- a/setup.py
+++ b/setup.py
@@ -6,6 +6,7 @@ import subprocess
import pathlib
import multiprocessing
from io import open
+import sysconfig
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
@@ -47,7 +48,7 @@ class CMakeBuild(build_ext):
'-DSWIG_IMPORT=ON',
'-DWITH_PYTHON=ON',
'-DWITH_EXAMPLES=OFF',
- '-DPYTHON_INCLUDE_DIR=' + self.include_dirs[0],
+ '-DPYTHON_INCLUDE_DIR=' + sysconfig.get_path('include'),
'-DCMAKE_INSTALL_PREFIX=' + extdir,
'-DWITH_SELFCONTAINED=ON',
'-DWITH_DEEPBIND=ON'
--
2.39.3 (Apple Git-146)

View File

@ -0,0 +1,68 @@
From 0577d6e0b0dc5bf127b1041018cfb41137d9f39c Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Fri, 2 Aug 2024 23:05:20 +0530
Subject: [PATCH 2/3] Remove size max check
In WebAssembly (currently 32-bit), SIZE_MAX is equal to UINT_MAX, which meant
these functions weren't being compiled, so there was no way to serialize or
deserialize unsigned int values, leading to compile errors when these functions
were called elsewhere. This patch removes the check for SIZE_MAX != UINT_MAX.
This patch can be revisited after the upstream PR is resolved:
https://github.com/casadi/casadi/pull/3785
---
casadi/core/serializing_stream.cpp | 2 --
casadi/core/serializing_stream.hpp | 7 +++----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/casadi/core/serializing_stream.cpp b/casadi/core/serializing_stream.cpp
index f3101f84e..e68caaf5c 100644
--- a/casadi/core/serializing_stream.cpp
+++ b/casadi/core/serializing_stream.cpp
@@ -155,7 +155,6 @@ namespace casadi {
for (int j=0;j<4;++j) pack(c[j]);
}
-#if SIZE_MAX != UINT_MAX
void DeserializingStream::unpack(unsigned int& e) {
assert_decoration('u');
uint32_t n;
@@ -171,7 +170,6 @@ namespace casadi {
const char* c = reinterpret_cast<const char*>(&n);
for (int j=0;j<4;++j) pack(c[j]);
}
-#endif
void DeserializingStream::unpack(bool& e) {
assert_decoration('b');
diff --git a/casadi/core/serializing_stream.hpp b/casadi/core/serializing_stream.hpp
index 47070d0e6..81c8d56bd 100644
--- a/casadi/core/serializing_stream.hpp
+++ b/casadi/core/serializing_stream.hpp
@@ -99,9 +99,8 @@ namespace casadi {
void unpack(Slice& e);
void unpack(int& e);
-#if SIZE_MAX != UINT_MAX
void unpack(unsigned int& e);
-#endif
+
void unpack(bool& e);
void unpack(casadi_int& e);
void unpack(size_t& e);
@@ -236,9 +235,9 @@ namespace casadi {
void pack(const GenericType& e);
void pack(std::istream& s);
void pack(int e);
-#if SIZE_MAX != UINT_MAX
+
void pack(unsigned int e);
-#endif
+
void pack(bool e);
void pack(casadi_int e);
void pack(size_t e);
--
2.39.3 (Apple Git-146)

View File

@ -0,0 +1,34 @@
From 6c9443c0c1694600927dca29373d29fb741581f2 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Thu, 18 Jul 2024 02:08:07 +0530
Subject: [PATCH 3/3] Disable RTLD_DEEPBIND for Emscripten
RTLD_DEEPBIND gives symbol resolution preference to the loaded library
over the global scope, it's usually used to avoid symbol collision. However,
WebAssembly handles internal symbol resolution differently, and the flag is
is used on Linux systems and does not necessarily translate to other platforms
such as Emscripten.
This can be revisited after the upstream PR is resolved:
https://github.com/casadi/casadi/pull/3785
---
casadi/core/casadi_os.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/casadi/core/casadi_os.cpp b/casadi/core/casadi_os.cpp
index d4718504..f285139c 100644
--- a/casadi/core/casadi_os.cpp
+++ b/casadi/core/casadi_os.cpp
@@ -115,7 +115,7 @@ handle_t open_shared_library(const std::string& lib, const std::vector<std::stri
flag = RTLD_LAZY | RTLD_LOCAL;
}
#ifdef WITH_DEEPBIND
- #ifndef __APPLE__
+ #if !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
flag |= RTLD_DEEPBIND;
#endif
#endif
--
2.39.3 (Apple Git-146)

View File

@ -0,0 +1,387 @@
import pytest
from pytest_pyodide import run_in_pyodide
@run_in_pyodide(packages=["casadi"])
def test_symbolic_variable(selenium):
import casadi as ca
x = ca.SX.sym("x")
assert isinstance(x, ca.SX)
assert x.name() == "x"
@run_in_pyodide(packages=["casadi", "numpy"])
def test_basic_casadi_function_eval(selenium):
import casadi as ca
import numpy as np
x = ca.MX.sym("x")
y = ca.MX.sym("y")
f = ca.Function("f", [x, y], [x**2 + y**2])
assert np.allclose(f(1, 2).full(), np.array([5]))
assert np.allclose(f(3, 4).full(), np.array([25]))
assert np.allclose(f(5, 6).full(), np.array([61]))
# IPOPT not available because compiled with -DWITH_IPOPT=OFF
# by default for size reasons. This can be changed by setting
# -DWITH_IPOPT=ON in the future, but it requires IPOPT to be
# built beforehand.
@pytest.mark.skip(reason="IPOPT not available for now")
@run_in_pyodide(packages=["casadi", "numpy"])
def test_simple_optimization(selenium):
import casadi as ca
import numpy as np
opti = ca.Opti()
x = opti.variable()
y = opti.variable()
opti.minimize((x - 1) ** 2 + (y - 2) ** 2)
opti.solver("ipopt")
sol = opti.solve()
assert np.allclose(sol.value(x), 1.0, atol=1e-6)
assert np.allclose(sol.value(y), 2.0, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_matrix_operations(selenium):
import casadi as ca
import numpy as np
A = ca.DM([[1, 2], [3, 4]])
B = ca.DM([[5, 6], [7, 8]])
C = A @ B
assert np.allclose(C.full(), np.array([[19, 22], [43, 50]]))
@run_in_pyodide(packages=["casadi", "numpy"])
def test_basic_integration(selenium):
import casadi as ca
import numpy as np
t = ca.MX.sym("t")
x = ca.MX.sym("x")
ode = {"t": t, "x": x, "ode": -x}
opts = {"tf": 1.0}
F = ca.integrator("F", "cvodes", ode, opts)
result = F(x0=1)
assert np.allclose(result["xf"].full(), np.array([np.exp(-1)]), atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_basic_rootfinder(selenium):
import casadi as ca
import numpy as np
x = ca.MX.sym("x")
p = ca.MX.sym("p")
f = ca.Function("f", [x, p], [x**2 - p])
# create a root finder with Newton's method
opts = {
"implicit_input": 0,
"implicit_output": 0,
"linear_solver": "csparse", # Use sparse linear solver
"max_iter": 100, # Set maximum iterations
"abstol": 1e-6, # Set absolute tolerance
}
rf = ca.rootfinder("rf", "newton", f, opts)
# solve for the square root of 9, with initial guess 2
initial_guess = 2
result = rf(initial_guess, 9)
assert np.isclose(result.full()[0, 0], 3, atol=1e-6)
######################################################################
# CasADi integrator tests, using the damped harmonic oscillator and the
# bouncing balls as examples. The tests are run for both CVODES and IDAS.
@run_in_pyodide(packages=["casadi", "numpy"])
@pytest.mark.parametrize("integrator_type", ["cvodes", "idas"])
def test_harmonic_oscillator(selenium, integrator_type):
import casadi as ca
import numpy as np
# define a damped harmonic oscillator:
# d^2x/dt^2 + 2*zeta*omega*dx/dt + omega^2*x = 0
x = ca.SX.sym("x")
v = ca.SX.sym("v")
omega = 2 * np.pi # natural frequency
zeta = 0.1 # damping ratio
dae = {
"x": ca.vertcat(x, v),
"ode": ca.vertcat(v, -(omega**2) * x - 2 * zeta * omega * v),
}
opts = {
"abstol": 1e-10, # Absolute tolerance
"reltol": 1e-10, # Relative tolerance
"max_num_steps": 10000, # max steps
}
F = ca.integrator("F", integrator_type, dae, 0, 1, opts)
# Set initial conditions: x(0) = 1, v(0) = 0
r = F(x0=[1, 0])
# exact analytical solution for the damped harmonic oscillator
def exact_solution(t, x0, v0):
# damped natural frequency
wd = omega * np.sqrt(1 - zeta**2)
# initial amplitude
A = np.sqrt(x0**2 + ((v0 + zeta * omega * x0) / wd) ** 2)
phi = np.arctan((v0 + zeta * omega * x0) / (wd * x0))
x = A * np.exp(-zeta * omega * t) * np.cos(wd * t - phi)
v = (
-A
* np.exp(-zeta * omega * t)
* (zeta * omega * np.cos(wd * t - phi) + wd * np.sin(wd * t - phi))
)
return x, v
t = 1 # Solution at t equals 1
expected_x, expected_v = exact_solution(t, 1, 0)
assert np.isclose(r["xf"][0].full()[0, 0], expected_x, atol=1e-8, rtol=1e-6)
assert np.isclose(r["xf"][1].full()[0, 0], expected_v, atol=1e-8, rtol=1e-6)
# probably test with custom time horizon too
t_custom = 2
F_custom = ca.integrator("F_custom", integrator_type, dae, 0, t_custom, opts)
r_custom = F_custom(x0=[1, 0])
expected_x_custom, expected_v_custom = exact_solution(t_custom, 1, 0)
assert np.isclose(
r_custom["xf"][0].full()[0, 0], expected_x_custom, atol=1e-6, rtol=1e-6
)
assert np.isclose(
r_custom["xf"][1].full()[0, 0], expected_v_custom, atol=1e-6, rtol=1e-6
)
# verify that the results are indeed different
assert not np.isclose(
r["xf"][0].full()[0, 0], r_custom["xf"][0].full()[0, 0], atol=1e-6, rtol=1e-6
)
@run_in_pyodide(packages=["casadi", "numpy"])
@pytest.mark.parametrize("integrator_type", ["cvodes", "idas"])
def test_bouncing_ball(selenium, integrator_type):
import casadi as ca
# Parameters
g = 9.81 # Gravity (m/s^2)
e = 0.8 # Coefficient of restitution
h0 = 10 # Initial height (m)
v0 = 0 # Initial velocity (m/s)
# state variables
s = ca.SX.sym("s", 2) # s[0] is height, s[1] is velocity
# add ODE right hand side
ode = ca.vertcat(s[1], -g)
# create integrator
opts = {"abstol": 1e-8, "reltol": 1e-8, "max_num_steps": 1000}
integrator = ca.integrator(
"integrator", integrator_type, {"x": s, "ode": ode}, opts
)
# simulating a bouncing ball
sim_time = 2.0
num_steps = 20
dt = sim_time / num_steps
t_log = [0.0]
h_log = [h0]
v_log = [v0]
s_current = ca.DM([h0, v0])
t_current = 0.0
for _ in range(num_steps):
# integrate for one step
res = integrator(x0=s_current, p=dt)
s_end = res["xf"]
# check if the ball passed through the ground
if s_end[0] < 0:
# some simple bounce handling
s_end[0] = abs(s_end[0]) # reflect position
s_end[1] = -e * s_end[1] # apply coefficient of restitution
t_current += dt
t_log.append(t_current)
h_log.append(s_end[0])
v_log.append(s_end[1])
s_current = s_end
# adding some basic verifications
assert (
len(t_log) == num_steps + 1
), f"Expected {num_steps + 1} time steps, got {len(t_log)}"
assert all(h >= 0 for h in h_log), "Height should never be negative"
assert abs(h_log[0] - h0) < 1e-6, "Initial height should match h0"
assert abs(v_log[0] - v0) < 1e-6, "Initial velocity should match v0"
max_heights = [max(h_log[i:]) for i in range(0, len(h_log), 5)]
assert all(
max_heights[i] >= max_heights[i + 1] for i in range(len(max_heights) - 1)
), "Maximum height should not increase over time"
######################################################################
@pytest.mark.parametrize(
"interp_type, expected_result", [("linear", 6.5), ("bspline", 6.25)]
)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_interpolant(selenium, interp_type, expected_result):
import casadi as ca
import numpy as np
x = [0, 1, 2, 3, 4, 5]
y = [0, 1, 4, 9, 16, 25]
F = ca.interpolant("F", interp_type, [x], y)
test_x = 2.5
result = F(test_x)
assert np.isclose(result, expected_result, atol=1e-6)
# Additiomal test points at edges
assert np.isclose(F(0), 0, atol=1e-6)
assert np.isclose(F(1), 1, atol=1e-6)
assert np.isclose(F(5), 25, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_jacobian(selenium):
import casadi as ca
import numpy as np
x = ca.MX.sym("x", 2)
f = ca.Function("f", [x], [ca.vertcat(x[0] ** 2 + x[1] ** 2, x[0] * x[1])])
# compute Jacobian symbolically
J_sym = ca.jacobian(f(x), x)
J = ca.Function("J", [x], [J_sym])
result = J([3, 4])
expected_jac = np.array([[6, 8], [4, 3]])
assert np.allclose(result.full(), expected_jac, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_ode_rk4(selenium):
import casadi as ca
import numpy as np
# use a simple ODE: dx/dt = -x
x = ca.MX.sym("x")
t = ca.MX.sym("t")
ode = {"x": x, "t": t, "ode": -x}
# create an integrator using RK4 (which doesn't require CVODES)
F = ca.integrator("F", "rk", ode, {"t0": 0, "tf": 1})
result = F(x0=1)
expected = np.exp(-1)
assert np.isclose(result["xf"].full()[0], expected, rtol=1e-6, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_forward_sensitivity(selenium):
import casadi as ca
import numpy as np
x = ca.SX.sym("x", 2)
p = ca.SX.sym("p")
f = (x[0] - 2) ** 2 + (x[1] - p) ** 2
F = ca.Function("F", [x, p], [f])
# Compute Jacobian with respect to p
J = ca.Function("J", [x, p], [ca.jacobian(F(x, p), p)])
x_nom = [1, 1]
p_nom = 1
sens = J(x_nom, p_nom)
# The sensitivity should be 2*(x[1] - p) = 2*(1 - 1) = 0
assert np.isclose(sens.full()[0, 0], 0, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_adjoint_sensitivity(selenium):
import casadi as ca
import numpy as np
x = ca.SX.sym("x", 2)
p = ca.SX.sym("p")
f = (x[0] - 2) ** 2 + (x[1] - p) ** 2
F = ca.Function("F", [x, p], [f])
# Compute gradient with respect to all inputs
G = ca.Function("G", [x, p], [ca.gradient(F(x, p), ca.vertcat(x, p))])
x_nom = [1, 1]
p_nom = 1
sens = G(x_nom, p_nom)
expected = [2 * (1 - 2), 2 * (1 - 1), -2 * (1 - 1)]
assert np.allclose(sens.full().flatten(), expected, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_gradient_computation(selenium):
import casadi as ca
import numpy as np
x = ca.SX.sym("x", 2)
f = x[0] ** 2 + x[1] ** 2
F = ca.Function("F", [x], [f])
# Compute gradient
G = ca.Function("G", [x], [ca.gradient(F(x), x)])
x_nom = [1, 2]
grad = G(x_nom)
expected = [2 * 1, 2 * 2]
assert np.allclose(grad.full().flatten(), expected, atol=1e-6)
@run_in_pyodide(packages=["casadi", "numpy"])
def test_hessian_computation(selenium):
import casadi as ca
import numpy as np
x = ca.SX.sym("x", 2)
f = x[0] ** 2 + x[1] ** 2
F = ca.Function("F", [x], [f])
# Compute Hessian of the function
H = ca.Function("H", [x], [ca.hessian(F(x), x)[0]])
x_nom = [1, 2]
hess = H(x_nom)
expected = [[2, 0], [0, 2]]
assert np.allclose(hess.full(), expected, atol=1e-6)

View File

@ -0,0 +1,11 @@
package:
name: cpp-exceptions-test2
version: "1.0"
tag:
- core
- pyodide.test
source:
path: src
build:
cxxflags: -fexceptions
ldflags: -fexceptions

View File

@ -0,0 +1,13 @@
#include "Python.h"
#include <stdexcept>
extern "C" __attribute__((visibility("default"))) PyObject*
PyInit_cpp_exceptions_test2()
{
try {
throw std::runtime_error("something bad?");
} catch (const std::exception& e) {
PyErr_SetString(PyExc_ImportError, "oops");
}
return nullptr;
}

View File

@ -0,0 +1,16 @@
from setuptools import Extension, setup
setup(
name="cpp-exceptions-test2",
version="1.0",
ext_modules=[
Extension(
name="cpp_exceptions_test2", # as it would be imported
# may include packages/namespaces separated by `.`
language="c++",
sources=[
"cpp_exceptions_test2.cpp"
], # all sources are compiled into a single binary file
),
],
)

16
packages/crc32c/meta.yaml Normal file
View File

@ -0,0 +1,16 @@
package:
name: crc32c
version: "2.4"
top-level:
- crc32c
source:
url: https://files.pythonhosted.org/packages/6f/19/47ac8d1d5b81a83272fe56d4cf425274437fd619ed0af9a5f9805484748c/crc32c-2.4.tar.gz
sha256: d985c4d9b1a1fd16c593d83f8735a8e4e156790a95338a1e0b199aac51ca1e5e
about:
home: https://github.com/ICRAR/crc32c
PyPI: https://pypi.org/project/crc32c
summary: A python package implementing the crc32c algorithm in hardware and software
license: LGPL-2.1-or-later
extra:
recipe-maintainers:
- agriyakhetarpal

View File

@ -0,0 +1,60 @@
# Test suite for the crc32c Pyodide package, based on the original test suite:
# https://github.com/ICRAR/crc32c/blob/master/test/test_crc32c.py
import pytest
from pytest_pyodide import run_in_pyodide
@run_in_pyodide(packages=["crc32c"])
def test_zero(selenium):
import crc32c
assert crc32c.crc32c(b"") == 0
TEST_DATA = [
("Numbers1", b"123456789", 0xE3069283),
("Numbers2", b"23456789", 0xBFE92A83),
("Numbers3", b"1234567890", 0xF3DBD4FE),
("Phrase", b"The quick brown fox jumps over the lazy dog", 0x22620404),
(
"LongPhrase",
(
b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc omni virtuti vitium contrario nomine opponitur. "
b"Conferam tecum, quam cuique verso rem subicias; Te ipsum, dignissimum maioribus tuis, voluptasne induxit, ut adolescentulus eriperes "
b"P. Conclusum est enim contra Cyrenaicos satis acute, nihil ad Epicurum. Duo Reges: constructio interrete. Tum Torquatus: Prorsus, inquit, assentior;\n"
b"Quando enim Socrates, qui parens philosophiae iure dici potest, quicquam tale fecit? Sed quid sentiat, non videtis. Haec quo modo conveniant, non "
b"sane intellego. Sed ille, ut dixi, vitiose. Dic in quovis conventu te omnia facere, ne doleas. Quod si ita se habeat, non possit beatam praestare "
b"vitam sapientia. Quis suae urbis conservatorem Codrum, quis Erechthei filias non maxime laudat? Primum divisit ineleganter; Huic mori optimum esse "
b"propter desperationem sapientiae, illi propter spem vivere."
),
0xFCB7575A,
),
]
@run_in_pyodide(packages=["crc32c"])
@pytest.mark.parametrize("name, val, checksum", TEST_DATA)
def test_all(selenium, name, val, checksum):
import crc32c
assert crc32c.crc32c(val) == checksum
@run_in_pyodide(packages=["crc32c"])
@pytest.mark.parametrize("name, val, checksum", TEST_DATA)
def test_piece_by_piece(selenium, name, val, checksum):
# The initial CRC value
c = 0
# A generator that yields each byte of the input value
# as a separate byte
def as_individual_bytes(val):
for byte in val:
yield bytes([byte])
for x in as_individual_bytes(val):
import crc32c
c = crc32c.crc32c(x, c)
assert c == checksum

View File

@ -10,15 +10,9 @@ source:
- patches/0001-Tell-rust-lang-libc-that-time_t-is-64-bits.patch
build:
script: |
export OPENSSL_INCLUDE_PATH=$(pkg-config --cflags-only-I --dont-define-prefix openssl)
export OPENSSL_LIBRARY_PATH=$(pkg-config --libs-only-L --dont-define-prefix openssl)
export OPENSSL_DIR=$WASM_LIBRARY_DIR
cflags: |
-Wno-implicit-function-declaration
$(OPENSSL_INCLUDE_PATH)
ldflags: |
$(OPENSSL_LIBRARY_PATH)
-Wl,--no-entry
# Allow linking to native libraries, otherwise libssl and libcrypto will be not linked to the final binary
export RUSTFLAGS="-Z link-native-libraries=yes"
requirements:
run:
- openssl

View File

@ -1,11 +1,11 @@
package:
name: cvxpy-base
version: 1.5.0
version: 1.5.1
top-level:
- cvxpy
source:
url: https://files.pythonhosted.org/packages/06/cd/c2d7c3f4dd08221a10148d0f7402a06a4696b28f14f0464b3216c55ef2e9/cvxpy_base-1.5.0.tar.gz
sha256: 95b4f7817a9462d91dd32e98adfb095e6b36af8983d3d5a08657b1d348b2c656
url: https://files.pythonhosted.org/packages/f8/9b/27b36409e5bfba14bee4de65af0735ea3ce2db5b81d825f33cbfb51873fc/cvxpy_base-1.5.1.tar.gz
sha256: ba4c7cb018c6afac7b779f355b13a61aa5c8dccaad91fa805b98c68ae1b99325
requirements:
run:
# Dependencies that are needed to run the package

13
packages/duckdb/meta.yaml Normal file
View File

@ -0,0 +1,13 @@
package:
name: duckdb
version: 1.0.0
top-level:
- duckdb
source:
url: https://duckdb.github.io/duckdb-pyodide/wheels/duckdb-1.0.0-cp312-cp312-pyodide_2024_0_wasm32.whl
sha256: 02ee0ea70f528e8aa6843f74b1fdd93619a8fb8521ccfb67585e2a68b25e3a39
about:
home: https://github.com/duckdb/duckdb
PyPI: https://pypi.org/project/duckdb
summary: A fast in-process analytical database
license: MIT

View File

@ -0,0 +1,58 @@
import pytest
from pytest_pyodide import run_in_pyodide
from conftest import package_is_built
def skip_if_not_installed(packages):
for package in packages:
if not package_is_built(package):
pytest.skip(f"{package} not built")
def test_duckdb(selenium):
packages = ["duckdb"]
skip_if_not_installed(packages)
selenium.load_package(packages)
@run_in_pyodide
def do_test(selenium):
import duckdb
with duckdb.connect() as con:
(platform,) = con.execute("PRAGMA platform").fetchone()
con.execute("CREATE TEMP TABLE t (id INT, content STRING)")
con.execute("INSERT INTO t VALUES (42, 'hello'), (43, 'world')")
query_result = con.execute(
"SELECT rowid, * FROM t ORDER BY rowid"
).fetchall()
assert "pyodide" in platform
assert "wasm" in platform
assert query_result == [(0, 42, "hello"), (1, 43, "world")]
do_test(selenium)
@pytest.mark.driver_timeout(60)
def test_duckdb_with_pandas(selenium):
packages = ["duckdb", "pandas"]
skip_if_not_installed(packages)
selenium.load_package(packages)
@run_in_pyodide
def do_test(selenium):
import duckdb
import pandas as pd
with duckdb.connect() as con:
df = con.sql("SELECT UNNEST(RANGE(5)) as x ORDER BY x").df()
expected = pd.DataFrame({"x": range(5)})
assert df.equals(expected)
do_test(selenium)

View File

@ -1,13 +1,13 @@
package:
name: gensim
version: 4.3.2
version: 4.3.3
top-level:
- gensim
source:
# Using the GitHub repository as the source instead of PyPI,
# so that cython can be applied to the source code.
url: https://github.com/piskvorky/gensim/archive/refs/tags/4.3.2.tar.gz
sha256: 9c3e471e52ea47f669873ff56c8606b99ad09cf2e31ccf232af5ace212e84167
url: https://github.com/piskvorky/gensim/archive/refs/tags/4.3.3.tar.gz
sha256: a0787f45b42829af77022469c57b10b5bdf106fa66fa0f75e3bcbb387be55c82
patches:
- patches/0001-Avoid-signature-mismatch-in-sdot-detection.patch
requirements:

View File

@ -6,17 +6,22 @@ package:
top-level:
- _hashlib
source:
sha256: $(PYTHON_ARCHIVE_SHA256)
url: $(PYTHON_ARCHIVE_URL)
path: src
build:
type: cpython_module
script: |
emcc $STDLIB_MODULE_CFLAGS -c Modules/_hashopenssl.c -o Modules/_hashlib.o \
wget ${PYTHON_ARCHIVE_URL} -O Python-${PYVERSION}.tgz
tar -xf Python-${PYVERSION}.tgz
cd Python-${PYVERSION}
emcc $STDLIB_MODULE_CFLAGS -c Modules/_hashopenssl.c -o _hashlib.o \
$(pkg-config --cflags --dont-define-prefix libcrypto) -DOPENSSL_THREADS
emcc Modules/_hashlib.o -o $DISTDIR/_hashlib.so $SIDE_MODULE_LDFLAGS \
emcc _hashlib.o -o _hashlib.so $SIDE_MODULE_LDFLAGS \
$(pkg-config --libs --dont-define-prefix libcrypto) -DOPENSSL_THREADS
cp _hashlib.so ${PKG_BUILD_DIR}/_hashlib.so
requirements:
run:
- openssl

View File

@ -0,0 +1,23 @@
[project]
name = "hashlib"
authors = [
{ name="Pyodide"},
]
description = "Unvendored hashlib for Pyodide"
version = "1.0.0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
ignore-vcs = true
[tool.hatch.build.targets.wheel]
ignore-vcs = true
include = [
"_hashlib.so",
]
exclude = [
"Python-*",
]

View File

@ -1,11 +1,11 @@
package:
name: lakers-python
version: 0.3.0
version: 0.3.3
top-level:
- lakers
source:
url: https://files.pythonhosted.org/packages/29/93/5d70b035f987a48dd854c1afc21025fb8446aae4d43c685b68691175623c/lakers_python-0.3.0.tar.gz
sha256: 009fc5e31b5a9a276216ff43ffd097004396a2a9131359a1da35d464e599cd1c
url: https://files.pythonhosted.org/packages/0b/53/4c942f81eb87be878f82331b63c04c7bff6268a837403837a07dfe129e7a/lakers_python-0.3.3.tar.gz
sha256: c0b3cfbc82478bde7dedcf06db275bdce328656361660bae7f527e6de617550c
requirements:
executable:
- rustup

View File

@ -1,11 +1,11 @@
package:
name: libcst
version: 1.3.1
version: 1.4.0
top-level:
- libcst
source:
url: https://files.pythonhosted.org/packages/f5/7e/11e25b1fc11bcad6b3f3a90fe515406387fe02e6b1ad36dea00ec125ca98/libcst-1.3.1.tar.gz
sha256: 03b1df1ae02456f1d465fcd5ead1d0d454bb483caefd8c8e6bde515ffdb53d1b
url: https://files.pythonhosted.org/packages/e4/bd/ff41d7a8efc4f60a61d903c3f9823565006f44f2b8b11c99701f552b0851/libcst-1.4.0.tar.gz
sha256: 449e0b16604f054fa7f27c3ffe86ea7ef6c409836fe68fe4e752a1894175db00
about:
home: ""
PyPI: https://pypi.org/project/libcst
@ -13,11 +13,11 @@ about:
A concrete syntax tree with AST-like properties for Python 3.0 through
3.12 programs.
license:
"All contributions towards LibCST are MIT licensed. Some Python files
have been derived from the standard library and are therefore PSF licensed. Modifications
All contributions towards LibCST are MIT licensed. Some Python files have
been derived from the standard library and are therefore PSF licensed. Modifications
on these files are dual licensed (both MIT and PSF). Some Python files have been
taken from dataclasses and are therefore Apache licensed. Modifications on these
files are licensed under Apache 2.0 license."
files are licensed under Apache 2.0 license.
extra:
recipe-maintainers:
- zsol

View File

@ -16,7 +16,7 @@ requirements:
- libxml
build:
type: shared_library
type: static_library
script: |
export PATH=${WASM_LIBRARY_DIR}/bin:${PATH}
@ -25,15 +25,18 @@ build:
# dap + byterange: no libcurl
emconfigure ./configure \
--host=none \
--prefix=${WASM_LIBRARY_DIR} \
--disable-doxygen \
--enable-netcdf-4 \
--disable-dap \
--disable-nczarr \
--disable-byterange \
--disable-dap-remote-tests \
--disable-examples \
--disable-utilities \
--disable-testsets \
--disable-shared \
CFLAGS="-fPIC -I${WASM_LIBRARY_DIR}/include -s USE_ZLIB=1" \
CXXFLAGS="-fPIC -I${WASM_LIBRARY_DIR}/include -s USE_ZLIB=1" \
LDFLAGS="-fPIC -s USE_ZLIB=1"

View File

@ -2,6 +2,7 @@ import pytest
from pytest_pyodide import run_in_pyodide
@pytest.mark.skip_pyproxy_check
@pytest.mark.driver_timeout(60)
@run_in_pyodide(packages=["lightgbm", "numpy"])
def test_train_predict(selenium):

View File

@ -7,18 +7,22 @@ package:
- lzma
- _lzma
source:
sha256: $(PYTHON_ARCHIVE_SHA256)
url: $(PYTHON_ARCHIVE_URL)
path: src
build:
type: cpython_module
script: |
emcc $STDLIB_MODULE_CFLAGS -c Modules/_lzmamodule.c -o Modules/_lzmamodule.o \
wget ${PYTHON_ARCHIVE_URL} -O Python-${PYVERSION}.tgz
tar -xf Python-${PYVERSION}.tgz
cd Python-${PYVERSION}
emcc $STDLIB_MODULE_CFLAGS -c Modules/_lzmamodule.c -o _lzmamodule.o \
$(pkg-config --cflags --dont-define-prefix liblzma)
emcc Modules/_lzmamodule.o -o $DISTDIR/_lzma.so $SIDE_MODULE_LDFLAGS \
emcc _lzmamodule.o -o _lzma.so $SIDE_MODULE_LDFLAGS \
$(pkg-config --libs --dont-define-prefix liblzma)
cp Lib/lzma.py $DISTDIR
cp _lzma.so ${PKG_BUILD_DIR}/_lzma.so
cp Lib/lzma.py ${PKG_BUILD_DIR}/lzma.py
requirements:
host:

View File

@ -0,0 +1,24 @@
[project]
name = "lzma"
authors = [
{ name="Pyodide"},
]
description = "Unvendored lzma for Pyodide"
version = "1.0.0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
ignore-vcs = true
[tool.hatch.build.targets.wheel]
ignore-vcs = true
include = [
"lzma.py",
"_lzma.so",
]
exclude = [
"Python-*",
]

View File

@ -5,9 +5,10 @@ from pytest_pyodide import run_in_pyodide
def test_lzma(selenium):
# TODO: libregrtest.main(["test_lzma"]) doesn't collect any tests for some unknown reason.
import test.test_lzma
import unittest
import test.test_lzma
suite = unittest.TestSuite(
[unittest.TestLoader().loadTestsFromModule(test.test_lzma)]
)

View File

@ -152,7 +152,7 @@ def test_font_manager(selenium):
# get fontlist from build
fontlist_built = json.loads(json.dumps(fm.FontManager(), cls=fm._JSONEncoder))
# reodering list to compare
# reordering list to compare
for list in ("afmlist", "ttflist"):
for fontlist in (fontlist_vendor, fontlist_built):
fontlist[list].sort(key=lambda x: x["fname"])

View File

@ -25,6 +25,10 @@ build:
export PATH=${WASM_LIBRARY_DIR}/bin:${PATH}
export HDF5_DIR=${WASM_LIBRARY_DIR}
echo ${HDF5_DIR}
ldflags: |
-L$(WASM_LIBRARY_DIR)/lib
-lhdf5
-lhdf5_hl
about:
home: https://github.com/Unidata/netcdf4-python
PyPI: https://pypi.org/project/netcdf4

View File

@ -1,30 +0,0 @@
#define NPY_HAVE_ENDIAN_H 1
#define NPY_SIZEOF_SHORT 2
#define NPY_SIZEOF_INT 4
#define NPY_SIZEOF_LONG 4
#define NPY_SIZEOF_FLOAT 4
#define NPY_SIZEOF_COMPLEX_FLOAT 8
#define NPY_SIZEOF_DOUBLE 8
#define NPY_SIZEOF_COMPLEX_DOUBLE 16
#define NPY_SIZEOF_LONGDOUBLE 8
#define NPY_SIZEOF_COMPLEX_LONGDOUBLE 16
#define NPY_SIZEOF_PY_INTPTR_T 4
#define NPY_SIZEOF_OFF_T 4
#define NPY_SIZEOF_PY_LONG_LONG 8
#define NPY_SIZEOF_LONGLONG 8
#define NPY_NO_SMP 0
#define NPY_HAVE_DECL_ISNAN
#define NPY_HAVE_DECL_ISINF
#define NPY_HAVE_DECL_ISFINITE
#define NPY_HAVE_DECL_SIGNBIT
#define NPY_USE_C99_COMPLEX 1
#define NPY_HAVE_COMPLEX_DOUBLE 1
#define NPY_HAVE_COMPLEX_FLOAT 1
#define NPY_HAVE_COMPLEX_LONG_DOUBLE 1
#define NPY_RELAXED_STRIDES_CHECKING 1
#define NPY_USE_C99_FORMATS 1
#define NPY_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif

View File

@ -30,8 +30,8 @@ elseif(OPENCL_INCLUDE_DIR)
else()
set(__opencl_dirs "${OpenCV_SOURCE_DIR}/3rdparty/include/opencl/1.2")
endif()
# extra dependencies for buildin code (OpenCL dir is required for extensions like cl_d3d11.h)
# buildin HAVE_OPENCL is already defined through cvconfig.h
# extra dependencies for building code (OpenCL dir is required for extensions like cl_d3d11.h)
# building HAVE_OPENCL is already defined through cvconfig.h
list(APPEND __builtin_include_dirs "${__opencl_dirs}")
# extra dependencies for

View File

@ -1,6 +1,6 @@
package:
name: openssl
version: 1.1.1n
version: 1.1.1w
tag:
- library
source:
@ -25,6 +25,11 @@ build:
make -j ${PYODIDE_JOBS:-3} libssl.a
emar -d libcrypto.a liblegacy-lib-bn_asm.o liblegacy-lib-des_enc.o liblegacy-lib-fcrypt_b.o
emcc ${SIDE_MODULE_LDFLAGS} libcrypto.a -o libcrypto.so
emcc ${SIDE_MODULE_LDFLAGS} libssl.a -o libssl.so
emcc ${SIDE_MODULE_LDFLAGS} libssl.a libcrypto.so -o libssl.so
make install_sw
mkdir -p ${WASM_LIBRARY_DIR}/lib
# remove static libraries, we will use shared one
rm -f ${WASM_LIBRARY_DIR}/lib/{libcrypto.a,libssl.a}
cp libcrypto.so libssl.so ${WASM_LIBRARY_DIR}/lib
cp libcrypto.so libssl.so ${DISTDIR}

View File

@ -6,7 +6,8 @@ package:
source:
sha256: 048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5
url: https://files.pythonhosted.org/packages/fb/2b/9b9c33ffed44ee921d0967086d653047286054117d584f1b1a7c22ceaf7b/packaging-23.2.tar.gz
patches:
- patches/0001-Add-Pyodide-compatibility.patch
about:
home: https://github.com/pypa/packaging
PyPI: https://pypi.org/project/packaging

View File

@ -0,0 +1,41 @@
From cf62f7f89a6a96321b07e1646b0d757848e10ea4 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Tue, 21 May 2024 07:48:46 -0400
Subject: [PATCH] Add Pyodide compatibility
We are changing our wheel platform tag to pyodide_2024_0 so we need to teach
packaging to map Emscripten platform to this.
---
src/packaging/tags.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/packaging/tags.py b/src/packaging/tags.py
index 6667d29..1c6d07a 100644
--- a/src/packaging/tags.py
+++ b/src/packaging/tags.py
@@ -502,6 +502,13 @@ def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
yield f"linux_{arch}"
+def _emscripten_platforms() -> Iterator[str]:
+ pyodide_abi_version = sysconfig.get_config_var("PYODIDE_ABI_VERSION")
+ if pyodide_abi_version:
+ yield f"pyodide_{pyodide_abi_version}_wasm32"
+ yield from _generic_platforms()
+
+
def _generic_platforms() -> Iterator[str]:
yield _normalize_string(sysconfig.get_platform())
@@ -514,6 +521,8 @@ def platform_tags() -> Iterator[str]:
return mac_platforms()
elif platform.system() == "Linux":
return _linux_platforms()
+ elif platform.system() == "Emscripten":
+ return _emscripten_platforms()
else:
return _generic_platforms()
--
2.34.1

View File

@ -1,13 +1,13 @@
package:
name: pandas
version: 2.2.0
version: 2.2.2
tag:
- min-scipy-stack
top-level:
- pandas
source:
url: https://files.pythonhosted.org/packages/03/d2/6fb05f20ee1b3961c7b283c1f8bafc6de752155d075c5db61c173de0de62/pandas-2.2.0.tar.gz
sha256: 30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2
url: https://files.pythonhosted.org/packages/88/d9/ecf715f34c73ccb1d8ceb82fc01cd1028a65a5f6dbc57bfa6ea155119058/pandas-2.2.2.tar.gz
sha256: 9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54
build:
cflags:
-Werror=implicit-function-declaration -Werror=mismatched-parameter-types

View File

@ -6,9 +6,12 @@ package:
top-level:
- _pydecimal
source:
sha256: $(PYTHON_ARCHIVE_SHA256)
url: $(PYTHON_ARCHIVE_URL)
path: src
build:
type: cpython_module
script: |
cp Lib/_pydecimal.py $DISTDIR
wget ${PYTHON_ARCHIVE_URL} -O Python-${PYVERSION}.tgz
tar -xf Python-${PYVERSION}.tgz
cd Python-${PYVERSION}
cp Lib/_pydecimal.py ${PKG_BUILD_DIR}/_pydecimal.py

View File

@ -0,0 +1,23 @@
[project]
name = "pydecimal"
authors = [
{ name="Pyodide"},
]
description = "Unvendored pydecimal for Pyodide"
version = "1.0.0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
ignore-vcs = true
[tool.hatch.build.targets.wheel]
ignore-vcs = true
include = [
"_pydecimal.py",
]
exclude = [
"Python-*",
]

View File

@ -6,10 +6,12 @@ package:
top-level:
- pydoc_data
source:
sha256: $(PYTHON_ARCHIVE_SHA256)
url: $(PYTHON_ARCHIVE_URL)
path: src
build:
type: cpython_module
script: |
cd Lib
tar --exclude=__pycache__ -cf - pydoc_data | tar -C $DISTDIR -xf -
wget ${PYTHON_ARCHIVE_URL} -O Python-${PYVERSION}.tgz
tar -xf Python-${PYVERSION}.tgz
cd Python-${PYVERSION}/Lib
tar --exclude=__pycache__ -cf - pydoc_data | tar -C ${PKG_BUILD_DIR} -xf -

View File

@ -0,0 +1,23 @@
[project]
name = "pydoc_data"
authors = [
{ name="Pyodide"},
]
description = "Unvendored pydoc_data for Pyodide"
version = "1.0.0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
ignore-vcs = true
[tool.hatch.build.targets.wheel]
ignore-vcs = true
include = [
"pydoc_data/",
]
exclude = [
"Python-*",
]

View File

@ -12,7 +12,7 @@ source:
- patches/0001-wasm_unify_pygame_web_pyodide_static_Freetype_init.patch
build:
script: |
embuilder build sdl2 sdl2_ttf sdl2_image sdl2_mixer sdl2_gfx libjpeg libpng giflib harfbuzz vorbis mpg123 libmodplug freetype --pic
embuilder build sdl2 sdl2_ttf sdl2_image sdl2_mixer sdl2_gfx libjpeg libpng giflib harfbuzz vorbis mpg123 libmodplug freetype libhtml5 --pic
export SDL_CONFIG=$(em-config CACHE)/sysroot/bin/sdl2-config
cflags: |
-sRELOCATABLE=1
@ -80,6 +80,7 @@ build:
-lmodplug \
-lmpg123 \
-logg \
-lhtml5 \
${STATIC_OBJS} \
${SHARED_LIBS} \
-o pygame_static.so

View File

@ -1,6 +1,8 @@
import pytest
from pytest_pyodide import run_in_pyodide
from conftest import package_is_built
@pytest.fixture(scope="function")
def selenium_sdl(selenium_standalone):
@ -26,6 +28,31 @@ def test_init(selenium_sdl):
pygame.display.init()
def test_keyboard_input():
"""
Checks if the wheel is importing "emscripten_compute_dom_pk_code" from the main module.
This symbol should not appear in the imports of the wheel, as libhtml5 should be linked to the wheel.
This symbol is used by SDL2 to handle keyboard input.
See: https://github.com/pyodide/pyodide/issues/4805#issuecomment-2169077347
TODO: find a better way to test keyboard input
"""
if not package_is_built("pygame-ce"):
pytest.skip("pygame-ce is not built")
from pathlib import Path
from auditwheel_emscripten import get_imports
dist_dir = Path(pytest.pyodide_dist_dir) # type: ignore[attr-defined]
wheel_path = next(dist_dir.glob("pygame_ce-*.whl"))
assert wheel_path.exists()
all_libs = get_imports(wheel_path)
for imports in all_libs.values():
all_fields = [imp.field for imp in imports]
assert "emscripten_compute_dom_pk_code" not in all_fields
@pytest.mark.driver_timeout(300)
@run_in_pyodide(packages=["pygame-ce", "pygame-ce-tests", "pytest"])
def test_run_tests(selenium_sdl):

View File

@ -0,0 +1,16 @@
package:
name: pyodide-unix-timezones
version: 1.0.0
top-level:
- unix_timezones
source:
url: https://files.pythonhosted.org/packages/f8/ab/637ae2629dc3e9ed7c192fb80f7fdefe311677138a5a5032872a115eb918/pyodide_unix_timezones-1.0.0-py3-none-any.whl
sha256: 9146c0eda703728571d8e3859043b0bb819c9ef45b9f32680234fade2e57b424
about:
home: https://github.com/joemarshall/pyodide-unix-timezones
PyPI: https://pypi.org/project/pyodide-unix-timezones
summary: Helper package to install unix timezone data on Pyodide
license: MIT
extra:
recipe-maintainers:
- joemarshall

View File

@ -16,6 +16,8 @@ requirements:
build:
script: |
embuilder build sqlite3 --pic
export PROJ_VERSION=9.3.1
export PROJ_DIR=${WASM_LIBRARY_DIR}
export PROJ_INCDIR=${WASM_LIBRARY_DIR}/include
@ -23,6 +25,11 @@ build:
export PROJ_WHEEL=1
mkdir -p pyproj/proj_dir/share
cp -r ${WASM_LIBRARY_DIR}/share/proj pyproj/proj_dir/share
cflags: |
-sUSE_SQLITE3
ldflags: |
-sUSE_SQLITE3
-lsqlite3
test:
imports:
- pyproj

View File

@ -0,0 +1,55 @@
# mypy: disable-error-code="no-untyped-def"
"""Taken from test_simple.py in pytest-asyncio"""
import asyncio
from textwrap import dedent
import pytest
from pytest import Pytester
pytest_plugins = "pytester"
async def async_coro():
await asyncio.sleep(0)
return "ok"
def test_event_loop_fixture(event_loop):
"""Test the injection of the event_loop fixture."""
assert event_loop
ret = event_loop.run_until_complete(async_coro())
assert ret == "ok"
@pytest.mark.asyncio
async def test_asyncio_marker():
"""Test the asyncio pytest marker."""
await asyncio.sleep(0)
def test_asyncio_marker_compatibility_with_xfail(pytester: Pytester):
pytester.makepyfile(
dedent(
"""\
import pytest
pytest_plugins = "pytest_asyncio"
@pytest.mark.xfail(reason="need a failure", strict=True)
@pytest.mark.asyncio
async def test_asyncio_marker_fail():
raise AssertionError
"""
)
)
result = pytester.runpytest("--asyncio-mode=strict")
result.assert_outcomes(xfailed=1)
@pytest.mark.asyncio
async def test_asyncio_marker_with_default_param(a_param=None):
"""Test the asyncio pytest marker."""
await asyncio.sleep(0)

View File

@ -0,0 +1,22 @@
package:
name: pytest-asyncio
version: 0.23.7
tag:
- core
- min-scipy-stack
top-level:
- pytest_asyncio
source:
url: https://files.pythonhosted.org/packages/e5/98/947690b1a79af83e584143cb904497caff05bb6016614b38326a81076357/pytest_asyncio-0.23.7-py3-none-any.whl
sha256: 009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b
requirements:
run:
- pytest
about:
home: https://github.com/pytest-dev/pytest-asyncio
PyPI: https://pypi.org/project/pytest-asyncio
summary: Pytest support for asyncio
license: Apache 2.0
extra:
recipe-maintainers:
- agriyakhetarpal

View File

@ -0,0 +1,21 @@
from pytest_pyodide import run_in_pyodide
from conftest import requires_jspi
@run_in_pyodide(packages=["pytest-asyncio"])
def do_test(selenium, contents):
from pathlib import Path
Path("test_pytest_asyncio.py").write_text(contents)
import pytest
assert pytest.main(["test_pytest_asyncio.py"]) == 0
@requires_jspi
def test_pytest_asyncio(selenium):
from pathlib import Path
contents = (Path(__file__).parent / "inner_test_pytest_asyncio.py").read_text()
do_test(selenium, contents)

View File

@ -1,19 +1,41 @@
from pytest_pyodide import run_in_pyodide
@run_in_pyodide(packages=["pytest"])
def do_test(selenium, contents):
from contextlib import redirect_stdout
from io import StringIO
from pathlib import Path
import pytest
Path("test_pytest.py").write_text(contents)
out = StringIO()
with redirect_stdout(out):
result = pytest.main(["test_pytest.py"])
assert result == 1
out.seek(0)
output = out.read()
assert "2 passed" in output, output
assert "1 failed" in output, output
assert "1 warning" in output, output
assert "This is a warning" in output, output
def test_pytest(selenium):
# TODO: don't use numpy in this test as it's not necessarily installed.
selenium.load_package(["pytest", "numpy"])
contents = """
def test_success():
assert 1 == 1
selenium.run(
"""
from pathlib import Path
import os
import numpy
import pytest
def test_warning():
import warnings
warnings.warn("This is a warning")
base_dir = Path(numpy.__file__).parent / "core" / "tests"
"""
)
def test_fail():
assert 1 == 2
"""
selenium.run("pytest.main([str(base_dir / 'test_api.py')])")
logs = "\n".join(selenium.logs)
assert "INTERNALERROR" not in logs
do_test(selenium, contents)

View File

@ -1,11 +1,11 @@
package:
name: python-sat
version: 1.8.dev12
version: 1.8.dev13
top-level:
- pysat
source:
sha256: 91d83422ec97e6d68dafcdbf9fb1015dcfc6b8c67f3883eda95beeca52bb8518
url: https://files.pythonhosted.org/packages/69/ef/bf96e7e9ebe777ab072a72e69f2dd222ace2b68d10356a2feba3fbccac38/python-sat-1.8.dev12.tar.gz
sha256: e9e31bd54ac1f6939433b0bcebb04807138d142187d6ea9dbac1b2240723b642
url: https://files.pythonhosted.org/packages/09/12/fb72411a01ae70d36b4fa5795a45125f1138da066fec66e8e3c66da08747/python-sat-1.8.dev13.tar.gz
patches:
- patches/force_malloc.patch

View File

@ -0,0 +1,43 @@
package:
name: rasterio
version: 1.3.10
top-level:
- rasterio
source:
url: https://github.com/rasterio/rasterio/archive/1.3.10.tar.gz
sha256: 0da4bea271a7f2ef2c44f528245a4f5c76ec635d075a0bd834300c75924b62c5
requirements:
host:
- numpy
- gdal
- libproj
run:
- numpy
- affine
- gdal
- attrs
- certifi
- click
- cligj
# - click-plugins # only for rio cli?
build:
vendor-sharedlib: true
script: |
export PACKAGE_DATA=1
export GDAL_CONFIG=${WASM_LIBRARY_DIR}/bin/gdal-config
export GDAL_DATA=${WASM_LIBRARY_DIR}/share/gdal
export PROJ_LIB=${WASM_LIBRARY_DIR}/share/proj
echo ${GDAL_CONFIG}
echo ${GDAL_DATA}
echo ${PROJ_LIB}
test:
imports:
- rasterio
about:
home: https://github.com/rasterio/rasterio
PyPI: https://pypi.org/project/rasterio
summary: Fast and direct raster I/O for use with Numpy and SciPy
license: BSD
extra:
recipe-maintainers:
- kjmalek

Some files were not shown because too many files have changed in this diff Show More