diff --git a/micropip/_compat/_compat_in_pyodide.py b/micropip/_compat/_compat_in_pyodide.py index be839de..58fb8f1 100644 --- a/micropip/_compat/_compat_in_pyodide.py +++ b/micropip/_compat/_compat_in_pyodide.py @@ -5,9 +5,21 @@ if TYPE_CHECKING: pass +import pyodide +from packaging.version import parse from pyodide._package_loader import get_dynlibs from pyodide.ffi import IN_BROWSER, to_js -from pyodide.http import HttpStatusError, pyfetch + +if parse(pyodide.__version__) > parse("0.27"): + from pyodide.http import HttpStatusError, pyfetch +else: + + class HttpStatusError(Exception): # type: ignore [no-redef] + """we just want this to be defined, it is never going to be raised""" + + pass + + from pyodide.http import pyfetch from .compatibility_layer import CompatibilityLayer diff --git a/micropip/package_index.py b/micropip/package_index.py index 2772b7b..f3d43e3 100644 --- a/micropip/package_index.py +++ b/micropip/package_index.py @@ -10,7 +10,7 @@ from packaging.utils import InvalidWheelFilename from packaging.version import InvalidVersion, Version -from ._compat import fetch_string_and_headers +from ._compat import HttpStatusError, fetch_string_and_headers from ._utils import is_package_compatible, parse_version from .externals.mousebender.simple import from_project_details_html from .wheelinfo import WheelInfo @@ -276,11 +276,33 @@ async def query_package( try: metadata, headers = await fetch_string_and_headers(url, _fetch_kwargs) + except HttpStatusError as e: + if e.status_code == 404: + continue + raise except OSError: - continue + # temporary pyodide compatibility. + # pypi now set proper CORS on 404 (https://github.com/pypi/warehouse/pull/16339), + # but stable pyodide (<0.27) does not yet have proper HttpStatusError exception + # so when: on pyodide and 0.26.x we ignore OSError. Once we drop support for 0.26 + # all this OSError except clause should just be gone. + try: + import pyodide + from packaging.version import parse + + if parse(pyodide.__version__) > parse("0.27"): + # reraise on more recent pyodide. + raise + continue + except ImportError: + # not in pyodide. + raise content_type = headers.get("content-type", "").lower() - parser = _select_parser(content_type, name) + try: + parser = _select_parser(content_type, name) + except ValueError as e: + raise ValueError(f"Error trying to decode url: {url}") from e return parser(metadata) else: raise ValueError(