Files
pyscript/pyscriptjs/src/pyodide.ts
Madhur Tandon 1db155570d PyodideRuntime should be one of the runtimes (#698)
* PyodideRuntime should be one of the runtimes

* subsume interpreter into runtime API

* fix eslint

* add comments

* move initializers, postInitializers, scriptsQueue, etc. to initialize() of Runtime Super Class

* modify comment for initialize

* small renaming

* change id to default

* fix pyscript.py import

* try adding tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add inlineDynamicImports option

* Make jest happy about ESM modules

* Attempt to make jest happy about pyodide

* point to version in accordance with node module being used

* fix base.ts

* fix tests

* fix indexURL path determination

* edit pyodide.asm.js as a part of setup process

* load runtime beforeAll tests

* add test for loading a package

* use only runPythonAsync underneath for pyodide

* import PyodideInterface type directly from pyodide

* add some comments

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Philipp Rudiger <prudiger@anaconda.com>
2022-08-25 02:33:36 +05:30

85 lines
2.8 KiB
TypeScript

import { Runtime } from './runtime';
import { getLastPath, inJest } from './utils';
import type { PyodideInterface } from 'pyodide';
import { loadPyodide } from 'pyodide';
// eslint-disable-next-line
// @ts-ignore
import pyscript from './python/pyscript.py';
export class PyodideRuntime extends Runtime {
src = 'https://cdn.jsdelivr.net/pyodide/v0.21.1/full/pyodide.js';
name = 'pyodide-default';
lang = 'python';
interpreter: PyodideInterface;
globals: any;
async loadInterpreter(): Promise<void> {
console.log('creating pyodide runtime');
// eslint-disable-next-line
// @ts-ignore
let extraOpts: any = {}
if (inJest()) {
extraOpts = {indexURL: [process.cwd(), 'node_modules', 'pyodide'].join('/') }
}
this.interpreter = await loadPyodide({
stdout: console.log,
stderr: console.log,
fullStdLib: false,
...extraOpts
});
this.globals = this.interpreter.globals;
// now that we loaded, add additional convenience functions
console.log('loading micropip');
await this.loadPackage('micropip');
console.log('loading pyscript...');
const output = await this.run(pyscript);
if (output !== undefined) {
console.log(output);
}
console.log('done setting up environment');
}
async run(code: string): Promise<any> {
return await this.interpreter.runPythonAsync(code);
}
registerJsModule(name: string, module: object): void {
this.interpreter.registerJsModule(name, module);
}
async loadPackage(names: string | string[]): Promise<void> {
await this.interpreter.loadPackage(names);
}
async installPackage(package_name: string | string[]): Promise<void> {
if (package_name.length > 0){
const micropip = this.globals.get('micropip');
await micropip.install(package_name);
micropip.destroy();
}
}
async loadFromFile(path: string): Promise<void> {
const filename = getLastPath(path);
await this.run(
`
from pyodide.http import pyfetch
from js import console
try:
response = await pyfetch("${path}")
except Exception as err:
console.warn("PyScript: Access to local files (using 'paths:' in py-env) is not available when directly opening a HTML file; you must use a webserver to serve the additional files. See https://github.com/pyscript/pyscript/issues/257#issuecomment-1119595062 on starting a simple webserver with Python.")
raise(err)
content = await response.bytes()
with open("${filename}", "wb") as f:
f.write(content)
`,
);
}
}