Neale Pickett
·
2024-04-09
python.mjs
1import * as pyodide from "https://cdn.jsdelivr.net/npm/pyodide@0.25.1/pyodide.mjs" // v0.16.1 known good
2
3const HOME = "/home/web_user"
4
5async function createInstance() {
6 let instance = await pyodide.loadPyodide()
7 instance.runPython("import sys")
8 self.postMessage({type: "loaded"})
9 return instance
10}
11const initialized = createInstance()
12
13class Buffer {
14 constructor() {
15 this.buf = []
16 }
17
18 write(s) {
19 this.buf.push(s)
20 }
21
22 value() {
23 return this.buf.join("")
24 }
25}
26
27async function handleMessage(event) {
28 let data = event.data
29
30 let instance = await initialized
31 let fs = instance._module.FS
32
33 let ret = {
34 result: null,
35 answer: null,
36 stdout: null,
37 stderr: null,
38 traceback: null,
39 }
40
41 switch (data.type) {
42 case "nop":
43 // You might want to do nothing in order to display to the user that a run can now be handled
44 break
45 case "run":
46 let sys = instance.globals.get("sys")
47 sys.stdout = new Buffer()
48 sys.stderr = new Buffer()
49 instance.globals.set("setanswer", (s) => {ret.answer = s})
50
51 try {
52 ret.result = await instance.runPythonAsync(data.code)
53 } catch (err) {
54 ret.traceback = err
55 }
56 ret.stdout = sys.stdout.value()
57 ret.stderr = sys.stderr.value()
58 break
59 case "wget":
60 let url = data.url
61 let dir = data.directory || fs.cwd()
62 let filename = url.split("/").pop()
63 let path = dir + "/" + filename
64
65 if (fs.analyzePath(path).exists) {
66 fs.unlink(path)
67 }
68 fs.createLazyFile(dir, filename, url, true, false)
69 break
70 default:
71 ret.result = "Unknown message type: " + data.type
72 break
73 }
74 if (data.channel) {
75 data.channel.postMessage(ret)
76 }
77}
78self.addEventListener("message", e => handleMessage(e))