UNPKG

@dodona/papyros

Version:

Scratchpad for multiple programming languages in the browser.

114 lines 4.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Backend, RunMode } from "../../Backend"; import { pyodideExpose, loadPyodideAndPackage } from "pyodide-worker-runner"; /* eslint-disable-next-line */ const pythonPackageUrl = require("./python_package.tar.gz.load_by_url").default; /** * Implementation of a Python backend for Papyros * Powered by Pyodide (https://pyodide.org/) */ export class PythonWorker extends Backend { constructor() { super(); this.pyodide = {}; this.papyros = {}; this.installPromise = null; } static convert(data) { return data.toJs ? data.toJs({ dict_converter: Object.fromEntries }) : data; } /** * @return {any} Function to expose a method with Pyodide support */ syncExpose() { return pyodideExpose; } static getPyodide() { return __awaiter(this, void 0, void 0, function* () { return yield loadPyodideAndPackage({ url: pythonPackageUrl, format: ".tgz" }); }); } launch(onEvent, onOverflow) { const _super = Object.create(null, { launch: { get: () => super.launch } }); return __awaiter(this, void 0, void 0, function* () { yield _super.launch.call(this, onEvent, onOverflow); this.pyodide = yield PythonWorker.getPyodide(); // Python calls our function with a PyProxy dict or a Js Map, // These must be converted to a PapyrosEvent (JS Object) to allow message passing this.papyros = this.pyodide.pyimport("papyros").Papyros.callKwargs({ callback: (e) => { const converted = PythonWorker.convert(e); return this.onEvent(converted); }, buffer_constructor: (cb) => { this.queue.setCallback(cb); return this.queue; } }); // preload micropip to allow installing packages yield this.pyodide.loadPackage("micropip"); }); } /** * Helper method to install imports and prevent race conditions with double downloading * @param {string} code The code containing import statements */ installImports(code) { return __awaiter(this, void 0, void 0, function* () { if (this.installPromise == null) { this.installPromise = this.papyros.install_imports.callKwargs({ source_code: code, ignore_missing: true }); } yield this.installPromise; this.installPromise = null; }); } runModes(code) { let modes = super.runModes(code); if (this.papyros.has_doctests(code)) { modes = [RunMode.Doctest, ...modes]; } modes = [RunMode.Debug, ...modes]; return modes; } runCode(extras_1, code_1) { return __awaiter(this, arguments, void 0, function* (extras, code, mode = "exec") { this.extras = extras; if (extras.interruptBuffer) { this.pyodide.setInterruptBuffer(extras.interruptBuffer); } yield this.installImports(code); return yield this.papyros.run_async.callKwargs({ source_code: code, mode: mode }); }); } lintCode(code) { return __awaiter(this, void 0, void 0, function* () { yield this.installImports(code); return PythonWorker.convert(this.papyros.lint(code)); }); } provideFiles(inlineFiles, hrefFiles) { return __awaiter(this, void 0, void 0, function* () { yield this.papyros.provide_files.callKwargs({ inline_files: JSON.stringify(inlineFiles), href_files: JSON.stringify(hrefFiles) }); }); } } //# sourceMappingURL=PythonWorker.js.map