fix(itkwasm): support the wasmtime-py 48 preopen_dir signature - #1590
Merged
Merged
Conversation
wasmtime-py 48.0.0 replaced WasiConfig.preopen_dir(path, guest_path, dir_perms, file_perms) with WasiConfig.preopen_dir(path, guest_path, fs_mutable=True) and stopped exporting DirPerms and FilePerms. Because pipeline.py imported those names at module scope, the removal broke plain `import itkwasm` with an ImportError, not just pipelines that perform file I/O. Drop the two imports and pass only the path arguments. Read-write is the default on both sides of the break -- DirPerms.READ_WRITE / FilePerms.READ_WRITE on <= 47, fs_mutable=True on 48 -- so the two-argument call is semantically identical across the supported range and no version shim or change to the `wasmtime >= 28.0.0` floor is needed. Every other wasmtime API used here is unchanged on 48: the Config feature flags, WasiConfig.inherit_* / argv, Module.deserialize_file, and Linker.define_wasi. Add test_pipeline_input_output_files_same_directory to cover the case the existing file test misses. When inputs and outputs live in separate directories, each preopen is exercised read-only or write-only; placing both in one directory collapses them to a single preopen that must serve reads and writes, pinning the read-write default this fix now relies on. Verified the test fails when the preopen is made read-only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
thewtex
merged commit Aug 21, 2026
480a6d6
into
InsightSoftwareConsortium:main
69 of 70 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
wasmtime-py48.0.0 removed theDirPermsandFilePermsenums and changed theWasiConfig.preopen_dirsignature:DirPerms/FilePermspreopen_dir(path, guest_path, dir_perms=DirPerms.READ_WRITE, file_perms=FilePerms.READ_WRITE)preopen_dir(path, guest_path, fs_mutable=True)itkwasm/pipeline.pyimported both names at module scope, inside theif sys.platform != "emscripten":block. So on wasmtime-py 48 the failure was notlimited to pipelines that perform file I/O — plain
import itkwasmraisedImportError, breaking the package for every user who picked up the new wasmtime.Changes
Drop the two imports and pass only the path arguments:
Read-write is the default on both sides of the break —
DirPerms.READ_WRITE/FilePerms.READ_WRITEon ≤ 47,fs_mutable=Trueon 48 — so the two-argument call issemantically identical across the whole supported range. That means no conditional
import, no
try/except ImportErrorshim, and no version-sniffing branch; it alsokeeps the existing
wasmtime >= 28.0.0floor inpyproject.tomlvalid, so nodependency bound needed changing.
Every other wasmtime API this module touches was checked against 48.0.0 and is
unchanged: the nine
Configfeature flags (wasm_bulk_memory,wasm_simd,wasm_relaxed_simd,wasm_relaxed_simd_deterministic,wasm_memory64,cranelift_opt_level,strategy,cache,parallel_compilation),WasiConfig.inherit_*/argv,Module.deserialize_file, andLinker.define_wasi.DirPerms/FilePermswere the only casualties.Test coverage
The changed lines were already executed by the existing suite, but line coverage was
misleading here. In
test_pipeline_input_output_filesthe inputs live intest/input/and the outputs in a temporary directory, so the run produces twopreopens, each exercised read-only or write-only. The case where a single
preopen must serve both reads and writes — precisely the read-write default this fix
now leans on — had no coverage.
test_pipeline_input_output_files_same_directorycloses that gap: it copies bothinputs into the temp directory so
preopen_directoriescollapses to one entry thathas to handle reads and writes at once. It carries the same win32
skipifas itssibling test.
To confirm the new test is not vacuous, the preopen was temporarily mutated to
read-only (
preopen_dir(preopen, preopen, False)); both file tests then fail withCould not open outputTxtFile., so the test genuinely pins the semantics rather thanpassing by construction.
Verification
packages/core/python/itkwasm/test/test_pipeline.pywas run against both ends of thesupported range, in isolated environments:
import itkwasmOK, 11 passedimport itkwasmOK, 11 passedtest_pipeline_dask_array_inputwas deselected in both local runs becausedaskisabsent from the minimal verification venvs; it is unrelated to this change and CI
runs it via the full pixi environment.
CodeRabbit review on the diff returned 0 findings.
Notes for reviewers
chorecommit bumping__version__from
1.0b200to1.0b201, so the fix can ship to PyPI.AGENTS.md, the rootREADME.md,nor
packages/core/python/itkwasm/README.mddocuments wasmtime versionconstraints, and this change alters no public API, environment variable, or
developer workflow.
black --checkreportspipeline.pyas unformatted, but it does so on theunmodified file at
mainas well (pre-existing trailing whitespace elsewhere inthe file), and the
blackdiff does not touch the changed region. Left alone hereto keep this fix's diff small.
🤖 Generated with Claude Code