Skip to content

Commit

Permalink
ENH Add raise_for_status to FetchResponse (#4053)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoodmane committed Aug 9, 2023
1 parent f8f026a commit 691bee1
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 6 deletions.
13 changes: 7 additions & 6 deletions docs/project/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ myst:
present also on `Task`s as well as `Future`s.
{pr}`3748`

- {{ Enhancement }} Added `headers` property to `pyodide.http.FetchResponse`.
{pr}`2078`

- {{ Enhancement }} Added methods to a `PyProxy` of a `list` to make these work
as drop-in replacements for JavaScript Arrays.
{pr}`3853`
Expand All @@ -70,9 +67,13 @@ myst:
`pyodide-lock.json`
{pr}`3824`

- {{ Breaking }} Changed the FetchResponse body getter methods to no longer
throw an OSError exception for 400 and above response status codes
{pr}`3986`
- {{ Enhancement }} Added `headers` property to `pyodide.http.FetchResponse`.
{pr}`2078`

- {{ Breaking }} Changed the `FetchResponse` body getter methods to no longer
throw an `OSError` exception for 400 and above response status codes. Added
`FetchResponse.raise_for_status` to raise an `OSError` for error status codes.
{pr}`3986` {pr}`4053`

### Packages

Expand Down
16 changes: 16 additions & 0 deletions src/py/pyodide/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ def _raise_if_failed(self) -> None:
if self.js_response.bodyUsed:
raise OSError("Response body is already used")

def raise_for_status(self) -> None:
"""Raise an :py:exc:`OSError` if the status of the response is an error (4xx or 5xx)"""
http_error_msg = ""
if 400 <= self.status < 500:
http_error_msg = (
f"{self.status} Client Error: {self.status_text} for url: {self.url}"
)

if 500 <= self.status < 600:
http_error_msg = (
f"{self.status} Server Error: {self.status_text} for url: {self.url}"
)

if http_error_msg:
raise OSError(http_error_msg)

def clone(self) -> "FetchResponse":
"""Return an identical copy of the :py:class:`FetchResponse`.
Expand Down
44 changes: 44 additions & 0 deletions src/tests/test_pyodide_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,50 @@ async def test_pyfetch_return_400_status_body(selenium, url_notfound):
assert body == "404 Not Found"


@pytest.fixture
def raise_for_status_fixture(httpserver):
httpserver.expect_request("/200").respond_with_data(
b"Some data here!",
content_type="text/text",
headers={"Access-Control-Allow-Origin": "*"},
status=200,
)
httpserver.expect_request("/404").respond_with_data(
b"Not Found",
content_type="text/text",
headers={"Access-Control-Allow-Origin": "*"},
status=404,
)
httpserver.expect_request("/504").respond_with_data(
b"Gateway timeout",
content_type="text/text",
headers={"Access-Control-Allow-Origin": "*"},
status=504,
)
return {p: httpserver.url_for(p) for p in ["/200", "/404", "/504"]}


@run_in_pyodide
async def test_pyfetch_raise_for_status(selenium, raise_for_status_fixture):
import pytest

from pyodide.http import pyfetch

resp = await pyfetch(raise_for_status_fixture["/200"])
resp.raise_for_status()
assert await resp.string() == "Some data here!"

resp = await pyfetch(raise_for_status_fixture["/404"])
with pytest.raises(OSError, match="404 Client Error: NOT FOUND for url: .*/404"):
resp.raise_for_status()

resp = await pyfetch(raise_for_status_fixture["/504"])
with pytest.raises(
OSError, match="504 Server Error: GATEWAY TIMEOUT for url: .*/504"
):
resp.raise_for_status()


@run_in_pyodide
async def test_pyfetch_unpack_archive(selenium):
import pathlib
Expand Down

0 comments on commit 691bee1

Please sign in to comment.