UNPKG

quantcoin-pyodide

Version:

Quantcoin.co Python cells for Starboard Notebook

115 lines (105 loc) 3.4 kB
import { PyodideModule } from "./pyodide"; // Regexp for validating package name and URI const PACKAGE_REGEX = '[a-z0-9_][a-z0-9_\-]*'; const PACKAGE_URI_REGEXP = new RegExp('^https?://.*?(' + PACKAGE_REGEX + ').js$', 'i'); const PACKAGE_NAME_REGEXP = new RegExp('^' + PACKAGE_REGEX + '$', 'i'); const PUBLIC_API = [ 'globals', 'loadPackage', 'loadedPackages', 'pyimport', 'repr', 'runPython', 'runPythonAsync', 'checkABI', 'version', 'autocomplete', ]; export function uriToPackageName(packageUri: string) { // Generate a unique package name from URI if (PACKAGE_NAME_REGEXP.test(packageUri)) { return packageUri; } const matches = PACKAGE_URI_REGEXP.exec(packageUri) if (matches !== null) { // Get the regexp group corresponding to the package name return matches[1]; } else { return null; } } export function getBaseUrl() { var baseUrl = self.pyodideArtifactsUrl || self.languagePluginUrl || 'https://cdn.quantcoin.io/pyodide/v0.15.0/full/'; baseUrl = baseUrl.substr(0, baseUrl.lastIndexOf('/')) + '/'; return baseUrl; } export function loadScript(url: string, onload: () => any, onerror: () => any) { if (self.document) { // browser const script = self.document.createElement('script'); script.src = url; script.onload = (e) => { onload(); }; script.onerror = (e: string | Event) => { onerror(); }; self.document.head.appendChild(script); } else if ((self as any).importScripts) { // webworker try { (self as any).importScripts(url); onload(); } catch { onerror(); } } } export function fixRecursionLimit(pyodide: {runPython: (code: string) => any}) { // The Javascript/Wasm call stack may be too small to handle the default // Python call stack limit of 1000 frames. This is generally the case on // Chrom(ium), but not on Firefox. Here, we determine the Javascript call // stack depth available, and then divide by 50 (determined heuristically) // to set the maximum Python call stack depth. let depth = 0; function recurse() { depth += 1; recurse(); } try { recurse(); } catch (err) { ; } let recursionLimit = depth / 50; if (recursionLimit > 1000) { recursionLimit = 1000; } pyodide.runPython(`import sys; sys.setrecursionlimit(int(${recursionLimit}))`); }; export function makePublicAPI(module: any) { const namespace: {_module: any, [key: string]: any} = {_module : module}; for (const name of PUBLIC_API) { namespace[name] = module[name]; } return namespace; } export async function preloadWasm(pyodideModule: PyodideModule) { const FS = self.pyodide._module.FS; const recurseDir = async (rootPath: string) => { let dirs; try { dirs = FS.readdir(rootPath); } catch { return; } for (let entry of dirs) { if (entry.startsWith('.')) { continue; } const path = rootPath + entry; if (entry.endsWith('.so')) { if (pyodideModule.preloadedWasm[path] === undefined) { pyodideModule.preloadedWasm[path] = await pyodideModule.loadWebAssemblyModule(FS.readFile(path), {loadAsync: true}); } } else if (FS.isDir(FS.lookupPath(path).node.mode)) { await recurseDir(path + '/'); } } } await recurseDir('/'); }