A WASM Plugin in Python (componentize-py)¶
A fidius WASM plugin is an ordinary WebAssembly component that implements an
interface's WIT contract. Nothing about it is Rust-specific — any language that
can produce a component works. This guide implements the same greeter
interface as Your First WASM Plugin (Rust)
in Python and loads it through the identical host path. This is the concrete
polyglot payoff of the Component Model (ADR FIDIUS-A-0003, "Path B").
The worked example here is the committed fixture
tests/wasm-fixtures/greeter-py/.
How non-Rust plugins differ from the Rust flow¶
A Rust author gets the WIT generated by the macros. A non-Rust author works from the WIT directly:
- Obtain the interface's
.wit(published by the interface author; the Rust macros emit the same shape — see the WASM Component ABI). - Implement the exported interface in your language.
- Build a component with your toolchain (here,
componentize-py). - Package, sign, and load exactly like any other fidius package.
There is no fidius dependency in the guest — it only has to satisfy the WIT.
Prerequisites¶
componentize-py:pip install componentize-py(the fixture pins0.24.0).wasm-toolsto validate the result — see Set Up the WASM Component Toolchain.
1. The WIT contract¶
This is the greeter interface projected to WIT
(tests/wasm-fixtures/greeter/wit/world.wit). A fallible method maps to
result<T, plugin-error>, a #[wire(raw)] method to list<u8>, and every
plugin exports fidius-interface-hash so the host can verify it matches the
descriptor at load:
package fidius:greeter@1.0.0;
interface greeter {
record plugin-error { code: string, message: string, details: option<string> }
greet: func(name: string) -> string;
add: func(a: s64, b: s64) -> result<s64, plugin-error>;
echo-bytes: func(data: list<u8>) -> list<u8>;
fidius-interface-hash: func() -> u64;
}
world greeter-plugin {
export greeter;
}
2. Implement it in Python¶
componentize-py maps the exported interface to a Python class. Kebab-case WIT
names become snake_case methods; result<T, _> returns the Ok value directly
(raise for the error arm):
# app.py
import os
class Greeter:
"""Implements the exported `greeter` interface."""
def greet(self, name: str) -> str:
return f"Hello, {name}!"
def add(self, a: int, b: int) -> int:
return a + b # the Ok arm of result<s64, plugin-error>
def echo_bytes(self, data: bytes) -> bytes:
return bytes(reversed(data))
def fidius_interface_hash(self) -> int:
# MUST equal the interface's hash — the host rejects a mismatch at load.
return 0x0102_0304_0506_0708
The interface hash must match
fidius-interface-hash is an integrity check: the host compares it to the
descriptor's interface_hash and refuses the plugin on a mismatch. The
interface author publishes the expected value (the Rust macros compute it
from the method signatures). It is not a security boundary — signing is.
3. Build the component¶
componentize-py -d path/to/wit -w greeter-plugin componentize app -o greeter_py.wasm
wasm-tools validate --features component-model greeter_py.wasm
The result is a component exporting fidius:greeter/greeter — the same artifact
shape the Rust plugin produces (it is larger, since it embeds a Python runtime).
4. Package, sign, and load¶
From here it is identical to any fidius package. The [wasm] section names the
component and its capability allow-list:
# greeter-py-pkg/package.toml
[package]
name = "greeter-py-pkg"
version = "0.1.0"
interface = "greeter"
interface_version = 1
runtime = "wasm"
[metadata]
category = "demo"
[wasm]
component = "greeter_py.wasm"
capabilities = []
cp greeter_py.wasm greeter-py-pkg/
fidius package sign --key mykey.secret greeter-py-pkg
fidius package pack greeter-py-pkg
// The host loads it through the SAME API as the Rust guest.
let handle = host.load_wasm("greeter-py-pkg", &Greeter_WASM_DESCRIPTOR)?;
let greeting: String = handle.call_method(0, &("Ada".to_string(),))?;
assert_eq!(greeting, "Hello, Ada!");
The host neither knows nor cares that the component is Python — it loads, sandboxes, and dispatches it exactly like the Rust one. That is the polyglot guarantee.
See also¶
- A WASM Plugin in JavaScript — the same interface, a third language
- Your First WASM Plugin (Rust)
- Capabilities & the WASM Sandbox
- WASM Component ABI