FIX Tell loadPackage about packages installed with micropip (#1457)

This commit is contained in:
Hood Chatham 2021-04-12 22:50:41 -04:00 committed by GitHub
parent 345ab910f1
commit c96583f1e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 11 deletions

View File

@ -54,18 +54,18 @@ substitutions:
`pyodide.globals.get('key')`. [#1367](https://github.com/pyodide/pyodide/pull/1367)
- {{ API }} Added {any}`PyProxy.getBuffer` API to allow direct access to Python
buffers as Javascript TypedArrays.
[1215](https://github.com/pyodide/pyodide/pull/1215)
[#1215](https://github.com/pyodide/pyodide/pull/1215)
- {{ API }} The innermost level of a buffer converted to Javascript used to be a
TypedArray if the buffer was contiguous and otherwise an Array. Now the
innermost level will be a TypedArray unless the buffer format code is a '?' in
which case it will be an Array of booleans, or if the format code is a "s" in
which case the innermost level will be converted to a string.
[1376](https://github.com/pyodide/pyodide/pull/1376)
[#1376](https://github.com/pyodide/pyodide/pull/1376)
- {{ Enhancement }} Javascript `BigInt`s are converted into Python `int` and
Python `int`s larger than 2^53 are converted into `BigInt`.
[1407](https://github.com/pyodide/pyodide/pull/1407)
[#1407](https://github.com/pyodide/pyodide/pull/1407)
- {{ API }} Added {any}`pyodide.isPyProxy` to test if an object is a `PyProxy`.
[1456](https://github.com/pyodide/pyodide/pull/1456)
[#1456](https://github.com/pyodide/pyodide/pull/1456)
### Fixed
- {{ Fix }} getattr and dir on JsProxy now report consistent results and include all
@ -136,13 +136,16 @@ substitutions:
- Changed the loading method: added an async function `loadPyodide` to load
Pyodide to use instead of `languagePluginURL` and `languagePluginLoader`. The
change is currently backwards compatible, but the old approach is deprecated.
[1363](https://github.com/pyodide/pyodide/pull/1363)
[#1363](https://github.com/pyodide/pyodide/pull/1363)
### micropip
- {{ Feature }} `micropip` now supports installing wheels from relative URLs.
[#872](https://github.com/pyodide/pyodide/pull/872)
- {{ API }} `micropip.install` now returns a Python `Future` instead of a Javascript `Promise`.
[#1324](https://github.com/pyodide/pyodide/pull/1324/)
- {{ FIX }} {any}`micropip.install` now interacts correctly with {any}`pyodide.loadPackage`.
[#1457](https://github.com/pyodide/pyodide/pull/1457/)
### Build system

View File

@ -57,6 +57,14 @@ else:
return result
if IN_BROWSER:
from pyodide_js import loadedPackages
else:
class loadedPackages: # type: ignore
pass
async def _get_pypi_json(pkgname):
url = f"https://pypi.org/pypi/{pkgname}/json"
fd = await _get_url(url)
@ -112,6 +120,7 @@ async def _install_wheel(name, fileinfo):
wheel = await _get_url(url)
_validate_wheel(wheel, fileinfo)
_extract_wheel(wheel)
setattr(loadedPackages, name, url)
class _PackageManager:
@ -155,14 +164,15 @@ class _PackageManager:
# Note: branch never happens in out-of-browser testing because we
# report that all dependencies are empty.
self.installed_packages.update(dict((k, None) for k in pyodide_packages))
wheel_promises.append(pyodide_js.loadPackage(list(pyodide_packages)))
wheel_promises.append(
asyncio.ensure_future(pyodide_js.loadPackage(list(pyodide_packages)))
)
# Now install PyPI packages
for name, wheel, ver in transaction["wheels"]:
wheel_promises.append(_install_wheel(name, wheel))
self.installed_packages[name] = ver
await gather(*wheel_promises)
return f'Installed {", ".join(self.installed_packages.keys())}'
async def add_requirement(self, requirement: str, ctx, transaction):
if requirement.endswith(".whl"):
@ -245,8 +255,8 @@ def install(requirements: Union[str, List[str]]):
----------
requirements : ``str | List[str]``
A requirement or list of requirements to install. Each requirement is a string, which should be either
a package name or URL to a wheel:
A requirement or list of requirements to install. Each requirement is a
string, which should be either a package name or URL to a wheel:
- If the requirement ends in ``.whl`` it will be interpreted as a URL.
The file must be a wheel named in compliance with the
@ -260,8 +270,8 @@ def install(requirements: Union[str, List[str]]):
-------
``Future``
A ``Future`` that resolves to ``None`` when all packages have
been downloaded and installed.
A ``Future`` that resolves to ``None`` when all packages have been
downloaded and installed.
"""
importlib.invalidate_caches()
return asyncio.ensure_future(PACKAGE_MANAGER.install(requirements))

View File

@ -170,3 +170,25 @@ def test_last_version_from_pypi():
wheel, ver = micropip.PACKAGE_MANAGER.find_wheel(metadata, requirement)
assert ver == "0.15.5"
def test_install_different_version(selenium_standalone_micropip):
selenium = selenium_standalone_micropip
selenium.run_js(
"""
await pyodide.runPythonAsync(`
import micropip
await micropip.install(
"https://files.pythonhosted.org/packages/89/06/2c2d3034b4d6bf22f2a4ae546d16925898658a33b4400cfb7e2c1e2871a3/pytz-2020.5-py2.py3-none-any.whl"
);
`);
"""
)
selenium.run_js(
"""
pyodide.runPython(`
import pytz
assert pytz.__version__ == "2020.5"
`);
"""
)