add all web jses (leave out the big data and asm files)
This commit is contained in:
parent
e8868b636f
commit
3b05f4316c
68 changed files with 1408 additions and 0 deletions
1
web/Jinja2.js
Normal file
1
web/Jinja2.js
Normal file
File diff suppressed because one or more lines are too long
1
web/MarkupSafe.js
Normal file
1
web/MarkupSafe.js
Normal file
File diff suppressed because one or more lines are too long
1
web/Pygments.js
Normal file
1
web/Pygments.js
Normal file
File diff suppressed because one or more lines are too long
1
web/astropy.js
Normal file
1
web/astropy.js
Normal file
File diff suppressed because one or more lines are too long
1
web/atomicwrites.js
Normal file
1
web/atomicwrites.js
Normal file
File diff suppressed because one or more lines are too long
1
web/attrs.js
Normal file
1
web/attrs.js
Normal file
File diff suppressed because one or more lines are too long
1
web/autograd.js
Normal file
1
web/autograd.js
Normal file
File diff suppressed because one or more lines are too long
1
web/beautifulsoup4.js
Normal file
1
web/beautifulsoup4.js
Normal file
File diff suppressed because one or more lines are too long
1
web/biopython.js
Normal file
1
web/biopython.js
Normal file
File diff suppressed because one or more lines are too long
1
web/bleach.js
Normal file
1
web/bleach.js
Normal file
File diff suppressed because one or more lines are too long
1
web/cloudpickle.js
Normal file
1
web/cloudpickle.js
Normal file
File diff suppressed because one or more lines are too long
95
web/console.html
Normal file
95
web/console.html
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="https://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery.terminal/js/jquery.terminal.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/jquery.terminal/css/jquery.terminal.min.css" rel="stylesheet"/>
|
||||
<link href="renderedhtml.css" rel="stylesheet"/>
|
||||
<script src="./pyodide_dev.js"></script>
|
||||
<!--<script src="./raylet.js"></script>-->
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
languagePluginLoader.then(() => {
|
||||
function pushCode(line) {
|
||||
handleResult(c.push(line))
|
||||
}
|
||||
|
||||
var term = $('body').terminal(
|
||||
pushCode,
|
||||
{
|
||||
greetings: "Welcome to the Pyodide terminal emulator 🐍",
|
||||
prompt: "[[;red;]>>> ]"
|
||||
}
|
||||
);
|
||||
|
||||
window.term = term;
|
||||
pyodide.runPython(`
|
||||
import io, code, sys
|
||||
from js import term, pyodide
|
||||
|
||||
class Console(code.InteractiveConsole):
|
||||
def runcode(self, code):
|
||||
sys.stdout = io.StringIO()
|
||||
sys.stderr = io.StringIO()
|
||||
term.runPython("\\n".join(self.buffer))
|
||||
_c = Console(locals=globals())
|
||||
`)
|
||||
|
||||
var c = pyodide.pyimport('_c')
|
||||
|
||||
function handleResult(result) {
|
||||
if (result) {
|
||||
term.set_prompt('[[;gray;]... ]')
|
||||
} else {
|
||||
term.set_prompt('[[;red;]>>> ]')
|
||||
var stderr = pyodide.runPython("sys.stderr.getvalue()").trim()
|
||||
if (stderr) {
|
||||
term.echo(`[[;red;]${stderr}]`)
|
||||
} else {
|
||||
var stdout = pyodide.runPython("sys.stdout.getvalue()")
|
||||
if (stdout) {
|
||||
term.echo(stdout.trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
term.runPython = function(code) {
|
||||
pyodide.runPythonAsync(code).then(
|
||||
term.handlePythonResult, term.handlePythonError
|
||||
)
|
||||
}
|
||||
|
||||
term.handlePythonResult = function(result) {
|
||||
if (result === undefined) {
|
||||
return
|
||||
} else if (result['_repr_html_'] !== undefined) {
|
||||
term.echo(result['_repr_html_'], {raw: true})
|
||||
} else {
|
||||
term.echo(result.toString())
|
||||
}
|
||||
}
|
||||
|
||||
term.handlePythonError = function(result) {
|
||||
term.error(result.toString())
|
||||
}
|
||||
|
||||
pyodide.loadPackage(["micropip", "cloudpickle"]).then( () =>
|
||||
pyodide.runPythonAsync(`
|
||||
import micropip
|
||||
import js
|
||||
wheel_path = js.window.location.protocol + "//" + js.window.location.host + "/ray_web-0.0.1-py3-none-any.whl"
|
||||
micropip.install(wheel_path)
|
||||
`).then( () => {
|
||||
term.echo("from ray import ray")
|
||||
pushCode("from ray import ray")
|
||||
term.echo("ray.connect()")
|
||||
pushCode("ray.connect()")
|
||||
})
|
||||
)
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
web/cssselect.js
Normal file
1
web/cssselect.js
Normal file
File diff suppressed because one or more lines are too long
1
web/cycler.js
Normal file
1
web/cycler.js
Normal file
File diff suppressed because one or more lines are too long
1
web/cytoolz.js
Normal file
1
web/cytoolz.js
Normal file
File diff suppressed because one or more lines are too long
1
web/decorator.js
Normal file
1
web/decorator.js
Normal file
File diff suppressed because one or more lines are too long
1
web/distlib.js
Normal file
1
web/distlib.js
Normal file
File diff suppressed because one or more lines are too long
1
web/docutils.js
Normal file
1
web/docutils.js
Normal file
File diff suppressed because one or more lines are too long
1
web/freesasa.js
Normal file
1
web/freesasa.js
Normal file
File diff suppressed because one or more lines are too long
1
web/future.js
Normal file
1
web/future.js
Normal file
File diff suppressed because one or more lines are too long
1
web/html5lib.js
Normal file
1
web/html5lib.js
Normal file
File diff suppressed because one or more lines are too long
11
web/index.html
Normal file
11
web/index.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="https://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="./raylet.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
1
web/joblib.js
Normal file
1
web/joblib.js
Normal file
File diff suppressed because one or more lines are too long
1
web/kiwisolver.js
Normal file
1
web/kiwisolver.js
Normal file
File diff suppressed because one or more lines are too long
1
web/lxml.js
Normal file
1
web/lxml.js
Normal file
File diff suppressed because one or more lines are too long
1
web/matplotlib.js
Normal file
1
web/matplotlib.js
Normal file
File diff suppressed because one or more lines are too long
1
web/micropip.js
Normal file
1
web/micropip.js
Normal file
File diff suppressed because one or more lines are too long
1
web/mne.js
Normal file
1
web/mne.js
Normal file
File diff suppressed because one or more lines are too long
1
web/more-itertools.js
Normal file
1
web/more-itertools.js
Normal file
File diff suppressed because one or more lines are too long
1
web/mpmath.js
Normal file
1
web/mpmath.js
Normal file
File diff suppressed because one or more lines are too long
1
web/networkx.js
Normal file
1
web/networkx.js
Normal file
File diff suppressed because one or more lines are too long
1
web/nltk.js
Normal file
1
web/nltk.js
Normal file
File diff suppressed because one or more lines are too long
1
web/nose.js
Normal file
1
web/nose.js
Normal file
File diff suppressed because one or more lines are too long
1
web/numpy.js
Normal file
1
web/numpy.js
Normal file
File diff suppressed because one or more lines are too long
1
web/packages.json
Normal file
1
web/packages.json
Normal file
File diff suppressed because one or more lines are too long
1
web/packaging.js
Normal file
1
web/packaging.js
Normal file
File diff suppressed because one or more lines are too long
1
web/pandas.js
Normal file
1
web/pandas.js
Normal file
File diff suppressed because one or more lines are too long
1
web/patsy.js
Normal file
1
web/patsy.js
Normal file
File diff suppressed because one or more lines are too long
1
web/pluggy.js
Normal file
1
web/pluggy.js
Normal file
File diff suppressed because one or more lines are too long
1
web/py.js
Normal file
1
web/py.js
Normal file
File diff suppressed because one or more lines are too long
1
web/pyodide.asm.data.js
Normal file
1
web/pyodide.asm.data.js
Normal file
File diff suppressed because one or more lines are too long
21
web/pyodide.asm.js
Normal file
21
web/pyodide.asm.js
Normal file
File diff suppressed because one or more lines are too long
465
web/pyodide.js
Normal file
465
web/pyodide.js
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
/**
|
||||
* The main bootstrap script for loading pyodide.
|
||||
*/
|
||||
|
||||
var languagePluginLoader = new Promise((resolve, reject) => {
|
||||
// This is filled in by the Makefile to be either a local file or the
|
||||
// deployed location. TODO: This should be done in a less hacky
|
||||
// way.
|
||||
var baseURL = self.languagePluginUrl || 'https://cdn.jsdelivr.net/pyodide/v0.15.0/full/';
|
||||
baseURL = baseURL.substr(0, baseURL.lastIndexOf('/')) + '/';
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Package loading
|
||||
let loadedPackages = {};
|
||||
var loadPackagePromise = new Promise((resolve) => resolve());
|
||||
// Regexp for validating package name and URI
|
||||
var package_name_regexp = '[a-z0-9_][a-z0-9_\-]*'
|
||||
var package_uri_regexp =
|
||||
new RegExp('^https?://.*?(' + package_name_regexp + ').js$', 'i');
|
||||
var package_name_regexp = new RegExp('^' + package_name_regexp + '$', 'i');
|
||||
|
||||
let _uri_to_package_name = (package_uri) => {
|
||||
// Generate a unique package name from URI
|
||||
|
||||
if (package_name_regexp.test(package_uri)) {
|
||||
return package_uri;
|
||||
} else if (package_uri_regexp.test(package_uri)) {
|
||||
let match = package_uri_regexp.exec(package_uri);
|
||||
// Get the regexp group corresponding to the package name
|
||||
return match[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
let preloadWasm = () => {
|
||||
// On Chrome, we have to instantiate wasm asynchronously. Since that
|
||||
// can't be done synchronously within the call to dlopen, we instantiate
|
||||
// every .so that comes our way up front, caching it in the
|
||||
// `preloadedWasm` dictionary.
|
||||
|
||||
let promise = new Promise((resolve) => resolve());
|
||||
let FS = pyodide._module.FS;
|
||||
|
||||
function recurseDir(rootpath) {
|
||||
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 (Module['preloadedWasm'][path] === undefined) {
|
||||
promise = promise
|
||||
.then(() => Module['loadWebAssemblyModule'](
|
||||
FS.readFile(path), {loadAsync: true}))
|
||||
.then((module) => {
|
||||
Module['preloadedWasm'][path] = module;
|
||||
});
|
||||
}
|
||||
} else if (FS.isDir(FS.lookupPath(path).node.mode)) {
|
||||
recurseDir(path + '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recurseDir('/');
|
||||
|
||||
return promise;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
function loadScript(url, onload, onerror) {
|
||||
if (self.document) { // browser
|
||||
const script = self.document.createElement('script');
|
||||
script.src = url;
|
||||
script.onload = (e) => { onload(); };
|
||||
script.onerror = (e) => { onerror(); };
|
||||
self.document.head.appendChild(script);
|
||||
} else if (self.importScripts) { // webworker
|
||||
try {
|
||||
self.importScripts(url);
|
||||
onload();
|
||||
} catch {
|
||||
onerror();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _loadPackage = (names, messageCallback, errorCallback) => {
|
||||
if (messageCallback == undefined) {
|
||||
messageCallback = () => {};
|
||||
}
|
||||
if (errorCallback == undefined) {
|
||||
errorCallback = () => {};
|
||||
}
|
||||
let _messageCallback = (msg) => {
|
||||
console.log(msg);
|
||||
messageCallback(msg);
|
||||
};
|
||||
let _errorCallback = (errMsg) => {
|
||||
console.error(errMsg);
|
||||
errorCallback(errMsg);
|
||||
};
|
||||
|
||||
// DFS to find all dependencies of the requested packages
|
||||
let packages = self.pyodide._module.packages.dependencies;
|
||||
let loadedPackages = self.pyodide.loadedPackages;
|
||||
let queue = [].concat(names || []);
|
||||
let toLoad = {};
|
||||
while (queue.length) {
|
||||
let package_uri = queue.pop();
|
||||
|
||||
const pkg = _uri_to_package_name(package_uri);
|
||||
|
||||
if (pkg == null) {
|
||||
_errorCallback(`Invalid package name or URI '${package_uri}'`);
|
||||
return;
|
||||
} else if (pkg == package_uri) {
|
||||
package_uri = 'default channel';
|
||||
}
|
||||
|
||||
if (pkg in loadedPackages) {
|
||||
if (package_uri != loadedPackages[pkg]) {
|
||||
_errorCallback(`URI mismatch, attempting to load package ` +
|
||||
`${pkg} from ${package_uri} while it is already ` +
|
||||
`loaded from ${loadedPackages[pkg]}!`);
|
||||
return;
|
||||
} else {
|
||||
_messageCallback(`${pkg} already loaded from ${loadedPackages[pkg]}`)
|
||||
}
|
||||
} else if (pkg in toLoad) {
|
||||
if (package_uri != toLoad[pkg]) {
|
||||
_errorCallback(`URI mismatch, attempting to load package ` +
|
||||
`${pkg} from ${package_uri} while it is already ` +
|
||||
`being loaded from ${toLoad[pkg]}!`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
`${pkg} to be loaded from ${package_uri}`); // debug level info.
|
||||
|
||||
toLoad[pkg] = package_uri;
|
||||
if (packages.hasOwnProperty(pkg)) {
|
||||
packages[pkg].forEach((subpackage) => {
|
||||
if (!(subpackage in loadedPackages) && !(subpackage in toLoad)) {
|
||||
queue.push(subpackage);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_errorCallback(`Unknown package '${pkg}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.pyodide._module.locateFile = (path) => {
|
||||
// handle packages loaded from custom URLs
|
||||
let pkg = path.replace(/\.data$/, "");
|
||||
if (pkg in toLoad) {
|
||||
let package_uri = toLoad[pkg];
|
||||
if (package_uri != 'default channel') {
|
||||
return package_uri.replace(/\.js$/, ".data");
|
||||
};
|
||||
};
|
||||
return baseURL + path;
|
||||
};
|
||||
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
if (Object.keys(toLoad).length === 0) {
|
||||
resolve('No new packages to load');
|
||||
return;
|
||||
}
|
||||
|
||||
let packageList = Array.from(Object.keys(toLoad));
|
||||
_messageCallback(`Loading ${packageList.join(', ')}`)
|
||||
|
||||
// monitorRunDependencies is called at the beginning and the end of each
|
||||
// package being loaded. We know we are done when it has been called
|
||||
// exactly "toLoad * 2" times.
|
||||
var packageCounter = Object.keys(toLoad).length * 2;
|
||||
|
||||
self.pyodide._module.monitorRunDependencies = () => {
|
||||
packageCounter--;
|
||||
if (packageCounter === 0) {
|
||||
for (let pkg in toLoad) {
|
||||
self.pyodide.loadedPackages[pkg] = toLoad[pkg];
|
||||
}
|
||||
delete self.pyodide._module.monitorRunDependencies;
|
||||
self.removeEventListener('error', windowErrorHandler);
|
||||
|
||||
let resolveMsg = `Loaded `;
|
||||
if (packageList.length > 0) {
|
||||
resolveMsg += packageList.join(', ');
|
||||
} else {
|
||||
resolveMsg += 'no packages'
|
||||
}
|
||||
|
||||
if (!isFirefox) {
|
||||
preloadWasm().then(() => {
|
||||
console.log(resolveMsg);
|
||||
resolve(resolveMsg);
|
||||
});
|
||||
} else {
|
||||
console.log(resolveMsg);
|
||||
resolve(resolveMsg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add a handler for any exceptions that are thrown in the process of
|
||||
// loading a package
|
||||
var windowErrorHandler = (err) => {
|
||||
delete self.pyodide._module.monitorRunDependencies;
|
||||
self.removeEventListener('error', windowErrorHandler);
|
||||
// Set up a new Promise chain, since this one failed
|
||||
loadPackagePromise = new Promise((resolve) => resolve());
|
||||
reject(err.message);
|
||||
};
|
||||
self.addEventListener('error', windowErrorHandler);
|
||||
|
||||
for (let pkg in toLoad) {
|
||||
let scriptSrc;
|
||||
let package_uri = toLoad[pkg];
|
||||
if (package_uri == 'default channel') {
|
||||
scriptSrc = `${baseURL}${pkg}.js`;
|
||||
} else {
|
||||
scriptSrc = `${package_uri}`;
|
||||
}
|
||||
_messageCallback(`Loading ${pkg} from ${scriptSrc}`)
|
||||
loadScript(scriptSrc, () => {}, () => {
|
||||
// If the package_uri fails to load, call monitorRunDependencies twice
|
||||
// (so packageCounter will still hit 0 and finish loading), and remove
|
||||
// the package from toLoad so we don't mark it as loaded, and remove
|
||||
// the package from packageList so we don't say that it was loaded.
|
||||
_errorCallback(`Couldn't load package from URL ${scriptSrc}`);
|
||||
delete toLoad[pkg];
|
||||
let packageListIndex = packageList.indexOf(pkg);
|
||||
if (packageListIndex !== -1) {
|
||||
packageList.splice(packageListIndex, 1);
|
||||
}
|
||||
for (let i = 0; i < 2; i++) {
|
||||
self.pyodide._module.monitorRunDependencies();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We have to invalidate Python's import caches, or it won't
|
||||
// see the new files. This is done here so it happens in parallel
|
||||
// with the fetching over the network.
|
||||
self.pyodide.runPython('import importlib as _importlib\n' +
|
||||
'_importlib.invalidate_caches()\n');
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
let loadPackage = (names, messageCallback, errorCallback) => {
|
||||
/* We want to make sure that only one loadPackage invocation runs at any
|
||||
* given time, so this creates a "chain" of promises. */
|
||||
loadPackagePromise = loadPackagePromise.then(
|
||||
() => _loadPackage(names, messageCallback, errorCallback));
|
||||
return loadPackagePromise;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Fix Python recursion limit
|
||||
function fixRecursionLimit(pyodide) {
|
||||
// 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}))`);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Rearrange namespace for public API
|
||||
let PUBLIC_API = [
|
||||
'globals',
|
||||
'loadPackage',
|
||||
'loadedPackages',
|
||||
'pyimport',
|
||||
'repr',
|
||||
'runPython',
|
||||
'runPythonAsync',
|
||||
'checkABI',
|
||||
'version',
|
||||
'autocomplete',
|
||||
];
|
||||
|
||||
function makePublicAPI(module, public_api) {
|
||||
var namespace = {_module : module};
|
||||
for (let name of public_api) {
|
||||
namespace[name] = module[name];
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Loading Pyodide
|
||||
let wasmURL = `${baseURL}pyodide.asm.wasm`;
|
||||
let Module = {};
|
||||
self.Module = Module;
|
||||
|
||||
Module.noImageDecoding = true;
|
||||
Module.noAudioDecoding = true;
|
||||
Module.noWasmDecoding = true;
|
||||
Module.preloadedWasm = {};
|
||||
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
|
||||
let wasm_promise, wasm_fetch = fetch(wasmURL);
|
||||
const compileBuffer = () =>
|
||||
wasm_fetch.then(response => response.arrayBuffer())
|
||||
.then(bytes => WebAssembly.compile(bytes));
|
||||
if (WebAssembly.compileStreaming === undefined) {
|
||||
wasm_promise = compileBuffer();
|
||||
} else {
|
||||
wasm_promise = WebAssembly.compileStreaming(wasm_fetch);
|
||||
wasm_promise = wasm_promise.catch(e => {
|
||||
if (e instanceof TypeError) {
|
||||
console.error("pyodide streaming compilation failed:", e,
|
||||
"- falling back to buffered compilation");
|
||||
return compileBuffer()
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
Module.instantiateWasm = (info, receiveInstance) => {
|
||||
wasm_promise.then(module => WebAssembly.instantiate(module, info))
|
||||
.then(instance => receiveInstance(instance));
|
||||
return {};
|
||||
};
|
||||
|
||||
Module.checkABI = function(ABI_number) {
|
||||
if (ABI_number !== parseInt('1')) {
|
||||
var ABI_mismatch_exception =
|
||||
`ABI numbers differ. Expected 1, got ${ABI_number}`;
|
||||
console.error(ABI_mismatch_exception);
|
||||
throw ABI_mismatch_exception;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Module.autocomplete =
|
||||
function(path) {
|
||||
var pyodide_module = Module.pyimport("pyodide");
|
||||
return pyodide_module.get_completions(path);
|
||||
}
|
||||
|
||||
Module.locateFile = (path) => baseURL + path;
|
||||
var postRunPromise = new Promise((resolve, reject) => {
|
||||
Module.postRun = () => {
|
||||
delete self.Module;
|
||||
fetch(`${baseURL}packages.json`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => {
|
||||
fixRecursionLimit(self.pyodide);
|
||||
self.pyodide.globals =
|
||||
self.pyodide.runPython('import sys\nsys.modules["__main__"]');
|
||||
self.pyodide = makePublicAPI(self.pyodide, PUBLIC_API);
|
||||
self.pyodide._module.packages = json;
|
||||
if (self.iodide !== undefined) {
|
||||
// Perform some completions immediately so there isn't a delay on
|
||||
// the first call to autocomplete
|
||||
self.pyodide.runPython('import pyodide');
|
||||
self.pyodide.runPython('pyodide.get_completions("")');
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
var dataLoadPromise = new Promise((resolve, reject) => {
|
||||
Module.monitorRunDependencies =
|
||||
(n) => {
|
||||
if (n === 0) {
|
||||
delete Module.monitorRunDependencies;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Promise.all([ postRunPromise, dataLoadPromise ]).then(() => resolve());
|
||||
|
||||
const data_script_src = `${baseURL}pyodide.asm.data.js`;
|
||||
loadScript(data_script_src, () => {
|
||||
const scriptSrc = `${baseURL}pyodide.asm.js`;
|
||||
loadScript(scriptSrc, () => {
|
||||
// The emscripten module needs to be at this location for the core
|
||||
// filesystem to install itself. Once that's complete, it will be replaced
|
||||
// by the call to `makePublicAPI` with a more limited public API.
|
||||
self.pyodide = pyodide(Module);
|
||||
self.pyodide.loadedPackages = {};
|
||||
self.pyodide.loadPackage = loadPackage;
|
||||
}, () => {});
|
||||
}, () => {});
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Iodide-specific functionality, that doesn't make sense
|
||||
// if not using with Iodide.
|
||||
if (self.iodide !== undefined) {
|
||||
// Load the custom CSS for Pyodide
|
||||
let link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = `${baseURL}renderedhtml.css`;
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
|
||||
// Add a custom output handler for Python objects
|
||||
self.iodide.addOutputRenderer({
|
||||
shouldRender : (val) => {
|
||||
return (typeof val === 'function' &&
|
||||
pyodide._module.PyProxy.isPyProxy(val));
|
||||
},
|
||||
|
||||
render : (val) => {
|
||||
let div = document.createElement('div');
|
||||
div.className = 'rendered_html';
|
||||
var element;
|
||||
if (val._repr_html_ !== undefined) {
|
||||
let result = val._repr_html_();
|
||||
if (typeof result === 'string') {
|
||||
div.appendChild(new DOMParser()
|
||||
.parseFromString(result, 'text/html')
|
||||
.body.firstChild);
|
||||
element = div;
|
||||
} else {
|
||||
element = result;
|
||||
}
|
||||
} else {
|
||||
let pre = document.createElement('pre');
|
||||
pre.textContent = val.toString();
|
||||
div.appendChild(pre);
|
||||
element = div;
|
||||
}
|
||||
return element.outerHTML;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
languagePluginLoader
|
||||
465
web/pyodide_dev.js
Normal file
465
web/pyodide_dev.js
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
/**
|
||||
* The main bootstrap script for loading pyodide.
|
||||
*/
|
||||
|
||||
var languagePluginLoader = new Promise((resolve, reject) => {
|
||||
// This is filled in by the Makefile to be either a local file or the
|
||||
// deployed location. TODO: This should be done in a less hacky
|
||||
// way.
|
||||
var baseURL = self.languagePluginUrl || './';
|
||||
baseURL = baseURL.substr(0, baseURL.lastIndexOf('/')) + '/';
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Package loading
|
||||
let loadedPackages = {};
|
||||
var loadPackagePromise = new Promise((resolve) => resolve());
|
||||
// Regexp for validating package name and URI
|
||||
var package_name_regexp = '[a-z0-9_][a-z0-9_\-]*'
|
||||
var package_uri_regexp =
|
||||
new RegExp('^https?://.*?(' + package_name_regexp + ').js$', 'i');
|
||||
var package_name_regexp = new RegExp('^' + package_name_regexp + '$', 'i');
|
||||
|
||||
let _uri_to_package_name = (package_uri) => {
|
||||
// Generate a unique package name from URI
|
||||
|
||||
if (package_name_regexp.test(package_uri)) {
|
||||
return package_uri;
|
||||
} else if (package_uri_regexp.test(package_uri)) {
|
||||
let match = package_uri_regexp.exec(package_uri);
|
||||
// Get the regexp group corresponding to the package name
|
||||
return match[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
let preloadWasm = () => {
|
||||
// On Chrome, we have to instantiate wasm asynchronously. Since that
|
||||
// can't be done synchronously within the call to dlopen, we instantiate
|
||||
// every .so that comes our way up front, caching it in the
|
||||
// `preloadedWasm` dictionary.
|
||||
|
||||
let promise = new Promise((resolve) => resolve());
|
||||
let FS = pyodide._module.FS;
|
||||
|
||||
function recurseDir(rootpath) {
|
||||
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 (Module['preloadedWasm'][path] === undefined) {
|
||||
promise = promise
|
||||
.then(() => Module['loadWebAssemblyModule'](
|
||||
FS.readFile(path), {loadAsync: true}))
|
||||
.then((module) => {
|
||||
Module['preloadedWasm'][path] = module;
|
||||
});
|
||||
}
|
||||
} else if (FS.isDir(FS.lookupPath(path).node.mode)) {
|
||||
recurseDir(path + '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recurseDir('/');
|
||||
|
||||
return promise;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
function loadScript(url, onload, onerror) {
|
||||
if (self.document) { // browser
|
||||
const script = self.document.createElement('script');
|
||||
script.src = url;
|
||||
script.onload = (e) => { onload(); };
|
||||
script.onerror = (e) => { onerror(); };
|
||||
self.document.head.appendChild(script);
|
||||
} else if (self.importScripts) { // webworker
|
||||
try {
|
||||
self.importScripts(url);
|
||||
onload();
|
||||
} catch {
|
||||
onerror();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _loadPackage = (names, messageCallback, errorCallback) => {
|
||||
if (messageCallback == undefined) {
|
||||
messageCallback = () => {};
|
||||
}
|
||||
if (errorCallback == undefined) {
|
||||
errorCallback = () => {};
|
||||
}
|
||||
let _messageCallback = (msg) => {
|
||||
console.log(msg);
|
||||
messageCallback(msg);
|
||||
};
|
||||
let _errorCallback = (errMsg) => {
|
||||
console.error(errMsg);
|
||||
errorCallback(errMsg);
|
||||
};
|
||||
|
||||
// DFS to find all dependencies of the requested packages
|
||||
let packages = self.pyodide._module.packages.dependencies;
|
||||
let loadedPackages = self.pyodide.loadedPackages;
|
||||
let queue = [].concat(names || []);
|
||||
let toLoad = {};
|
||||
while (queue.length) {
|
||||
let package_uri = queue.pop();
|
||||
|
||||
const pkg = _uri_to_package_name(package_uri);
|
||||
|
||||
if (pkg == null) {
|
||||
_errorCallback(`Invalid package name or URI '${package_uri}'`);
|
||||
return;
|
||||
} else if (pkg == package_uri) {
|
||||
package_uri = 'default channel';
|
||||
}
|
||||
|
||||
if (pkg in loadedPackages) {
|
||||
if (package_uri != loadedPackages[pkg]) {
|
||||
_errorCallback(`URI mismatch, attempting to load package ` +
|
||||
`${pkg} from ${package_uri} while it is already ` +
|
||||
`loaded from ${loadedPackages[pkg]}!`);
|
||||
return;
|
||||
} else {
|
||||
_messageCallback(`${pkg} already loaded from ${loadedPackages[pkg]}`)
|
||||
}
|
||||
} else if (pkg in toLoad) {
|
||||
if (package_uri != toLoad[pkg]) {
|
||||
_errorCallback(`URI mismatch, attempting to load package ` +
|
||||
`${pkg} from ${package_uri} while it is already ` +
|
||||
`being loaded from ${toLoad[pkg]}!`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
`${pkg} to be loaded from ${package_uri}`); // debug level info.
|
||||
|
||||
toLoad[pkg] = package_uri;
|
||||
if (packages.hasOwnProperty(pkg)) {
|
||||
packages[pkg].forEach((subpackage) => {
|
||||
if (!(subpackage in loadedPackages) && !(subpackage in toLoad)) {
|
||||
queue.push(subpackage);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_errorCallback(`Unknown package '${pkg}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.pyodide._module.locateFile = (path) => {
|
||||
// handle packages loaded from custom URLs
|
||||
let pkg = path.replace(/\.data$/, "");
|
||||
if (pkg in toLoad) {
|
||||
let package_uri = toLoad[pkg];
|
||||
if (package_uri != 'default channel') {
|
||||
return package_uri.replace(/\.js$/, ".data");
|
||||
};
|
||||
};
|
||||
return baseURL + path;
|
||||
};
|
||||
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
if (Object.keys(toLoad).length === 0) {
|
||||
resolve('No new packages to load');
|
||||
return;
|
||||
}
|
||||
|
||||
let packageList = Array.from(Object.keys(toLoad));
|
||||
_messageCallback(`Loading ${packageList.join(', ')}`)
|
||||
|
||||
// monitorRunDependencies is called at the beginning and the end of each
|
||||
// package being loaded. We know we are done when it has been called
|
||||
// exactly "toLoad * 2" times.
|
||||
var packageCounter = Object.keys(toLoad).length * 2;
|
||||
|
||||
self.pyodide._module.monitorRunDependencies = () => {
|
||||
packageCounter--;
|
||||
if (packageCounter === 0) {
|
||||
for (let pkg in toLoad) {
|
||||
self.pyodide.loadedPackages[pkg] = toLoad[pkg];
|
||||
}
|
||||
delete self.pyodide._module.monitorRunDependencies;
|
||||
self.removeEventListener('error', windowErrorHandler);
|
||||
|
||||
let resolveMsg = `Loaded `;
|
||||
if (packageList.length > 0) {
|
||||
resolveMsg += packageList.join(', ');
|
||||
} else {
|
||||
resolveMsg += 'no packages'
|
||||
}
|
||||
|
||||
if (!isFirefox) {
|
||||
preloadWasm().then(() => {
|
||||
console.log(resolveMsg);
|
||||
resolve(resolveMsg);
|
||||
});
|
||||
} else {
|
||||
console.log(resolveMsg);
|
||||
resolve(resolveMsg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add a handler for any exceptions that are thrown in the process of
|
||||
// loading a package
|
||||
var windowErrorHandler = (err) => {
|
||||
delete self.pyodide._module.monitorRunDependencies;
|
||||
self.removeEventListener('error', windowErrorHandler);
|
||||
// Set up a new Promise chain, since this one failed
|
||||
loadPackagePromise = new Promise((resolve) => resolve());
|
||||
reject(err.message);
|
||||
};
|
||||
self.addEventListener('error', windowErrorHandler);
|
||||
|
||||
for (let pkg in toLoad) {
|
||||
let scriptSrc;
|
||||
let package_uri = toLoad[pkg];
|
||||
if (package_uri == 'default channel') {
|
||||
scriptSrc = `${baseURL}${pkg}.js`;
|
||||
} else {
|
||||
scriptSrc = `${package_uri}`;
|
||||
}
|
||||
_messageCallback(`Loading ${pkg} from ${scriptSrc}`)
|
||||
loadScript(scriptSrc, () => {}, () => {
|
||||
// If the package_uri fails to load, call monitorRunDependencies twice
|
||||
// (so packageCounter will still hit 0 and finish loading), and remove
|
||||
// the package from toLoad so we don't mark it as loaded, and remove
|
||||
// the package from packageList so we don't say that it was loaded.
|
||||
_errorCallback(`Couldn't load package from URL ${scriptSrc}`);
|
||||
delete toLoad[pkg];
|
||||
let packageListIndex = packageList.indexOf(pkg);
|
||||
if (packageListIndex !== -1) {
|
||||
packageList.splice(packageListIndex, 1);
|
||||
}
|
||||
for (let i = 0; i < 2; i++) {
|
||||
self.pyodide._module.monitorRunDependencies();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We have to invalidate Python's import caches, or it won't
|
||||
// see the new files. This is done here so it happens in parallel
|
||||
// with the fetching over the network.
|
||||
self.pyodide.runPython('import importlib as _importlib\n' +
|
||||
'_importlib.invalidate_caches()\n');
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
let loadPackage = (names, messageCallback, errorCallback) => {
|
||||
/* We want to make sure that only one loadPackage invocation runs at any
|
||||
* given time, so this creates a "chain" of promises. */
|
||||
loadPackagePromise = loadPackagePromise.then(
|
||||
() => _loadPackage(names, messageCallback, errorCallback));
|
||||
return loadPackagePromise;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Fix Python recursion limit
|
||||
function fixRecursionLimit(pyodide) {
|
||||
// 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}))`);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Rearrange namespace for public API
|
||||
let PUBLIC_API = [
|
||||
'globals',
|
||||
'loadPackage',
|
||||
'loadedPackages',
|
||||
'pyimport',
|
||||
'repr',
|
||||
'runPython',
|
||||
'runPythonAsync',
|
||||
'checkABI',
|
||||
'version',
|
||||
'autocomplete',
|
||||
];
|
||||
|
||||
function makePublicAPI(module, public_api) {
|
||||
var namespace = {_module : module};
|
||||
for (let name of public_api) {
|
||||
namespace[name] = module[name];
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Loading Pyodide
|
||||
let wasmURL = `${baseURL}pyodide.asm.wasm`;
|
||||
let Module = {};
|
||||
self.Module = Module;
|
||||
|
||||
Module.noImageDecoding = true;
|
||||
Module.noAudioDecoding = true;
|
||||
Module.noWasmDecoding = true;
|
||||
Module.preloadedWasm = {};
|
||||
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
|
||||
let wasm_promise, wasm_fetch = fetch(wasmURL);
|
||||
const compileBuffer = () =>
|
||||
wasm_fetch.then(response => response.arrayBuffer())
|
||||
.then(bytes => WebAssembly.compile(bytes));
|
||||
if (WebAssembly.compileStreaming === undefined) {
|
||||
wasm_promise = compileBuffer();
|
||||
} else {
|
||||
wasm_promise = WebAssembly.compileStreaming(wasm_fetch);
|
||||
wasm_promise = wasm_promise.catch(e => {
|
||||
if (e instanceof TypeError) {
|
||||
console.error("pyodide streaming compilation failed:", e,
|
||||
"- falling back to buffered compilation");
|
||||
return compileBuffer()
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
Module.instantiateWasm = (info, receiveInstance) => {
|
||||
wasm_promise.then(module => WebAssembly.instantiate(module, info))
|
||||
.then(instance => receiveInstance(instance));
|
||||
return {};
|
||||
};
|
||||
|
||||
Module.checkABI = function(ABI_number) {
|
||||
if (ABI_number !== parseInt('1')) {
|
||||
var ABI_mismatch_exception =
|
||||
`ABI numbers differ. Expected 1, got ${ABI_number}`;
|
||||
console.error(ABI_mismatch_exception);
|
||||
throw ABI_mismatch_exception;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Module.autocomplete =
|
||||
function(path) {
|
||||
var pyodide_module = Module.pyimport("pyodide");
|
||||
return pyodide_module.get_completions(path);
|
||||
}
|
||||
|
||||
Module.locateFile = (path) => baseURL + path;
|
||||
var postRunPromise = new Promise((resolve, reject) => {
|
||||
Module.postRun = () => {
|
||||
delete self.Module;
|
||||
fetch(`${baseURL}packages.json`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => {
|
||||
fixRecursionLimit(self.pyodide);
|
||||
self.pyodide.globals =
|
||||
self.pyodide.runPython('import sys\nsys.modules["__main__"]');
|
||||
self.pyodide = makePublicAPI(self.pyodide, PUBLIC_API);
|
||||
self.pyodide._module.packages = json;
|
||||
if (self.iodide !== undefined) {
|
||||
// Perform some completions immediately so there isn't a delay on
|
||||
// the first call to autocomplete
|
||||
self.pyodide.runPython('import pyodide');
|
||||
self.pyodide.runPython('pyodide.get_completions("")');
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
var dataLoadPromise = new Promise((resolve, reject) => {
|
||||
Module.monitorRunDependencies =
|
||||
(n) => {
|
||||
if (n === 0) {
|
||||
delete Module.monitorRunDependencies;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Promise.all([ postRunPromise, dataLoadPromise ]).then(() => resolve());
|
||||
|
||||
const data_script_src = `${baseURL}pyodide.asm.data.js`;
|
||||
loadScript(data_script_src, () => {
|
||||
const scriptSrc = `${baseURL}pyodide.asm.js`;
|
||||
loadScript(scriptSrc, () => {
|
||||
// The emscripten module needs to be at this location for the core
|
||||
// filesystem to install itself. Once that's complete, it will be replaced
|
||||
// by the call to `makePublicAPI` with a more limited public API.
|
||||
self.pyodide = pyodide(Module);
|
||||
self.pyodide.loadedPackages = {};
|
||||
self.pyodide.loadPackage = loadPackage;
|
||||
}, () => {});
|
||||
}, () => {});
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Iodide-specific functionality, that doesn't make sense
|
||||
// if not using with Iodide.
|
||||
if (self.iodide !== undefined) {
|
||||
// Load the custom CSS for Pyodide
|
||||
let link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = `${baseURL}renderedhtml.css`;
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
|
||||
// Add a custom output handler for Python objects
|
||||
self.iodide.addOutputRenderer({
|
||||
shouldRender : (val) => {
|
||||
return (typeof val === 'function' &&
|
||||
pyodide._module.PyProxy.isPyProxy(val));
|
||||
},
|
||||
|
||||
render : (val) => {
|
||||
let div = document.createElement('div');
|
||||
div.className = 'rendered_html';
|
||||
var element;
|
||||
if (val._repr_html_ !== undefined) {
|
||||
let result = val._repr_html_();
|
||||
if (typeof result === 'string') {
|
||||
div.appendChild(new DOMParser()
|
||||
.parseFromString(result, 'text/html')
|
||||
.body.firstChild);
|
||||
element = div;
|
||||
} else {
|
||||
element = result;
|
||||
}
|
||||
} else {
|
||||
let pre = document.createElement('pre');
|
||||
pre.textContent = val.toString();
|
||||
div.appendChild(pre);
|
||||
element = div;
|
||||
}
|
||||
return element.outerHTML;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
languagePluginLoader
|
||||
1
web/pyparsing.js
Normal file
1
web/pyparsing.js
Normal file
File diff suppressed because one or more lines are too long
1
web/pytest.js
Normal file
1
web/pytest.js
Normal file
File diff suppressed because one or more lines are too long
1
web/python-dateutil.js
Normal file
1
web/python-dateutil.js
Normal file
File diff suppressed because one or more lines are too long
1
web/python-sat.js
Normal file
1
web/python-sat.js
Normal file
File diff suppressed because one or more lines are too long
1
web/pytz.js
Normal file
1
web/pytz.js
Normal file
File diff suppressed because one or more lines are too long
11
web/raylet.js
Normal file
11
web/raylet.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
languagePluginLoader.then(() => {
|
||||
pyodide.loadPackage(["micropip", "cloudpickle"]).then( () =>
|
||||
pyodide.runPython(`
|
||||
import micropip
|
||||
import js
|
||||
wheel_path = js.window.location.protocol + "//" + js.window.location.host + "/ray_web-0.0.1-py3-none-any.whl"
|
||||
micropip.install(wheel_path)
|
||||
`)
|
||||
)
|
||||
})
|
||||
1
web/regex.js
Normal file
1
web/regex.js
Normal file
File diff suppressed because one or more lines are too long
209
web/renderedhtml.css
Normal file
209
web/renderedhtml.css
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
.rendered_html {
|
||||
overflow: auto;
|
||||
max-height: 30em;
|
||||
color: black;
|
||||
/* any extras will just be numbers: */
|
||||
}
|
||||
.rendered_html em {
|
||||
font-style: italic;
|
||||
}
|
||||
.rendered_html strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
.rendered_html u {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.rendered_html :link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.rendered_html :visited {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.rendered_html h1 {
|
||||
font-size: 185.7%;
|
||||
margin: 1.08em 0 0 0;
|
||||
font-weight: bold;
|
||||
line-height: 1.0;
|
||||
}
|
||||
.rendered_html h2 {
|
||||
font-size: 157.1%;
|
||||
margin: 1.27em 0 0 0;
|
||||
font-weight: bold;
|
||||
line-height: 1.0;
|
||||
}
|
||||
.rendered_html h3 {
|
||||
font-size: 128.6%;
|
||||
margin: 1.55em 0 0 0;
|
||||
font-weight: bold;
|
||||
line-height: 1.0;
|
||||
}
|
||||
.rendered_html h4 {
|
||||
font-size: 100%;
|
||||
margin: 2em 0 0 0;
|
||||
font-weight: bold;
|
||||
line-height: 1.0;
|
||||
}
|
||||
.rendered_html h5 {
|
||||
font-size: 100%;
|
||||
margin: 2em 0 0 0;
|
||||
font-weight: bold;
|
||||
line-height: 1.0;
|
||||
font-style: italic;
|
||||
}
|
||||
.rendered_html h6 {
|
||||
font-size: 100%;
|
||||
margin: 2em 0 0 0;
|
||||
font-weight: bold;
|
||||
line-height: 1.0;
|
||||
font-style: italic;
|
||||
}
|
||||
.rendered_html h1:first-child {
|
||||
margin-top: 0.538em;
|
||||
}
|
||||
.rendered_html h2:first-child {
|
||||
margin-top: 0.636em;
|
||||
}
|
||||
.rendered_html h3:first-child {
|
||||
margin-top: 0.777em;
|
||||
}
|
||||
.rendered_html h4:first-child {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html h5:first-child {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html h6:first-child {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html ul:not(.list-inline),
|
||||
.rendered_html ol:not(.list-inline) {
|
||||
padding-left: 2em;
|
||||
}
|
||||
.rendered_html ul {
|
||||
list-style: disc;
|
||||
}
|
||||
.rendered_html ul ul {
|
||||
list-style: square;
|
||||
margin-top: 0;
|
||||
}
|
||||
.rendered_html ul ul ul {
|
||||
list-style: circle;
|
||||
}
|
||||
.rendered_html ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
.rendered_html ol ol {
|
||||
list-style: upper-alpha;
|
||||
margin-top: 0;
|
||||
}
|
||||
.rendered_html ol ol ol {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
.rendered_html ol ol ol ol {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
.rendered_html ol ol ol ol ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
.rendered_html * + ul {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html * + ol {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html hr {
|
||||
color: black;
|
||||
background-color: black;
|
||||
}
|
||||
.rendered_html pre {
|
||||
margin: 1em 2em;
|
||||
padding: 0px;
|
||||
background-color: white;
|
||||
}
|
||||
.rendered_html code {
|
||||
background-color: #eff0f1;
|
||||
}
|
||||
.rendered_html p code {
|
||||
padding: 1px 5px;
|
||||
}
|
||||
.rendered_html pre code {
|
||||
background-color: white;
|
||||
}
|
||||
.rendered_html pre,
|
||||
.rendered_html code {
|
||||
border: 0;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
}
|
||||
.rendered_html blockquote {
|
||||
margin: 1em 2em;
|
||||
}
|
||||
.rendered_html table {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.rendered_html thead {
|
||||
border-bottom: 1px solid black;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.rendered_html tr,
|
||||
.rendered_html th,
|
||||
.rendered_html td {
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
padding: 0.5em 0.5em;
|
||||
line-height: normal;
|
||||
white-space: normal;
|
||||
max-width: none;
|
||||
border: none;
|
||||
}
|
||||
.rendered_html th {
|
||||
font-weight: bold;
|
||||
}
|
||||
.rendered_html tbody tr:nth-child(odd) {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.rendered_html tbody tr:hover {
|
||||
background: rgba(66, 165, 245, 0.2);
|
||||
}
|
||||
.rendered_html * + table {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html p {
|
||||
text-align: left;
|
||||
}
|
||||
.rendered_html * + p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html img {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.rendered_html * + img {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.rendered_html img,
|
||||
.rendered_html svg {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.rendered_html img.unconfined,
|
||||
.rendered_html svg.unconfined {
|
||||
max-width: none;
|
||||
}
|
||||
.rendered_html .alert {
|
||||
margin-bottom: initial;
|
||||
}
|
||||
.rendered_html * + .alert {
|
||||
margin-top: 1em;
|
||||
}
|
||||
[dir="rtl"] .rendered_html p {
|
||||
text-align: right;
|
||||
}
|
||||
1
web/scikit-learn.js
Normal file
1
web/scikit-learn.js
Normal file
File diff suppressed because one or more lines are too long
1
web/scipy.js
Normal file
1
web/scipy.js
Normal file
File diff suppressed because one or more lines are too long
1
web/setuptools.js
Normal file
1
web/setuptools.js
Normal file
File diff suppressed because one or more lines are too long
1
web/soupsieve.js
Normal file
1
web/soupsieve.js
Normal file
File diff suppressed because one or more lines are too long
1
web/statsmodels.js
Normal file
1
web/statsmodels.js
Normal file
File diff suppressed because one or more lines are too long
1
web/sympy.js
Normal file
1
web/sympy.js
Normal file
File diff suppressed because one or more lines are too long
23
web/test.html
Normal file
23
web/test.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!-- Bootstrap HTML for running the unit tests. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<script>
|
||||
window.logs = [];
|
||||
console.log = function(message) {
|
||||
window.logs.push(message);
|
||||
}
|
||||
console.warn = function(message) {
|
||||
window.logs.push(message);
|
||||
}
|
||||
console.info = function(message) {
|
||||
window.logs.push(message);
|
||||
}
|
||||
console.error = function(message) {
|
||||
window.logs.push(message);
|
||||
}
|
||||
</script>
|
||||
<script src="pyodide_dev.js"></script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
1
web/test.js
Normal file
1
web/test.js
Normal file
File diff suppressed because one or more lines are too long
1
web/toolz.js
Normal file
1
web/toolz.js
Normal file
File diff suppressed because one or more lines are too long
1
web/traits.js
Normal file
1
web/traits.js
Normal file
File diff suppressed because one or more lines are too long
1
web/uncertainties.js
Normal file
1
web/uncertainties.js
Normal file
File diff suppressed because one or more lines are too long
1
web/webencodings.js
Normal file
1
web/webencodings.js
Normal file
File diff suppressed because one or more lines are too long
25
web/webworker.js
Normal file
25
web/webworker.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
self.languagePluginUrl = 'https://cdn.jsdelivr.net/pyodide/v0.15.0/full/'
|
||||
importScripts('./pyodide.js')
|
||||
|
||||
var onmessage = function(e) { // eslint-disable-line no-unused-vars
|
||||
languagePluginLoader.then(() => {
|
||||
const data = e.data;
|
||||
const keys = Object.keys(data);
|
||||
for (let key of keys) {
|
||||
if (key !== 'python') {
|
||||
// Keys other than python must be arguments for the python script.
|
||||
// Set them on self, so that `from js import key` works.
|
||||
self[key] = data[key];
|
||||
}
|
||||
}
|
||||
|
||||
self.pyodide.runPythonAsync(data.python, () => {})
|
||||
.then((results) => { self.postMessage({results}); })
|
||||
.catch((err) => {
|
||||
// if you prefer messages with the error
|
||||
self.postMessage({error : err.message});
|
||||
// if you prefer onerror events
|
||||
// setTimeout(() => { throw err; });
|
||||
});
|
||||
});
|
||||
}
|
||||
25
web/webworker_dev.js
Normal file
25
web/webworker_dev.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
self.languagePluginUrl = './'
|
||||
importScripts('./pyodide_dev.js')
|
||||
|
||||
var onmessage = function(e) { // eslint-disable-line no-unused-vars
|
||||
languagePluginLoader.then(() => {
|
||||
const data = e.data;
|
||||
const keys = Object.keys(data);
|
||||
for (let key of keys) {
|
||||
if (key !== 'python') {
|
||||
// Keys other than python must be arguments for the python script.
|
||||
// Set them on self, so that `from js import key` works.
|
||||
self[key] = data[key];
|
||||
}
|
||||
}
|
||||
|
||||
self.pyodide.runPythonAsync(data.python, () => {})
|
||||
.then((results) => { self.postMessage({results}); })
|
||||
.catch((err) => {
|
||||
// if you prefer messages with the error
|
||||
self.postMessage({error : err.message});
|
||||
// if you prefer onerror events
|
||||
// setTimeout(() => { throw err; });
|
||||
});
|
||||
});
|
||||
}
|
||||
1
web/xlrd.js
Normal file
1
web/xlrd.js
Normal file
File diff suppressed because one or more lines are too long
1
web/yt.js
Normal file
1
web/yt.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue