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

Code before:
            await this.loadPackage('micropip');
        }
        logger.info('pyodide loaded and initialized');
    }

    run(code: string): unknown {
        return this.interpreter.runPython(code);
    }

    registerJsModule(name: string, module: object): void {
        this.interpreter.registerJsModule(name, module);
    }

    async loadPackage(names: string | string[]): Promise<void> {
        logger.info(`pyodide.loadPackage: ${names.toString()}`);
        await this.interpreter.loadPackage(names, logger.info.bind(logger), logger.info.bind(logger));
    }

    async installPackage(package_name: string | string[]): Promise<void> {
        if (package_name.length > 0) {
            logger.info(`micropip install ${package_name.toString()}`);
            const micropip = this.globals.get('micropip') as Micropip;
            try {
                await micropip.install(package_name);
                micropip.destroy();
            } catch(e) {
                let exceptionMessage = `Unable to install package(s) '` + package_name +`'.`

                // If we can't fetch `package_name` micropip.install throws a huge
                // Python traceback in `e.message` this logic is to handle the
                // error and throw a more sensible error message instead of the
                // huge traceback.
                if (e.message.includes("Can't find a pure Python 3 wheel")) {
                    exceptionMessage += (
                        ` Reason: Can't find a pure Python 3 Wheel for package(s) '` + package_name +
                        `'. See: https://pyodide.org/en/stable/usage/faq.html#micropip-can-t-find-a-pure-python-wheel ` +
                        `for more information.`
                    )
                } else if (e.message.includes("Can't fetch metadata")) {
                    exceptionMessage += (
                        " Unable to find package in PyPI. " +
                        "Please make sure you have entered a correct package name."
                    )
                } else {
                    exceptionMessage += ` Reason: ${e.message as string}`
                }

                logger.error(e);

                throw new InstallError(
                    ErrorCode.MICROPIP_INSTALL_ERROR,

Review comment (suggestion):
here we should check that `e` is actually a Python error and not some unrelated exception that we don't expect

Code after:
            await this.loadPackage('micropip');
        }
        logger.info('pyodide loaded and initialized');
    }

    run(code: string): unknown {
        return this.interpreter.runPython(code);
    }

    registerJsModule(name: string, module: object): void {
        this.interpreter.registerJsModule(name, module);
    }

    async loadPackage(names: string | string[]): Promise<void> {
        logger.info(`pyodide.loadPackage: ${names.toString()}`);
        await this.interpreter.loadPackage(names, logger.info.bind(logger), logger.info.bind(logger));
    }

    async installPackage(package_name: string | string[]): Promise<void> {
        if (package_name.length > 0) {
            logger.info(`micropip install ${package_name.toString()}`);
            const micropip = this.globals.get('micropip') as Micropip;
            try {
                await micropip.install(package_name);
                micropip.destroy();
            } catch(e) {
                let exceptionMessage = `Unable to install package(s) '` + package_name +`'.`

                // If we can't fetch `package_name` micropip.install throws a huge
                // Python traceback in `e.message` this logic is to handle the
                // error and throw a more sensible error message instead of the
                // huge traceback.
                if (e.message.includes("Can't find a pure Python 3 wheel")) {
                    exceptionMessage += (
                        ` Reason: Can't find a pure Python 3 Wheel for package(s) '` + package_name +
                        `'. See: https://pyodide.org/en/stable/usage/faq.html#micropip-can-t-find-a-pure-python-wheel ` +
                        `for more information.`
                    )
                } else if (e.message.includes("Can't fetch metadata")) {
                    exceptionMessage += (
                        " Unable to find package in PyPI. " +
                        "Please make sure you have entered a correct package name."
                    )
                } else {
                    exceptionMessage += (
                        ` Reason: ${e.message as string}. Please open an issue at ` +
                        `https://github.com/pyscript/pyscript/issues/new if you require help or ` +
                        `you think it's a bug.`)
                }

                logger.error(e);