From c7a29954717172e2041c568ff783ca92fafa1eca Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Wed, 26 Mar 2025 23:58:52 +0530 Subject: [PATCH 1/5] Don't raise HTTPStatusError on CORS errors --- micropip/package_index.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/micropip/package_index.py b/micropip/package_index.py index 8128f06b..a1cc4618 100644 --- a/micropip/package_index.py +++ b/micropip/package_index.py @@ -9,7 +9,7 @@ from typing import Any from urllib.parse import urljoin, urlparse, urlunparse -from ._compat import HttpStatusError, fetch_string_and_headers +from ._compat import fetch_string_and_headers from ._utils import is_package_compatible, parse_version from ._vendored.mousebender.simple import from_project_details_html from ._vendored.packaging.src.packaging.utils import InvalidWheelFilename @@ -313,14 +313,9 @@ async def query_package( logger.debug("Url has no placeholder, appending package name : %r", url) try: metadata, headers = await fetch_string_and_headers(url, _fetch_kwargs) - except HttpStatusError as e: - if e.status_code == 404: - logger.debug("NotFound (404) for %r, trying next index.", url) - continue - logger.debug( - "Error fetching %r (%s), trying next index.", url, e.status_code - ) - raise + except Exception as e: + logger.debug("Error fetching metadata for %r: %r", url, e) + continue content_type = headers.get("content-type", "").lower() try: From 865720027734d84d443799eb948103b8ac57a87e Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Fri, 28 Mar 2025 17:50:32 +0530 Subject: [PATCH 2/5] Better log message Co-authored-by: Gyeongjae Choi --- micropip/package_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micropip/package_index.py b/micropip/package_index.py index a1cc4618..ed5ccbc0 100644 --- a/micropip/package_index.py +++ b/micropip/package_index.py @@ -314,7 +314,7 @@ async def query_package( try: metadata, headers = await fetch_string_and_headers(url, _fetch_kwargs) except Exception as e: - logger.debug("Error fetching metadata for %r: %r", url, e) + logger.debug("Error fetching metadata for the package %r from (%r): %r, trying next index.", name, url, e) continue content_type = headers.get("content-type", "").lower() From c8ba44644c7882b5f2ad986fb11c806782edc86c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 28 Mar 2025 12:20:45 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- micropip/package_index.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/micropip/package_index.py b/micropip/package_index.py index ed5ccbc0..3fa998e7 100644 --- a/micropip/package_index.py +++ b/micropip/package_index.py @@ -314,7 +314,12 @@ async def query_package( try: metadata, headers = await fetch_string_and_headers(url, _fetch_kwargs) except Exception as e: - logger.debug("Error fetching metadata for the package %r from (%r): %r, trying next index.", name, url, e) + logger.debug( + "Error fetching metadata for the package %r from (%r): %r, trying next index.", + name, + url, + e, + ) continue content_type = headers.get("content-type", "").lower() From b695bbdc2f67da57371242c0f23336012b40dcfa Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Fri, 28 Mar 2025 17:57:41 +0530 Subject: [PATCH 4/5] Drop `micropip._compat.HttpStatusError` --- micropip/_compat/__init__.py | 4 ---- micropip/_compat/compatibility_layer.py | 8 ------- tests/test_compat.py | 30 ------------------------- 3 files changed, 42 deletions(-) delete mode 100644 tests/test_compat.py diff --git a/micropip/_compat/__init__.py b/micropip/_compat/__init__.py index 737add1b..a9e07387 100644 --- a/micropip/_compat/__init__.py +++ b/micropip/_compat/__init__.py @@ -34,9 +34,6 @@ to_js = compatibility_layer.to_js -HttpStatusError = compatibility_layer.HttpStatusError - - __all__ = [ "LOCKFILE_INFO", "LOCKFILE_PACKAGES", @@ -47,5 +44,4 @@ "loadPackage", "get_dynlibs", "to_js", - "HttpStatusError", ] diff --git a/micropip/_compat/compatibility_layer.py b/micropip/_compat/compatibility_layer.py index dc963520..13e7705d 100644 --- a/micropip/_compat/compatibility_layer.py +++ b/micropip/_compat/compatibility_layer.py @@ -13,14 +13,6 @@ class CompatibilityLayer(ABC): All of the following methods / properties must be implemented for use both inside and outside of pyodide. """ - class HttpStatusError(ABC, Exception): - status_code: int - message: str - - @abstractmethod - def __init__(self, status_code: int, message: str): - pass - class loadedPackages(ABC): @staticmethod @abstractmethod diff --git a/tests/test_compat.py b/tests/test_compat.py deleted file mode 100644 index 6a886de9..00000000 --- a/tests/test_compat.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -test that function in compati behave the same - -""" - -import pytest -from pytest_pyodide import run_in_pyodide - - -@pytest.mark.driver_timeout(10) -def test_404(selenium_standalone_micropip, httpserver, request): - selenium_standalone_micropip.set_script_timeout(11) - - @run_in_pyodide(packages=["micropip", "packaging"]) - async def _inner_test_404_raise(selenium, url): - import pytest - - from micropip._compat import HttpStatusError, fetch_string_and_headers - - with pytest.raises(HttpStatusError): - await fetch_string_and_headers(url, {}) - - httpserver.expect_request("/404").respond_with_data( - "Not found", - status=404, - content_type="text/plain", - headers={"Access-Control-Allow-Origin": "*"}, - ) - url_404 = httpserver.url_for("/404") - _inner_test_404_raise(selenium_standalone_micropip, url_404) From abc1437ae6bc3e67718e51c3b91ae7910f4124f6 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:13:30 +0530 Subject: [PATCH 5/5] Drop HttpStatusError completely --- micropip/_compat/_compat_in_pyodide.py | 18 ++++-------------- micropip/_compat/_compat_not_in_pyodide.py | 16 +--------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/micropip/_compat/_compat_in_pyodide.py b/micropip/_compat/_compat_in_pyodide.py index 198afeab..323ec2d7 100644 --- a/micropip/_compat/_compat_in_pyodide.py +++ b/micropip/_compat/_compat_in_pyodide.py @@ -7,7 +7,7 @@ from pyodide._package_loader import get_dynlibs from pyodide.ffi import IN_BROWSER, to_js -from pyodide.http import HttpStatusError, pyfetch +from pyodide.http import pyfetch from .compatibility_layer import CompatibilityLayer @@ -28,14 +28,6 @@ class CompatibilityInPyodide(CompatibilityLayer): - class HttpStatusError(Exception): - status_code: int - message: str - - def __init__(self, status_code: int, message: str): - self.status_code = status_code - self.message = message - super().__init__(message) @staticmethod async def fetch_bytes(url: str, kwargs: dict[str, str]) -> bytes: @@ -51,11 +43,9 @@ async def fetch_bytes(url: str, kwargs: dict[str, str]) -> bytes: async def fetch_string_and_headers( url: str, kwargs: dict[str, str] ) -> tuple[str, dict[str, str]]: - try: - response = await pyfetch(url, **kwargs) - response.raise_for_status() - except HttpStatusError as e: - raise CompatibilityInPyodide.HttpStatusError(e.status, str(e)) from e + + response = await pyfetch(url, **kwargs) + response.raise_for_status() content = await response.string() headers: dict[str, str] = response.headers diff --git a/micropip/_compat/_compat_not_in_pyodide.py b/micropip/_compat/_compat_not_in_pyodide.py index 978c724e..c7c9dd77 100644 --- a/micropip/_compat/_compat_not_in_pyodide.py +++ b/micropip/_compat/_compat_not_in_pyodide.py @@ -1,7 +1,6 @@ import re from pathlib import Path from typing import IO, TYPE_CHECKING, Any -from urllib.error import HTTPError from urllib.request import Request, urlopen from urllib.response import addinfourl @@ -17,15 +16,6 @@ class CompatibilityNotInPyodide(CompatibilityLayer): # TODO: use packaging APIs here instead? _canonicalize_regex = re.compile(r"[-_.]+") - class HttpStatusError(Exception): - status_code: int - message: str - - def __init__(self, status_code: int, message: str): - self.status_code = status_code - self.message = message - super().__init__(message) - class loadedPackages(CompatibilityLayer.loadedPackages): @staticmethod def to_py(): @@ -43,11 +33,7 @@ async def fetch_bytes(url: str, kwargs: dict[str, Any]) -> bytes: async def fetch_string_and_headers( url: str, kwargs: dict[str, Any] ) -> tuple[str, dict[str, str]]: - try: - response = CompatibilityNotInPyodide._fetch(url, kwargs=kwargs) - except HTTPError as e: - raise CompatibilityNotInPyodide.HttpStatusError(e.code, str(e)) from e - + response = CompatibilityNotInPyodide._fetch(url, kwargs=kwargs) headers = {k.lower(): v for k, v in response.headers.items()} return response.read().decode(), headers