@arminmajerie/datamorph-python-wasm
v0.1.2
Published
Embedded Python execution for the browser via WebAssembly, powered by RustPython
Maintainers
Readme
@arminmajerie/datamorph-python-wasm
Embedded Python execution for the browser via WebAssembly. Powered by RustPython, this package lets you run Python transformation scripts directly in the browser — no server-side Python installation required.
Full documentation: DataMorph Docs — Python Integration
Installation
npm install @arminmajerie/datamorph-python-wasmQuick start
import init, { evaluate_script, validate_script } from '@arminmajerie/datamorph-python-wasm';
// Initialize once
await init();
// Execute a Python script
const context = JSON.stringify({
payload: [
{ name: "widget", price: 10, qty: 3 },
{ name: "gadget", price: 25, qty: 1 },
],
attributes: {},
variables: {},
});
const result = JSON.parse(evaluate_script(`
payload = [
{"name": item["name"].upper(), "total": item["price"] * item["qty"]}
for item in payload
]
`, context));
console.log(result.value);
// [{ name: "WIDGET", total: 30 }, { name: "GADGET", total: 25 }]API
All functions return JSON strings following the same envelope pattern as @arminmajerie/data-morph-wasm:
| Function | Description |
|----------|-------------|
| evaluate_script(script, context_json) | Execute a Python script with the given context. Returns { ok, value, context, stdout }. |
| validate_script(script) | Compile-only syntax check. Returns { ok: true } or { ok: false, error }. |
| register_log_callback(callback) | Register a JS callback for print() output. |
| get_engine_info() | Returns engine metadata (RustPython version, features). |
Context shape
{
"payload": { "key": "value" },
"attributes": { "source": "api" },
"variables": { "env": "production" }
}Scripts receive payload, attributes, and vars as global variables. Assigning to payload changes the output. Modifications to attributes and vars are returned in the result's context field.
Result envelope
// Success
{
"ok": true,
"value": { "transformed": "data" },
"context": {
"payload": { "transformed": "data" },
"attributes": { "source": "api", "processed": true },
"variables": { "env": "production" }
},
"stdout": "Processing complete\n"
}
// Error
{
"ok": false,
"error": "Runtime error: NameError: name 'undefined_var' is not defined"
}Available Python features
The embedded interpreter uses Interpreter::without_stdlib:
Works:
- All builtins:
dict,list,str,int,float,bool,None,tuple,set - Built-in functions:
print,len,range,enumerate,zip,map,filter,sorted,sum,min,max,abs,round,pow,isinstance,hasattr,getattr,setattr - String methods:
.upper(),.lower(),.strip(),.split(),.join(),.replace(),.find(),.startswith(),.endswith(),.format(), f-strings - List/dict/set comprehensions, generator expressions
- Control flow:
if/elif/else,for/while,try/except/finally - Functions:
def,lambda,*args,**kwargs - Classes:
class, inheritance,__init__, methods
Does not work:
importstatements (no stdlib:json,re,datetime,os,math, etc.)- C-extension packages (
numpy,pandas,requests) - File I/O, network access,
async/await
JSON conversion happens on the Rust side — you don't need
import json. Python dicts/lists assigned topayloadare automatically serialized to JSON.
Examples
Filtering
payload = [item for item in payload if item["score"] >= 50]Grouping
result = {}
for item in payload:
key = item["category"]
if key not in result:
result[key] = []
result[key].append(item["name"])
payload = resultAttributes and variables
source = attributes["source"]
multiplier = vars["multiplier"]
payload = {
"computed": payload["base"] * multiplier,
"origin": source,
}
attributes["processed"] = True
vars["result_status"] = "done"Error handling
try:
result = payload["value"] / payload["divisor"]
except ZeroDivisionError:
result = None
payload = {"result": result, "error": result is None}Bundler configuration
Vite
import wasm from 'vite-plugin-wasm';
export default defineConfig({
plugins: [wasm()],
build: { target: 'esnext' },
optimizeDeps: {
exclude: ['@arminmajerie/datamorph-python-wasm'],
},
});Webpack 5+
module.exports = {
experiments: {
asyncWebAssembly: true,
},
};Node.js usage (testing)
import { createRequire } from 'node:module';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
const require = createRequire(import.meta.url);
const pkgDir = path.dirname(
require.resolve('@arminmajerie/datamorph-python-wasm/package.json')
);
const mod = await import(path.join(pkgDir, 'datamorph_python_wasm.js'));
const wasmBuffer = await readFile(path.join(pkgDir, 'datamorph_python_wasm_bg.wasm'));
await mod.default({ module_or_path: wasmBuffer });
const result = JSON.parse(
mod.evaluate_script('payload = payload * 2', JSON.stringify({ payload: 21 }))
);
console.log(result.value); // 42Related packages
| Package | Description | |---------|-------------| | @arminmajerie/data-morph-wasm | DataMorph transformation engine (WASM) | | @arminmajerie/datamorph-python-wasm | Python execution engine (this package) |
Documentation
- Python Integration Guide — full API reference, examples, and feature matrix
- WASM / Browser Guide — DataMorph WASM integration
- Playground — try Python scripts in the browser
- DataMorph Docs — complete documentation
License
MIT OR Apache-2.0
