Skip to content

Commit

Permalink
Support top-level await in Python. Fixes #18
Browse files Browse the repository at this point in the history
  • Loading branch information
rameshvarun committed Sep 8, 2023
1 parent 119dadf commit 382e6f2
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/blog-cells.css
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,4 @@ script[type="text/notebook-cell"] {

margin-top: 25px;
margin-bottom: 25px;
}
}
4 changes: 2 additions & 2 deletions src/blog-cells.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { JavaScriptKernel } from "./javascript-kernel";
import { PythonKernel } from "./python-kernel";
import { Kernel } from "./kernel";

export { JavaScriptKernel, PythonKernel};
export { JavaScriptKernel, PythonKernel };

// Register kernels by name and lazily initialize them.
class KernelFactory {
Expand All @@ -31,7 +31,7 @@ class KernelFactory {
if (this.kernels.has(name)) {
return this.kernels.get(name)!;
}

if (this.initializers.has(name)) {
const kernel = this.initializers.get(name)!();
this.kernels.set(name, kernel);
Expand Down
10 changes: 7 additions & 3 deletions src/kernel.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { LanguageSupport } from "@codemirror/language";

export type OutputLine = {
type: 'log' | 'error' | 'warn';
type: "log" | "error" | "warn";
line: string;
};

export abstract class Kernel {
requestID: number = 0;
getRequestID() {
return this.requestID++;
return this.requestID++;
}

abstract run(code: string, onOutput: (line: OutputLine) => void, onDone: () => void);
abstract run(
code: string,
onOutput: (line: OutputLine) => void,
onDone: () => void
);
abstract getSyntaxHighlighter(): LanguageSupport;
}
76 changes: 42 additions & 34 deletions src/python-kernel/worker.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
importScripts("https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js");
declare var loadPyodide;

let onStdout: ((str) => void) | null = null;

// Start loading Pyodide asynchronously.
// Start loading Pyodide immediately.
const loadPython = (async () => {
let pyodide = await loadPyodide({
stdout: (msg) => {
if (msg === "Python initialization complete") return;
if (onStdout) onStdout(msg);
},
});
let pyodide = await loadPyodide();

// Install micropip by default. Users can install
// additional packages using `micropip.install()`.
Expand All @@ -19,40 +12,55 @@ const loadPython = (async () => {
return pyodide;
})();

class PythonExecutor {
ready: Promise<void>;

constructor() {
this.ready = Promise.resolve();
}

run(
code,
output: (logType: string, logLine: string) => void = (type, line) => {}
) {
const done = this.ready
.then(async () => {
const pyodide = await loadPython;
pyodide.setStdout({
isatty: false,
batched: (line: string) => {
output("log", line);
}
});
await pyodide.runPythonAsync(code);
pyodide.setStdout({});
})
.catch((error) => {
output("error", error.toString());
});
this.ready = done;
return done;
}
}

const pyExecutor = new PythonExecutor();

self.onmessage = async (e: MessageEvent) => {
console.log("Worker received message: %o", e);
const requestID = e.data.requestID;

if (e.data.kind === "run-code") {
// Register stdout callback.
onStdout = (msg) => {
await pyExecutor.run(e.data.code, (type, output) => {
self.postMessage({
kind: "run-code-output",
requestID: requestID,
output: {type: "log", line: msg},
output: {type: type, line: output},
});
};

try {
// Wait for Pyodide to load.
const pyodide = await loadPython;
});

// Run code in a new namespace.
pyodide.runPython(e.data.code);
} catch (error) {
self.postMessage({
kind: "run-code-output",
requestID: requestID,
output: {type: "error", line: error.toString()},
});
} finally {
// Unregister stdout callback.
onStdout = null;

self.postMessage({
kind: "run-code-done",
requestID: requestID,
});
}
self.postMessage({
kind: "run-code-done",
requestID: requestID,
});
}
};

0 comments on commit 382e6f2

Please sign in to comment.