Skip to content

fix(itkwasm): support the wasmtime-py 48 preopen_dir signature - #1590

Merged
thewtex merged 2 commits into
InsightSoftwareConsortium:mainfrom
thewtex:dirperms
Aug 21, 2026
Merged

thewtex merged 2 commits into
InsightSoftwareConsortium:mainfrom
thewtex:dirperms

Conversation

@thewtex

@thewtex thewtex commented Aug 21, 2026

Copy link
Copy Markdown
Member

Problem

wasmtime-py 48.0.0 removed the DirPerms and FilePerms enums and changed the
WasiConfig.preopen_dir signature:

wasmtime-py signature exports DirPerms / FilePerms
28.0.0 – 47.x preopen_dir(path, guest_path, dir_perms=DirPerms.READ_WRITE, file_perms=FilePerms.READ_WRITE) yes
48.0.0 preopen_dir(path, guest_path, fs_mutable=True) no

itkwasm/pipeline.py imported both names at module scope, inside the
if sys.platform != "emscripten": block. So on wasmtime-py 48 the failure was not
limited to pipelines that perform file I/O — plain import itkwasm raised
ImportError, breaking the package for every user who picked up the new wasmtime.

Changes

Drop the two imports and pass only the path arguments:

for preopen in preopen_directories:
    wasi_config.preopen_dir(preopen, preopen)

Read-write is the default on both sides of the breakDirPerms.READ_WRITE /
FilePerms.READ_WRITE on ≤ 47, fs_mutable=True on 48 — so the two-argument call is
semantically identical across the whole supported range. That means no conditional
import, no try/except ImportError shim, and no version-sniffing branch; it also
keeps the existing wasmtime >= 28.0.0 floor in pyproject.toml valid, so no
dependency bound needed changing.

Every other wasmtime API this module touches was checked against 48.0.0 and is
unchanged: the nine Config feature 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, and Linker.define_wasi.
DirPerms / FilePerms were 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_files the inputs live in
test/input/ and the outputs in a temporary directory, so the run produces two
preopens, 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_directory closes that gap: it copies both
inputs into the temp directory so preopen_directories collapses to one entry that
has to handle reads and writes at once. It carries the same win32 skipif as its
sibling 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 with
Could not open outputTxtFile., so the test genuinely pins the semantics rather than
passing by construction.

Verification

packages/core/python/itkwasm/test/test_pipeline.py was run against both ends of the
supported range, in isolated environments:

  • wasmtime-py 28.0.0 (dependency floor) — import itkwasm OK, 11 passed
  • wasmtime-py 48.0.0 (the breaking release) — import itkwasm OK, 11 passed

test_pipeline_dask_array_input was deselected in both local runs because dask is
absent 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

  • This branch also contains a separate chore commit bumping __version__
    from 1.0b200 to 1.0b201, so the fix can ship to PyPI.
  • No documentation updates were needed: neither AGENTS.md, the root README.md,
    nor packages/core/python/itkwasm/README.md documents wasmtime version
    constraints, and this change alters no public API, environment variable, or
    developer workflow.
  • black --check reports pipeline.py as unformatted, but it does so on the
    unmodified file at main as well (pre-existing trailing whitespace elsewhere in
    the file), and the black diff does not touch the changed region. Left alone here
    to keep this fix's diff small.

🤖 Generated with Claude Code

thewtex and others added 2 commits August 20, 2026 22:05
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 thewtex changed the title dirperms fix(itkwasm): support the wasmtime-py 48 preopen_dir signature Aug 21, 2026
@thewtex
thewtex merged commit 480a6d6 into InsightSoftwareConsortium:main Aug 21, 2026
69 of 70 checks passed
@thewtex
thewtex deleted the dirperms branch August 21, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant