pyodide/test_wheel: make it support modular wheels

This commit is contained in:
Andrej730
2026-08-06 19:13:30 +05:00
parent 47812b2d32
commit e044b865dd
9 changed files with 100 additions and 19 deletions
+5 -8
View File
@@ -84,16 +84,13 @@ jobs:
- name: Run wheel tests
run: |
cp -r IfcOpenShell/pyodide/test test
# venv set up in build_pyodide.sh.
source .venv/bin/activate
uv pip install pytest-pyodide
PYODIDE_ROOT_DIST=`pyodide config get pyodide_root`/dist
# `pytest-pyodide` requires pyodide in 'pyodide' directory in cwd, when running `pytest`.
cp -r $PYODIDE_ROOT_DIST test/pyodide
cp dist/ifcopenshell-*.whl test/pyodide
cd test
pytest --capture=no
ln -s "$PWD/dist" IfcOpenShell/dist
ln -s "$PWD/dist-modular" IfcOpenShell/dist-modular
cd IfcOpenShell/pyodide
./run_pytest.py setup
./run_pytest.py run
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
+3
View File
@@ -16,6 +16,9 @@
/src/ifcmax/out/
/src/ifcwrap/out/
/src/ifctester/webapp/public/pyodide/
# pyodide wheels
/dist/
/dist-modular/
/win/BuildDepsCache*.txt
+5
View File
@@ -30,3 +30,8 @@ since it's pure cmake without any additional moving parts.
- it will produce Python package in `IfcOpenShell/ifcopenshell`
- run `pyodide build`
- it will produce a wheel in `IfcOpenShell/dist`
- testing:
- ensure you're in pyodide environment
- `cd IfcOpenshell/pyodide`
- `./run_pytest.py setup`
- `./run_pytest.py run`
View File
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
import argparse
import shlex
import shutil
import subprocess
from pathlib import Path
SCRIPT_DIR = Path(__file__).parent
DIST_DIRS = (
SCRIPT_DIR / "test/pyodide",
SCRIPT_DIR / "test/pyodide-modular",
)
WHEEL_SRCS = (
SCRIPT_DIR / "../dist",
SCRIPT_DIR / "../dist-modular",
)
def run(cmd: list, **kwargs) -> None:
print("$", shlex.join(str(part) for part in cmd))
subprocess.check_call(cmd, **kwargs)
def setup() -> None:
run(["uv", "pip", "install", "pytest-pyodide"])
# Copy pyodide installation so we can modify it locally just for tests.
pyodide_root = subprocess.check_output(["pyodide", "config", "get", "pyodide_root"], text=True).strip()
pyodide_root_dist = Path(pyodide_root) / "dist"
for dist_dir in DIST_DIRS:
if dist_dir.exists():
shutil.rmtree(dist_dir)
shutil.copytree(pyodide_root_dist, dist_dir)
def run_tests() -> None:
for dist_dir, wheel_src in zip(DIST_DIRS, WHEEL_SRCS):
if not wheel_src.exists():
raise RuntimeError(f"error: {wheel_src} does not exist")
# Clean up previous wheels.
for whl in dist_dir.glob("ifcopenshell*.whl"):
whl.unlink()
# Symlink new ones.
for whl in wheel_src.glob("ifcopenshell*.whl"):
(dist_dir / whl.name).symlink_to(whl.resolve())
for dist_dir in DIST_DIRS:
run(["pytest", f"--dist-dir={dist_dir}", "--capture=no"], cwd=SCRIPT_DIR)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("command", choices=["setup", "run"])
args = parser.parse_args()
if args.command == "setup":
setup()
else:
run_tests()
+2
View File
@@ -0,0 +1,2 @@
pyodide
pyodide-modular
View File
+22 -11
View File
@@ -1,18 +1,30 @@
import zipfile
from pathlib import Path
WHEEL_FILENAME = next(
p.name for p in (Path.cwd() / "pyodide").iterdir() if p.name.startswith("ifcopenshell-") and p.suffix == ".whl"
)
from ..order_pyodide_wheel_shared_objects import shared_object_sort_key
def test_ifcopenshell_import(selenium):
def _first_so_name(wheel_path: Path) -> str:
with zipfile.ZipFile(wheel_path) as zf:
for name in zf.namelist():
if name.endswith(".so"):
return Path(name).name
return wheel_path.name
def test_ifcopenshell_import(selenium, request):
dist_dir = Path(request.config.getoption("--dist-dir"))
wheel_paths = list(dist_dir.glob("ifcopenshell*.whl"))
wheel_paths.sort(key=lambda path: shared_object_sort_key(_first_so_name(path), 0))
WHEEL_NAMES = tuple(path.name for path in wheel_paths)
selenium.load_package("micropip")
# Important to test it with `micropip.install`
# without any dependencies loaded to ensure micropip will load them automatically.
selenium.run_async(
f"""
selenium.run_async(f"""
import micropip
await micropip.install(f"./{WHEEL_FILENAME}")
wheel_filenames = {WHEEL_NAMES!r}
for wheel_filename in wheel_filenames:
print(f"Loading {{wheel_filename}}...")
await micropip.install(f"./{{wheel_filename}}")
import ifcopenshell
from pathlib import Path
ifcopenshell.set_plugin_search_paths([str(Path(ifcopenshell.__file__).parent)])
@@ -24,5 +36,4 @@ def test_ifcopenshell_import(selenium):
wall.Name = "Test"
assert wall.Name == "Test", f"Entity name wasn't changed: {{wall}}"
print(wall)
"""
)
""")
+1
View File
@@ -9,6 +9,7 @@ line-length = 120
include = '''
src/.*.pyi?$
|nix/.*.pyi?$
|pyodide/.*.pyi?$
'''
extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/rules/*