diff --git a/.circleci/config.yml b/.circleci/config.yml index a948bc406..f24a3670c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,14 +23,16 @@ jobs: working_directory: ~/repo docker: - - image: python:3.8-alpine + - image: cimg/python:3.8.2-node steps: - checkout - run: name: Install prerequisites - command: pip install -r docs/requirements-doc.txt + command: | + pip install -r docs/requirements-doc.txt + sudo npm install -g jsdoc - run: name: Build docs diff --git a/docs/conf.py b/docs/conf.py index 197c002fe..40902789f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,8 +49,11 @@ extensions = [ "sphinx.ext.autosummary", "sphinxcontrib.napoleon", "myst_parser", + "sphinx_js", ] +js_source_path = "../src/" + autosummary_generate = True autodoc_default_flags = ["members", "inherited-members"] diff --git a/docs/development/contributing.md b/docs/development/contributing.md index 0c18bb387..0c8bc7253 100644 --- a/docs/development/contributing.md +++ b/docs/development/contributing.md @@ -64,6 +64,7 @@ sections](https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets ### Building the docs From the directory ``docs``, first install the python dependencies with ``pip install -r requirements-doc.txt``. +You also need to install JsDoc, which is a ``node`` dependency. Install it with ``sudo npm install -g jsdoc``. Then to build the docs run ``make html``. The built documentation will be in the subdirectory ``docs/_build/html``. To view them, cd into ``_build/html`` and start a file server, for instance ``http-server``. diff --git a/docs/development/new-packages.md b/docs/development/new-packages.md index 7e57c37cf..a8af2bd21 100644 --- a/docs/development/new-packages.md +++ b/docs/development/new-packages.md @@ -21,7 +21,7 @@ libraries to the build. We automate the following steps: the virtual filesystem. Lastly, a `packages.json` file is output containing the dependency tree of all -packages, so {ref}`pyodide.loadPackage ` can +packages, so {any}`pyodide.loadPackage` can load a package's dependencies automatically. ## mkpkg diff --git a/docs/project/changelog.md b/docs/project/changelog.md index 3147d3ee5..87e1b9973 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -239,7 +239,7 @@ Sergio, Seungmin Kim, Shyam Saladi, smkm, Wei Ouyang The latest release can be accessed via https://pyodide-cdn2.iodide.io/latest/full/ - Adds `messageCallback` and `errorCallback` to - {ref}`pyodide.loadPackage `. + {any}`pyodide.loadPackage`. - Reduces the initial memory footprint (`TOTAL_MEMORY`) from 1 GiB to 5 MiB. More memory will be allocated as needed. - When building from source, only a subset of packages can be built by setting diff --git a/docs/requirements-doc.txt b/docs/requirements-doc.txt index cd5fbdd7b..b6e129d0e 100644 --- a/docs/requirements-doc.txt +++ b/docs/requirements-doc.txt @@ -4,3 +4,4 @@ sphinx_rtd_theme myst-parser==0.13.1 sphinxcontrib-napoleon distlib # required by micropip +sphinx-js==3.1 \ No newline at end of file diff --git a/docs/usage/api-reference.md b/docs/usage/api-reference.md index 4b5710567..d110a3637 100644 --- a/docs/usage/api-reference.md +++ b/docs/usage/api-reference.md @@ -26,40 +26,21 @@ Backward compatibility of the API is not guaranteed at this point. ## Javascript API - Backward compatibility of the API is not guaranteed at this point. -| | | -|-|-| -| **{ref}`js_api_pyodide_globals`** | An alias to the global Python namespace | -| **{ref}`js_api_pyodide_pyodide_py`** | An alias to the pyodide Python package | -| **{ref}`pyodide.loadPackage(names, ...) `** | Load a package or a list of packages over the network | -| **{ref}`pyodide.loadPackageFromImports(code) `** | Inspect a Python code chunk and use ``pyodide.loadPackage` to load any known packages that the code chunk imports. | -| **{ref}`js_api_pyodide_loadedPackages`** | `Object` with loaded packages. | -| **{ref}`pyodide.registerJsModule(name, js_object) `** | Registers a javascript object as a Python module. | -| **{ref}`pyodide.unregisterJsModule(name) `** | Unregisters a module previously registered with `js_api_pyodide_registerJsPackage`. | -| **{ref}`js_api_pyodide_pyimport`** | Access a Python object in the global namespace from Javascript | -| **{ref}`js_api_pyodide_runPython`** | Runs Python code from Javascript. | -| **{ref}`pyodide.runPythonAsync(code, ...) `** | Runs Python code with automatic preloading of imports. | -| **{ref}`js_api_pyodide_version`** | The pyodide version string. | -| **{ref}`pyodide.setInterruptBuffer(interruptBuffer) `** | Set the keyboard interrupt buffer | - - ```{eval-rst} -.. toctree:: - :hidden: - - js-api/pyodide.globals.md - js-api/pyodide.pyodide_py.md - js-api/pyodide.loadPackage.md - js-api/pyodide.loadPackagesFromImports.md - js-api/pyodide.loadedPackages.md - js-api/pyodide.registerJsModule.md - js-api/pyodide.unregisterJsModule.md - js-api/pyodide.pyimport.md - js-api/pyodide.runPython.md - js-api/pyodide.runPythonAsync.md - js-api/pyodide.version.md +.. js:module:: pyodide +.. js:autofunction:: runPython +.. js:autofunction:: runPythonAsync +.. js:autoattribute:: globals +.. js:autoattribute:: pyodide_py +.. js:autoattribute:: version +.. js:autofunction:: pyimport +.. js:autofunction:: loadPackage +.. js:autoattribute:: loadedPackages +.. js:autofunction:: loadPackagesFromImports +.. js:autofunction:: registerJsModule +.. js:autofunction:: unregisterJsModule ``` diff --git a/docs/usage/js-api/pyodide.globals.md b/docs/usage/js-api/pyodide.globals.md deleted file mode 100644 index 4934fddbf..000000000 --- a/docs/usage/js-api/pyodide.globals.md +++ /dev/null @@ -1,13 +0,0 @@ -(js_api_pyodide_globals)= -# pyodide.globals - -An alias to the global Python namespace. - -An object whose attributes are members of the Python global namespace. This is a -more convenient alternative to {ref}`pyodide.pyimport `. - -For example, to access the `foo` Python object from Javascript: - -```javascript -pyodide.globals.foo -``` diff --git a/docs/usage/js-api/pyodide.loadPackage.md b/docs/usage/js-api/pyodide.loadPackage.md deleted file mode 100644 index 553c5eccf..000000000 --- a/docs/usage/js-api/pyodide.loadPackage.md +++ /dev/null @@ -1,19 +0,0 @@ -(js_api_pyodide_loadpackage)= -# pyodide.loadPackage(names, messageCallback, errorCallback) - -Load a package or a list of packages over the network. - -This makes the files for the package available in the virtual filesystem. -The package needs to be imported from Python before it can be used. - -*Parameters* - -| name | type | description | -|-------------------|-----------------|---------------------------------------| -| *names* | {String, Array} | package name, or URL. Can be either a single element, or an array. | -| *messageCallback* | function | A callback, called with progress messages. (optional) | -| *errorCallback* | function | A callback, called with error/warning messages. (optional) | - -*Returns* - -Loading is asynchronous, therefore, this returns a `Promise`. diff --git a/docs/usage/js-api/pyodide.loadPackagesFromImports.md b/docs/usage/js-api/pyodide.loadPackagesFromImports.md deleted file mode 100644 index 073faac8e..000000000 --- a/docs/usage/js-api/pyodide.loadPackagesFromImports.md +++ /dev/null @@ -1,29 +0,0 @@ -(js_api_pyodide_loadPackagesFromImports)= -# pyodide.loadPackagesFromImports(code, messageCallback, errorCallback) - -Inspect a Python code chunk and use ``pyodide.loadPackage` to load any known packages that the code chunk imports. Uses `pyodide_py.find_imports ` to inspect the code. - -For example, given the following code chunk - -```python -import numpy as np -x = np.array([1, 2, 3]) -``` - -`loadPackagesFromImports` will call `pyodide.loadPackage(['numpy'])`. -See also {ref}`js_api_pyodide_runPythonAsync`. - - -*Parameters* - -| name | type | description | -|-------------------|----------|--------------------------------| -| *code* | String | code to inspect for packages to load. | -| *messageCallback* | function | A callback, called with progress messages. (optional) | -| *errorCallback* | function | A callback, called with error/warning messages. (optional) | - -*Returns* - -| name | type | description | -|------------|---------|------------------------------------------| -| *result* | Promise | Resolves to undefined on success. | diff --git a/docs/usage/js-api/pyodide.loadedPackages.md b/docs/usage/js-api/pyodide.loadedPackages.md deleted file mode 100644 index 065817fc3..000000000 --- a/docs/usage/js-api/pyodide.loadedPackages.md +++ /dev/null @@ -1,8 +0,0 @@ -(js_api_pyodide_loadedPackages)= -# pyodide.loadedPackages - -`Object` with loaded packages. - -Use `Object.keys(pyodide.loadedPackages)` to access the names of the -loaded packages, and `pyodide.loadedPackages[package_name]` to access -install location for a particular `package_name`. diff --git a/docs/usage/js-api/pyodide.pyimport.md b/docs/usage/js-api/pyodide.pyimport.md deleted file mode 100644 index 21ea680fa..000000000 --- a/docs/usage/js-api/pyodide.pyimport.md +++ /dev/null @@ -1,22 +0,0 @@ -(js_api_pyodide_pyimport)= -# pyodide.pyimport(name) - -Access a Python object in the global namespace from Javascript. - -For example, to access the `foo` Python object from Javascript: -```javascript -let foo = pyodide.pyimport('foo'); -``` - -*Parameters* - -| name | type | description | -|---------|--------|----------------------| -| *names* | String | Python variable name | - - -*Returns* - -| name | type | description | -|-----------|---------|---------------------------------------| -| *object* | *any* | If one of the basic types (string, number,
boolean, array, object), the Python
object is converted to Javascript and
returned. For other types, a Proxy
object to the Python object is returned. | diff --git a/docs/usage/js-api/pyodide.pyodide_py.md b/docs/usage/js-api/pyodide.pyodide_py.md deleted file mode 100644 index 89e1e2044..000000000 --- a/docs/usage/js-api/pyodide.pyodide_py.md +++ /dev/null @@ -1,3 +0,0 @@ -(js_api_pyodide_pyodide_py)= -# pyodide.pyodide_py -A reference to the python `pyodide` package. Read all about it in the Python api. diff --git a/docs/usage/js-api/pyodide.registerJsModule.md b/docs/usage/js-api/pyodide.registerJsModule.md deleted file mode 100644 index e088d6eaa..000000000 --- a/docs/usage/js-api/pyodide.registerJsModule.md +++ /dev/null @@ -1,12 +0,0 @@ -(js_api_pyodide_registerJsModule)= -# pyodide.registerJsModule(name, module) - -Registers the Js object ``module`` as a Js module with ``name``. This module can then be imported from Python using the standard Python import system. If another module by the same name has already been imported, this won't have much effect unless you also delete the imported module from ``sys.modules``. This calls the ``pyodide_py`` api ``pyodide_py.register_js_module``. - - -**Parameters** - -| name | type | description | -|-----------|--------|--------------------------------------| -| *name* | String | Name of js module | -| *module* | object | Javascript object backing the module | diff --git a/docs/usage/js-api/pyodide.runPython.md b/docs/usage/js-api/pyodide.runPython.md deleted file mode 100644 index 412125626..000000000 --- a/docs/usage/js-api/pyodide.runPython.md +++ /dev/null @@ -1,19 +0,0 @@ -(js_api_pyodide_runPython)= -# pyodide.runPython(code) - -Runs a string of Python code from Javascript. - -The last part of the string may be an expression, in which case, its value is returned. - -**Parameters** - -| name | type | description | -|---------|--------|--------------------------------| -| *code* | String | Python code to evaluate | - - -**Returns** - -| name | type | description | -|------------|---------|---------------------------------| -| *jsresult* | *any* | Result, converted to Javascript | diff --git a/docs/usage/js-api/pyodide.runPythonAsync.md b/docs/usage/js-api/pyodide.runPythonAsync.md deleted file mode 100644 index 6158e1671..000000000 --- a/docs/usage/js-api/pyodide.runPythonAsync.md +++ /dev/null @@ -1,36 +0,0 @@ -(js_api_pyodide_runPythonAsync)= -# pyodide.runPythonAsync(code, messageCallback, errorCallback) - -Runs Python code, possibly asynchronously loading any known packages that the code -chunk imports. - -For example, given the following code chunk - -```python -import numpy as np -x = np.array([1, 2, 3]) -``` - -pyodide will first call `pyodide.loadPackage(['numpy'])`, and then run the code -chunk, returning the result. Since package fetching must happen asynchronously, -this function returns a `Promise` which resolves to the output. For example, to -use: - -```javascript -pyodide.runPythonAsync(code, messageCallback) - .then((output) => handleOutput(output)) -``` - -*Parameters* - -| name | type | description | -|-------------------|----------|--------------------------------| -| *code* | String | Python code to evaluate | -| *messageCallback* | function | A callback, called with progress messages. (optional) | -| *errorCallback* | function | A callback, called with error/warning messages. (optional) | - -*Returns* - -| name | type | description | -|------------|---------|------------------------------------------| -| *result* | Promise | Resolves to the result of the code chunk | diff --git a/docs/usage/js-api/pyodide.setInterruptBuffer.md b/docs/usage/js-api/pyodide.setInterruptBuffer.md deleted file mode 100644 index 45f0b2571..000000000 --- a/docs/usage/js-api/pyodide.setInterruptBuffer.md +++ /dev/null @@ -1,19 +0,0 @@ -(js_api_pyodide_setInterruptBuffer)= # -pyodide.setInterruptBuffer(interruptBuffer) This is a low level API for -handling keyboard interrupts. Sets the pyodide interrupt buffer to be -`interruptBuffer`. If thereafter one sets `interruptBuffer[0] = 2;` (2 stands -for SIGINT) this will cause Pyodide to raise a `KeyboardInterupt`. The value of -`interruptBuffer[0]` will regularly be set back to zero. This is intended for -use when Pyodide is running on a webworker. In this case, one should make -`interruptBuffer` a `SharedArrayBuffer` shared with the main thread. If the -user requests a keyboard interrupt from the main thread, then the main thread -can set `interruptBuffer[0] = 2;` and this will signal the webworker to raise a -KeyboardInterupt exception. - - -**Parameters** - -| name | type | description -| -|--------------------|------------|------------------------------------------------------| -| *interruptBuffer* | TypedArray | The SharedArrayBuffer to use as the interrupt buffer | diff --git a/docs/usage/js-api/pyodide.unregisterJsModule.md b/docs/usage/js-api/pyodide.unregisterJsModule.md deleted file mode 100644 index a5fd98c55..000000000 --- a/docs/usage/js-api/pyodide.unregisterJsModule.md +++ /dev/null @@ -1,11 +0,0 @@ -(js_api_pyodide_unregisterJsModule)= -# pyodide.unregisterJsModule(name) - -Unregisters a Js module with given name that has been previously registered with `js_api_pyodide_registerJsModule` or ``pyodide.register_js_module``. If a Js module with that name does not already exist, will throw an error. Note that if the module has already been imported, this won't have much effect unless you also delete the imported module from ``sys.modules``. This calls the ``pyodide_py`` api ``pyodide_py.unregister_js_module``. - -**Parameters** - -| name | type | description | -|---------|--------|--------------------------------| -| *name* | String | Name of js module | - diff --git a/docs/usage/js-api/pyodide.version.md b/docs/usage/js-api/pyodide.version.md deleted file mode 100644 index afc5202fe..000000000 --- a/docs/usage/js-api/pyodide.version.md +++ /dev/null @@ -1,8 +0,0 @@ -(js_api_pyodide_version)= -# pyodide.version - -The pyodide version. - -It can be either the exact release version (e.g. `0.1.0`), or -the latest release version followed by the number of commits since, and -the git hash of the current commit (e.g. `0.1.0-1-bd84646`). diff --git a/docs/usage/loading-packages.md b/docs/usage/loading-packages.md index 54120eedd..3a17562d3 100644 --- a/docs/usage/loading-packages.md +++ b/docs/usage/loading-packages.md @@ -3,18 +3,17 @@ Only the Python standard library is available after importing Pyodide. To use other packages, you’ll need to load them using either: - - {ref}`pyodide.loadPackage ` for packages built - with pyodide, or + - {any}`pyodide.loadPackage` for packages built with pyodide, or - `micropip.install` for pure Python packages with wheels available on PyPi or from other URLs. ```{note} `micropip` can also be used to load packages built in pyodide (in -which case it relies on {ref}`pyodide.loadPackage `). +which case it relies on {any}`pyodide.loadPackage`). ``` Alternatively you can run Python code without manually pre-loading packages. -You can do this with {ref}`pyodide.runPythonAsync ` +You can do this with {any}`pyodide.runPythonAsync` which will automatically download all packages that the code snippet imports. It only supports packages included in Pyodide (not on PyPi) at present. @@ -92,7 +91,7 @@ be the case if the wheels is made using standard python tools (`pip wheel`, `setup.py bdist_wheel`). All required dependencies need also to be previously installed with `micropip` -or {ref}`pyodide.loadPackage `. +or {any}`pyodide.loadPackage`. If the file is on a remote server, it must set Cross-Origin Resource Sharing (CORS) headers to allow access. Otherwise, you can prepend a CORS proxy to the URL. Note however diff --git a/docs/usage/quickstart.md b/docs/usage/quickstart.md index 5a06fc499..07b04ca22 100644 --- a/docs/usage/quickstart.md +++ b/docs/usage/quickstart.md @@ -31,7 +31,7 @@ languagePluginLoader.then(() => { ## Running Python code -Python code is run using the {ref}`pyodide.runPython ` +Python code is run using the {any}`pyodide.runPython` function. It takes as input a string of Python code. If the code ends in an expression, it returns the result of the expression, converted to Javascript objects (see {ref}`type_conversions`). @@ -124,7 +124,7 @@ Create and save a test `index.html` page with the following contents: ## Accessing Python scope from JavaScript -You can also access from JavaScript all functions and variables defined in Python using the {ref}`pyodide.globals `) object. +You can also access from JavaScript all functions and variables defined in Python using the {any}`pyodide.globals`) object. For example, if you initialize the variable `x = numpy.ones([3,3])` in Python, you can access it from JavaScript in your browser's developer console as follows: `pyodide.globals.x`. The same goes for functions and imports. See {ref}`type_conversions` for more details. diff --git a/docs/usage/type-conversions.md b/docs/usage/type-conversions.md index e0c570179..af20b9e2d 100644 --- a/docs/usage/type-conversions.md +++ b/docs/usage/type-conversions.md @@ -3,9 +3,8 @@ Python to Javascript conversions occur: -- when returning the final expression from a - {ref}`pyodide.runPython ` call -- using {ref}`pyodide.pyimport ` +- when returning the final expression from {any}`pyodide.runPython` +- using {any}`pyodide.pyimport` - passing arguments to a Javascript function from Python Javascript to Python conversions occur: @@ -122,7 +121,7 @@ foo.call_method(); // This will raise an exception, since the object has been ## Using Python objects from Javascript A Python object (in global scope) can be brought over to Javascript using the -{ref}`pyodide.pyimport ` function. It takes a string +{any}`pyodide.pyimport` function. It takes a string giving the name of the variable, and returns the object, converted to Javascript. diff --git a/src/pyodide.js b/src/pyodide.js index 0a5ad30bd..32ae206f3 100644 --- a/src/pyodide.js +++ b/src/pyodide.js @@ -3,6 +3,7 @@ */ globalThis.languagePluginLoader = new Promise((resolve, reject) => { + let Module = {}; // Note: PYODIDE_BASE_URL is an environement variable replaced in // in this template in the Makefile. It's recommended to always set // languagePluginUrl in any case. @@ -264,7 +265,29 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => { // It never fails. let loadPackageChain = Promise.resolve(); - async function loadPackage(names, messageCallback, errorCallback) { + /** + * @type {object} + * + * Use ``Object.keys(pyodide.loadedPackages)`` to get the list of names of + * loaded packages, and ``pyodide.loadedPackages[package_name]`` to access + * install location for a particular ``package_name``. + */ + Module.loadedPackages = {}; + + /** + * Load a package or a list of packages over the network. + * This makes the files for the package available in the virtual filesystem. + * The package needs to be imported from Python before it can be used. + * @param {String | Array} names package name, or URL. Can be either a single + * element, or an array + * @param {function} messageCallback A callback, called with progress messages + * (optional) + * @param {function} errorCallback A callback, called with error/warning + * messages (optional) + * @returns {Promise} Resolves to ``undefined`` when loading is complete + */ + Module.loadPackage = + async function(names, messageCallback, errorCallback) { if (!Array.isArray(names)) { names = [ names ]; } @@ -330,7 +353,6 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => { //////////////////////////////////////////////////////////// // Loading Pyodide - let Module = {}; self.Module = Module; Module.noImageDecoding = true; @@ -360,9 +382,61 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => { throw e; }; + /** + * @member {PyProxy} pyodide_py + * An alias to the Python pyodide package. + */ + + /** + * @member {PyProxy} globals + * An alias to the global Python namespace. + * + * An object whose attributes are members of the Python global namespace. This + * is an alternative to :meth:`pyimport`. For example, to access the ``foo`` + * Python object from Javascript use + * ``pyodide.globals.get("foo")`` + */ + + /** + * @member {string} version + * The pyodide version. + * + * It can be either the exact release version (e.g. `0.1.0`), or + * the latest release version followed by the number of commits since, and + * the git hash of the current commit (e.g. `0.1.0-1-bd84646`). + */ + + /** + * Runs a string of Python code from Javascript. + * + * The last part of the string may be an expression, in which case, its value + * is returned. + * + * @param {string} code Python code to evaluate + * @returns The result of the python code converted to Javascript + */ Module.runPython = code => Module.pyodide_py.eval_code(code, Module.globals); // clang-format off + /** + * Inspect a Python code chunk and use ``pyodide.loadPackage` to load any known + * packages that the code chunk imports. Uses + * :func:`pyodide_py.find_imports ` to inspect the code. + + * For example, given the following code chunk as input + * + * .. code-block:: python + * + * import numpy as np + * x = np.array([1, 2, 3]) + * + * :js:func:`loadPackagesFromImports` will call ``pyodide.loadPackage(['numpy'])``. + * See also :js:func:`runPythonAsync`. + * + * @param {*} code + * @param {*} messageCallback + * @param {*} errorCallback + */ Module.loadPackagesFromImports = async function(code, messageCallback, errorCallback) { let imports = Module.pyodide_py.find_imports(code).deepCopyToJavascript(); if (imports.length === 0) { @@ -377,22 +451,78 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => { } } if (packages.size) { - await loadPackage( + await Module.loadPackage( Array.from(packages.keys()), messageCallback, errorCallback ); } }; // clang-format on + /** + * Access a Python object in the global namespace from Javascript. + * @param {string} name Python variable name + * @returns If the Python object is an immutable type (string, number, + * boolean), it is converted to Javascript and returned. For other types, a + * `PyProxy` object is returned. + */ Module.pyimport = name => Module.globals[name]; + /** + * Runs Python code, possibly asynchronously loading any known packages that + * the code chunk imports. For example, given the following code chunk + * + * .. code-block:: python + * + * import numpy as np + * x = np.array([1, 2, 3]) + * + * pyodide will first call `pyodide.loadPackage(['numpy'])`, and then run the + * code chunk, returning the result. Since package fetching must happen + * asynchronously, this function returns a `Promise` which resolves to the + * output. For example: + * + * .. code-block:: javascript + * + * pyodide.runPythonAsync(code, messageCallback) + * .then((output) => handleOutput(output)) + * + * @param {string} code Python code to evaluate + * @param {Function} messageCallback A callback, called with progress + * messages. (optional) + * @param {Function} errorCallback A callback, called with error/warning + * messages. (optional) + */ Module.runPythonAsync = async function(code, messageCallback, errorCallback) { await Module.loadPackagesFromImports(code, messageCallback, errorCallback); return Module.runPython(code); }; + /** + * Registers the Js object ``module`` as a Js module with ``name``. + * This module can then be imported from Python using the standard Python + * import system. If another module by the same name has already been + * imported, this won't have much effect unless you also delete the imported + * module from + * ``sys.modules``. This calls the ``pyodide_py`` api + * :func:`pyodide.register_js_module`. + * + * @param {string} name Name of js module to add + * @param {object} module Javascript object backing the module + */ Module.registerJsModule = function( name, module) { Module.pyodide_py.register_js_module(name, module); }; + + /** + * Unregisters a Js module with given name that has been previously registered + * with :js:func:`registerJsModule` or :func:`pyodide.register_js_module`. If + * a Js module with that name does not already exist, will throw an error. + * Note that if the module has already been imported, this won't have much + * effect unless you also delete the imported module from ``sys.modules``. + * This calls the + * ``pyodide_py`` api :func:`pyodide.unregister_js_module`. + * + * @param {string} name Name of js module to remove + */ Module.unregisterJsModule = function( name) { Module.pyodide_py.unregister_js_module(name); }; @@ -500,15 +630,11 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => { }; const scriptSrc = `${baseURL}pyodide.asm.js`; - loadScript(scriptSrc).then(() => { + loadScript(scriptSrc).then(async () => { // 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. - pyodide(Module).then((x) => { - self.pyodide = x; - self.pyodide.loadedPackages = {}; - self.pyodide.loadPackage = loadPackage; - }, () => {}); + self.pyodide = await pyodide(Module); }); }); languagePluginLoader