diff --git a/micropip/package_index.py b/micropip/package_index.py index cafca25..d2027b1 100644 --- a/micropip/package_index.py +++ b/micropip/package_index.py @@ -171,6 +171,7 @@ def _compatible_wheels( sha256=sha256, size=size, core_metadata=core_metadata, + ) @classmethod diff --git a/micropip/transaction.py b/micropip/transaction.py index 9d73954..7631fc0 100644 --- a/micropip/transaction.py +++ b/micropip/transaction.py @@ -234,7 +234,6 @@ async def _add_requirement_from_package_index(self, req: Requirement): req.name, self.index_urls, self.fetch_kwargs, - compat_layer=self._compat_layer, ) logger.debug("Transaction: got metadata %r for requirement %r", metadata, req) diff --git a/tests/test_install.py b/tests/test_install.py index c0baff9..dfa520f 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -1,8 +1,6 @@ import pytest -from conftest import mock_fetch_cls from pytest_pyodide import run_in_pyodide -import micropip from micropip._vendored.packaging.src.packaging.utils import parse_wheel_filename @@ -141,7 +139,9 @@ def test_install_constraints( @pytest.mark.asyncio -async def test_package_with_extra(mock_fetch): +async def test_package_with_extra(host_micropip_with_mock_fetch): + micropip, mock_fetch = host_micropip_with_mock_fetch + mock_fetch.add_pkg_version("depa") mock_fetch.add_pkg_version("depb") mock_fetch.add_pkg_version("pkga", extras={"opt_feature": ["depa"]}) @@ -159,7 +159,9 @@ async def test_package_with_extra(mock_fetch): @pytest.mark.asyncio -async def test_package_with_extra_all(mock_fetch): +async def test_package_with_extra_all(host_micropip_with_mock_fetch): + micropip, mock_fetch = host_micropip_with_mock_fetch + mock_fetch.add_pkg_version("depa") mock_fetch.add_pkg_version("depb") mock_fetch.add_pkg_version("depc") @@ -183,8 +185,10 @@ async def test_package_with_extra_all(mock_fetch): @pytest.mark.parametrize("transitive_req", [True, False]) @pytest.mark.asyncio async def test_package_with_extra_transitive( - mock_fetch, transitive_req, mock_importlib + host_micropip_with_mock_fetch, transitive_req, mock_importlib ): + micropip, mock_fetch = host_micropip_with_mock_fetch + mock_fetch.add_pkg_version("depb") pkga_optional_dep = "depa[opt_feature]" if transitive_req else "depa" @@ -201,7 +205,9 @@ async def test_package_with_extra_transitive( @pytest.mark.asyncio -async def test_install_keep_going(mock_fetch: mock_fetch_cls) -> None: +async def test_install_keep_going(host_micropip_with_mock_fetch) -> None: + micropip, mock_fetch = host_micropip_with_mock_fetch + dummy = "dummy" dep1 = "dep1" dep2 = "dep2" @@ -216,7 +222,9 @@ async def test_install_keep_going(mock_fetch: mock_fetch_cls) -> None: @pytest.mark.asyncio -async def test_install_version_compare_prerelease(mock_fetch: mock_fetch_cls) -> None: +async def test_install_version_compare_prerelease(host_micropip_with_mock_fetch) -> None: + micropip, mock_fetch = host_micropip_with_mock_fetch + dummy = "dummy" version_old = "3.2.0" version_new = "3.2.1a1" @@ -233,7 +241,9 @@ async def test_install_version_compare_prerelease(mock_fetch: mock_fetch_cls) -> @pytest.mark.asyncio -async def test_install_no_deps(mock_fetch: mock_fetch_cls) -> None: +async def test_install_no_deps(host_micropip_with_mock_fetch) -> None: + micropip, mock_fetch = host_micropip_with_mock_fetch + dummy = "dummy" dep = "dep" mock_fetch.add_pkg_version(dummy, requirements=[dep]) @@ -248,9 +258,11 @@ async def test_install_no_deps(mock_fetch: mock_fetch_cls) -> None: @pytest.mark.asyncio @pytest.mark.parametrize("pre", [True, False]) async def test_install_pre( - mock_fetch: mock_fetch_cls, + host_micropip_with_mock_fetch, pre: bool, ) -> None: + micropip, mock_fetch = host_micropip_with_mock_fetch + dummy = "dummy" version_alpha = "2.0.1a1" version_stable = "1.0.0" @@ -264,18 +276,27 @@ async def test_install_pre( @pytest.mark.asyncio -async def test_fetch_wheel_fail(monkeypatch, wheel_base): - import micropip - from micropip import wheelinfo +async def test_fetch_wheel_fail(selenium_standalone_micropip, httpserver): - def _mock_fetch_bytes(arg, *args, **kwargs): - raise OSError(f"Request for {arg} failed with status 404: Not Found") + httpserver.expect_request("/fake-pkg-micropip-test-1.0.0-py3-none-any.whl").respond_with_data( + b"Not found", + status=404, + content_type="text/plain", + headers={"Access-Control-Allow-Origin": "*"}, + ) - monkeypatch.setattr(wheelinfo, "fetch_bytes", _mock_fetch_bytes) + url = httpserver.url_for("/fake-pkg-micropip-test-1.0.0-py3-none-any.whl") - msg = "Access-Control-Allow-Origin" - with pytest.raises(ValueError, match=msg): - await micropip.install("https://x.com/xxx-1.0.0-py3-none-any.whl") + @run_in_pyodide() + async def run_test(selenium, url): + import pytest + + import micropip + + with pytest.raises(ValueError, match="Access-Control-Allow-Origin"): + await micropip.install(url) + + run_test(selenium_standalone_micropip, url) @pytest.mark.skip_refcount_check @@ -312,8 +333,10 @@ async def call_micropip_install(pyfetch_mock): @pytest.mark.asyncio async def test_load_binary_wheel1( - mock_fetch: mock_fetch_cls, mock_importlib: None, mock_platform: None + host_micropip_with_mock_fetch, mock_importlib: None, mock_platform: None ) -> None: + micropip, mock_fetch = host_micropip_with_mock_fetch + dummy = "dummy" mock_fetch.add_pkg_version(dummy, platform="emscripten") await micropip.install(dummy) @@ -380,35 +403,6 @@ async def run_test(selenium, url, name, version): run_test(selenium_standalone_micropip, wheel_url, name, version) -@pytest.mark.asyncio -async def test_custom_index_urls(mock_package_index_json_api, monkeypatch): - mock_server_fake_package = mock_package_index_json_api( - pkgs=["fake-pkg-micropip-test"] - ) - - _wheel_url = "" - - async def _mock_fetch_bytes(url, *args): - nonlocal _wheel_url - _wheel_url = url - return b"fake wheel" - - from micropip import wheelinfo - - monkeypatch.setattr(wheelinfo, "fetch_bytes", _mock_fetch_bytes) - - try: - await micropip.install( - "fake-pkg-micropip-test", index_urls=[mock_server_fake_package] - ) - except Exception: - # We just check that the custom index url was used - # install will fail because the package is not real, but it doesn't matter. - pass - - assert "fake_pkg_micropip_test-1.0.0-py2.py3-none-any.whl" in _wheel_url - - def test_install_pkg_with_sharedlib_deps(selenium_standalone_micropip, wheel_catalog): """ Test if micropip can locate shared libraries in the wheel file correctly. diff --git a/tests/test_transaction.py b/tests/test_transaction.py index e6abc0c..f08b982 100644 --- a/tests/test_transaction.py +++ b/tests/test_transaction.py @@ -285,7 +285,7 @@ def test_last_version_and_best_tag_from_pypi( assert str(wheel.version) == new_version -def test_search_pyodide_lock_first(): +def test_search_pyodide_lock_first(host_compat_layer): from micropip import package_index from micropip.transaction import Transaction @@ -298,6 +298,7 @@ def test_search_pyodide_lock_first(): fetch_kwargs={}, verbose=False, index_urls=package_index.DEFAULT_INDEX_URLS, + _compat_layer=host_compat_layer, ) assert t.search_pyodide_lock_first is True @@ -310,13 +311,14 @@ def test_search_pyodide_lock_first(): fetch_kwargs={}, verbose=False, index_urls=["https://my.custom.index.com"], + _compat_layer=host_compat_layer, ) assert t.search_pyodide_lock_first is False @pytest.mark.asyncio async def test_index_url_priority( - mock_importlib, wheel_base, monkeypatch, mock_package_index_simple_json_api + mock_importlib, wheel_base, monkeypatch, mock_package_index_simple_json_api, host_compat_layer ): # Test that if the index_urls are provided, package should be searched in # the index_urls first before searching in Pyodide lock file. @@ -341,6 +343,7 @@ async def mock_add_wheel(self, wheel, extras, *, specifier=""): ctx_extras=[], fetch_kwargs={}, index_urls=mock_index_url, + _compat_layer=host_compat_layer, ) await t.add_requirement("black") diff --git a/tests/test_wheelinfo.py b/tests/test_wheelinfo.py index 4eff860..3494ecb 100644 --- a/tests/test_wheelinfo.py +++ b/tests/test_wheelinfo.py @@ -3,9 +3,9 @@ from micropip.wheelinfo import WheelInfo -def test_from_url(): +def test_from_url(host_compat_layer): url = "https://test.com/dummy_module-0.0.1-py3-none-any.whl" - wheel = WheelInfo.from_url(url) + wheel = WheelInfo.from_url(url, compat_layer=host_compat_layer) assert wheel.name == "dummy-module" assert str(wheel.version) == "0.0.1" @@ -15,7 +15,7 @@ def test_from_url(): assert wheel.sha256 is None -def test_from_package_index(): +def test_from_package_index(host_compat_layer): name = "dummy-module" filename = "dummy_module-0.0.1-py3-none-any.whl" url = "https://test.com/dummy_module-0.0.1-py3-none-any.whl" @@ -25,7 +25,7 @@ def test_from_package_index(): core_metadata = True wheel = WheelInfo.from_package_index( - name, filename, url, version, sha256, size, core_metadata + name, filename, url, version, sha256, size, core_metadata, compat_layer=host_compat_layer ) assert wheel.name == name @@ -37,9 +37,9 @@ def test_from_package_index(): assert wheel.core_metadata == core_metadata -def test_extract(wheel_catalog, tmp_path): +def test_extract(wheel_catalog, tmp_path, host_compat_layer): pytest_wheel = wheel_catalog.get("pytest") - dummy_wheel = WheelInfo.from_url(pytest_wheel.url) + dummy_wheel = WheelInfo.from_url(pytest_wheel.url, compat_layer=host_compat_layer) dummy_wheel._data = pytest_wheel.content dummy_wheel._extract(tmp_path) @@ -47,9 +47,9 @@ def test_extract(wheel_catalog, tmp_path): assert dummy_wheel._dist_info.is_dir() -def test_set_installer(wheel_catalog, tmp_path): +def test_set_installer(wheel_catalog, tmp_path, host_compat_layer): pytest_wheel = wheel_catalog.get("pytest") - dummy_wheel = WheelInfo.from_url(pytest_wheel.url) + dummy_wheel = WheelInfo.from_url(pytest_wheel.url, compat_layer=host_compat_layer) dummy_wheel._data = pytest_wheel.content dummy_wheel._extract(tmp_path) @@ -67,9 +67,9 @@ def test_install(): @pytest.mark.asyncio -async def test_download(wheel_catalog): +async def test_download(wheel_catalog, host_compat_layer): pytest_wheel = wheel_catalog.get("pytest") - wheel = WheelInfo.from_url(pytest_wheel.url) + wheel = WheelInfo.from_url(pytest_wheel.url, compat_layer=host_compat_layer) assert wheel._metadata is None @@ -79,9 +79,9 @@ async def test_download(wheel_catalog): @pytest.mark.asyncio -async def test_requires(wheel_catalog, tmp_path): +async def test_requires(wheel_catalog, tmp_path, host_compat_layer): pytest_wheel = wheel_catalog.get("pytest") - wheel = WheelInfo.from_url(pytest_wheel.url) + wheel = WheelInfo.from_url(pytest_wheel.url, compat_layer=host_compat_layer) await wheel.download({}) wheel._extract(tmp_path) @@ -96,7 +96,7 @@ async def test_requires(wheel_catalog, tmp_path): @pytest.mark.asyncio -async def test_download_pep658_metadata(wheel_catalog): +async def test_download_pep658_metadata(wheel_catalog, host_compat_layer): pytest_wheel = wheel_catalog.get("pytest") sha256 = "dummy-sha256" size = 1234 @@ -110,6 +110,7 @@ async def test_download_pep658_metadata(wheel_catalog): sha256, size, core_metadata=True, + compat_layer=host_compat_layer, ) assert wheel_with_metadata.pep658_metadata_available() @@ -131,6 +132,7 @@ async def test_download_pep658_metadata(wheel_catalog): sha256, size, core_metadata=None, + compat_layer=host_compat_layer, ) assert not wheel_without_metadata.pep658_metadata_available() @@ -147,6 +149,7 @@ async def test_download_pep658_metadata(wheel_catalog): sha256, size, core_metadata=None, + compat_layer=host_compat_layer, ) assert wheel._metadata is None @@ -186,6 +189,7 @@ async def test_download_pep658_metadata_checksum(wheel_catalog, host_compat_laye sha256, size, core_metadata={"sha256": checksum}, + compat_layer=host_compat_layer, ) assert wheel._metadata is None