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

Code before:
        const pyscript_module = runtime.interpreter.pyimport('pyscript');
        pyscript_module.define_custom_element = define_custom_element;
        pyscript_module.PyScript.set_version_info(version);
        pyscript_module.destroy();

        // TODO: Currently adding the imports for backwards compatibility, we should
        //       remove it
        await runtime.run(`
        from pyscript import *
        `);
        logger.warn(`DEPRECATION WARNING: 'micropip', 'Element', 'console', 'document' and several other \
objects form the pyscript module (with the exception of 'display') will be \
be removed from the Python global namespace in the following release. \
To avoid errors in future releases use import from pyscript instead. For instance: \
from pyscript import micropip, Element, console, document`);

        logger.info('Packages to install: ', this.config.packages);
        await runtime.installPackage(this.config.packages);
        await this.fetchPaths(runtime);

        // Finally load plugins
        await this.fetchPythonPlugins(runtime);
    }

    async fetchPaths(runtime: Runtime) {
        // XXX this can be VASTLY improved: for each path we need to fetch a
        // URL and write to the virtual filesystem: pyodide.loadFromFile does
        // it in Python, which means we need to have the runtime
        // initialized. But we could easily do it in JS in parallel with the
        // download/startup of pyodide.
        const [paths, fetchPaths] = calculatePaths(this.config.fetch);
        logger.info('Paths to fetch: ', fetchPaths);
        for (let i = 0; i < paths.length; i++) {
            logger.info(`  fetching path: ${fetchPaths[i]}`);
            try {
                await runtime.loadFromFile(paths[i], fetchPaths[i]);
            } catch (e) {
                // The 'TypeError' here happens when running pytest
                // I'm not particularly happy with this solution.
                if (e.name === 'FetchError' || e.name === 'TypeError') {
                    handleFetchError(<Error>e, fetchPaths[i]);
                } else {
                    throw e;
                }
            }
        }
        logger.info('All paths fetched');
    }

    /**
     * Fetches all the python plugins specified in this.config, saves them on the FS and import

Review comment (performance):
I think this is unnecessary because you are already calling `runtime.invalidate_module_path_cache()` inside `fetchPythonPlugins` before each plugin is imported, so (I think!) the cache would be invalidated anyway. With that said, I think it's totally fine to keep this here anyway and remove it later

Code after:
        //Refresh the module cache so Python consistently finds pyscript module
        runtime.invalidate_module_path_cache()

        // inject `define_custom_element` it into the PyScript module scope
        const pyscript_module = runtime.interpreter.pyimport('pyscript');
        pyscript_module.define_custom_element = define_custom_element;
        pyscript_module.PyScript.set_version_info(version);
        pyscript_module.destroy();

        // TODO: Currently adding the imports for backwards compatibility, we should
        //       remove it
        await runtime.run(`
        from pyscript import *
        `);
        logger.warn(`DEPRECATION WARNING: 'micropip', 'Element', 'console', 'document' and several other \
objects form the pyscript module (with the exception of 'display') will be \
be removed from the Python global namespace in the following release. \
To avoid errors in future releases use import from pyscript instead. For instance: \
from pyscript import micropip, Element, console, document`);

        logger.info('Packages to install: ', this.config.packages);
        await runtime.installPackage(this.config.packages);
        await this.fetchPaths(runtime);

        //This may be unnecessary - only useful if plugins try to import files fetch'd in fetchPaths()
        runtime.invalidate_module_path_cache()
        // Finally load plugins
        await this.fetchPythonPlugins(runtime);
    }

    async fetchPaths(runtime: Runtime) {
        // XXX this can be VASTLY improved: for each path we need to fetch a
        // URL and write to the virtual filesystem: pyodide.loadFromFile does
        // it in Python, which means we need to have the runtime
        // initialized. But we could easily do it in JS in parallel with the
        // download/startup of pyodide.
        const [paths, fetchPaths] = calculatePaths(this.config.fetch);
        logger.info('Paths to fetch: ', fetchPaths);
        for (let i = 0; i < paths.length; i++) {
            logger.info(`  fetching path: ${fetchPaths[i]}`);
            try {
                await runtime.loadFromFile(paths[i], fetchPaths[i]);
            } catch (e) {
                // The 'TypeError' here happens when running pytest
                // I'm not particularly happy with this solution.
                if (e.name === 'FetchError' || e.name === 'TypeError') {
                    handleFetchError(<Error>e, fetchPaths[i]);
                } else {
                    throw e;
                }
            }