moth/theme/workspace/python.mjs

79 lines
2.0 KiB
JavaScript

import * as pyodide from "https://cdn.jsdelivr.net/npm/pyodide@0.25.1/pyodide.mjs" // v0.16.1 known good
const HOME = "/home/web_user"
async function createInstance() {
let instance = await pyodide.loadPyodide()
instance.runPython("import sys")
self.postMessage({type: "loaded"})
return instance
}
const initialized = createInstance()
class Buffer {
constructor() {
this.buf = []
}
write(s) {
this.buf.push(s)
}
value() {
return this.buf.join("")
}
}
async function handleMessage(event) {
let data = event.data
let instance = await initialized
let fs = instance._module.FS
let ret = {
result: null,
answer: null,
stdout: null,
stderr: null,
traceback: null,
}
switch (data.type) {
case "nop":
// You might want to do nothing in order to display to the user that a run can now be handled
break
case "run":
let sys = instance.globals.get("sys")
sys.stdout = new Buffer()
sys.stderr = new Buffer()
instance.globals.set("setanswer", (s) => {ret.answer = s})
try {
ret.result = await instance.runPythonAsync(data.code)
} catch (err) {
ret.traceback = err
}
ret.stdout = sys.stdout.value()
ret.stderr = sys.stderr.value()
break
case "wget":
let url = data.url
let dir = data.directory || fs.cwd()
let filename = url.split("/").pop()
let path = dir + "/" + filename
if (fs.analyzePath(path).exists) {
fs.unlink(path)
}
fs.createLazyFile(dir, filename, url, true, false)
break
default:
ret.result = "Unknown message type: " + data.type
break
}
if (data.channel) {
data.channel.postMessage(ret)
}
}
self.addEventListener("message", e => handleMessage(e))