Repository: pyscript/pyscript
File: pyscriptjs/src/remote_interpreter.ts (TypeScript)

Code before:
        super();
        this.src = src;
    }

    /**
     * loads the interface for the interpreter and saves an instance of it
     * in the `this.interface` property along with calling of other
     * additional convenience functions.
     * */

    /**
     * Although `loadPyodide` is used below,
     * notice that it is not imported i.e.
     * import { loadPyodide } from 'pyodide';
     * is not used at the top of this file.
     *
     * This is because, if it's used, loadPyodide
     * behaves mischievously i.e. it tries to load
     * additional files but with paths that are wrong such as:
     *
     * http://127.0.0.1:8080/build/...
     * which results in a 404 since `build` doesn't
     * contain these files and is clearly the wrong
     * path.
     */
    async loadInterpreter(config: AppConfig, stdio: Stdio): Promise<void> {
        this.interface = Synclink.proxy(
            await loadPyodide({
                stdout: (msg: string) => {
                    // TODO: add syncify when moved to worker
                    stdio.stdout_writeline(msg);
                },
                stderr: (msg: string) => {
                    stdio.stderr_writeline(msg);
                },
                fullStdLib: false,
            }),
        );
        this.FS = this.interface.FS;
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        this.PATH = (this.interface as any)._module.PATH;
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        this.PATH_FS = (this.interface as any)._module.PATH_FS;

        // TODO: Remove this once `runtimes` is removed!
        this.interpreter = this.interface;

        // Write pyscript package into file system
        for (const dir of python_package.dirs) {
            this.FS.mkdir('/home/pyodide/' + dir);
        }

Review comment (suggestion):
Not really related to this PR, but this is what `indexURL` is for. But if you want to support multiple versions of Pyodide you can't vendor one version of `loadPyodide`. So probably the comment should say that we have to use the `loadPyodide` that came from the dynamically imported Pyodide to allow alternate Pyodide versions.

@antocuni was suggesting that we shouldn't even support multiple Pyodide versions, but that's yet another separate discussion I suppose.

Code after:
    globals: PyProxyDict & ProxyMarked;
    // TODO: Remove this once `runtimes` is removed!
    interpreter: InterpreterInterface & ProxyMarked;

    constructor(src = 'https://cdn.jsdelivr.net/pyodide/v0.23.2/full/pyodide.js') {
        super();
        this.src = src;
    }

    /**
     * loads the interface for the interpreter and saves an instance of it
     * in the `this.interface` property along with calling of other
     * additional convenience functions.
     * */

    /**
     * Although `loadPyodide` is used below,
     * notice that it is not imported i.e.
     * import { loadPyodide } from 'pyodide';
     * is not used at the top of this file.
     *
     * This is because, if it's used, loadPyodide
     * behaves mischievously i.e. it tries to load
     * additional files but with paths that are wrong such as:
     *
     * http://127.0.0.1:8080/build/...
     * which results in a 404 since `build` doesn't
     * contain these files and is clearly the wrong
     * path.
     */
    async loadInterpreter(config: AppConfig, stdio: Synclink.Remote<Stdio & ProxyMarked>): Promise<void> {
        // TODO: move this to "main thread"!
        const _pyscript_js_main = { define_custom_element, showWarning, deepQuerySelector };

        this.interface = Synclink.proxy(
            await loadPyodide({
                stdout: (msg: string) => {
                    stdio.stdout_writeline(msg).syncify();
                },
                stderr: (msg: string) => {
                    stdio.stderr_writeline(msg).syncify();
                },
                fullStdLib: false,
            }),
        );
        this.interface.registerComlink(Synclink);
        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
        this.FS = this.interface.FS;
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        this.PATH = (this.interface as any)._module.PATH;
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access