Metadata-Version: 2.4
Name: universal-wasm-loader
Version: 1.0.1
Summary: Universal WASM loader for Python
Project-URL: Homepage, https://github.com/jrmarcum/universalWasmLoader-py
Project-URL: Repository, https://github.com/jrmarcum/universalWasmLoader-py
Author-email: Jon Marcum <jrmarcum.se@gmail.com>
License: MIT
License-File: LICENSE
Keywords: canonical-abi,loader,wasm,webassembly,wit
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: wasmtime>=26.0.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.9.0; extra == 'dev'
Description-Content-Type: text/markdown

# universalWasmLoader-py

Universal WASM loader for Python — the Python port of
[universalWasmLoader-js](https://github.com/jrmarcum/universalWasmLoader-js). Loads and
instantiates WebAssembly modules and, when a companion `.wit` file is present, applies the
Canonical ABI so you call WIT exports with idiomatic Python values (`int`/`float`, `bool`,
`str`) instead of raw i32/pointer pairs.

- **PyPI package:** `universal-wasm-loader`
- **WASM runtime:** [`wasmtime`](https://pypi.org/project/wasmtime/) ≥ 26.0.0
- **License:** MIT

## Install

```sh
pip install universal-wasm-loader
```

## Usage

`wasm_import()` loads a `.wasm` module and hands you its exports as a dict of
**ready-to-call Python functions** — pull one out, bind it to a name, and call it
like any other function:

```python
import asyncio
from universal_wasm_loader import wasm_import

async def main():
    # Load the module. Exports come back as a dict of callables.
    exports = await wasm_import("./math.wasm")

    # Turn a WASM export into a Python function and call it.
    # (companion math.wit -> `calculate: func(a: s32, b: s32) -> s32`)
    calculate = exports["calculate"]
    print(calculate(1, 2))        # 3

asyncio.run(main())
```

When a companion `<name>.wit` sits next to the `.wasm`, the **Canonical ABI** is
applied automatically: kebab-case WIT names become camelCase keys, and arguments
and results are idiomatic Python values (`bool`, `str`) — no manual i32/pointer
handling:

```python
# strings_50.wasm + strings_50.wit -> greet, shout, str-len
exports = await wasm_import("./strings_50.wasm")

greet = exports["greet"]
print(greet("World"))             # "Hello, World!"   (str in, str out)
print(exports["strLen"]("hello")) # 5                 (WIT export `str-len`)
```

`create_singleton()` (one shared instance) and `InstancePool()` (N instances for
concurrent workloads) are also exported. See the
[project on GitHub](https://github.com/jrmarcum/universalWasmLoader-py) for the
full API, examples, and source.
