Skip to content

Commit

Permalink
lazy-wheel: improve handling of servers that tell us that they suppor…
Browse files Browse the repository at this point in the history
…t range requests but do not respect them
  • Loading branch information
radoering authored and abn committed Mar 1, 2024
1 parent a70330b commit fd8489e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
12 changes: 11 additions & 1 deletion src/poetry/inspection/lazy_wheel.py
Expand Up @@ -49,6 +49,11 @@ class HTTPRangeRequestUnsupported(LazyWheelUnsupportedError):
"""Raised when the remote server appears unable to support byte ranges."""


class HTTPRangeRequestNotRespected(LazyWheelUnsupportedError):
"""Raised when the remote server tells us that it supports byte ranges
but does not respect a respective request."""


class UnsupportedWheel(LazyWheelUnsupportedError):
"""Unsupported wheel."""

Expand Down Expand Up @@ -429,7 +434,12 @@ def _stream_response(self, start: int, end: int) -> Response:
self._request_count += 1
response = self._session.get(self._url, headers=headers, stream=True)
response.raise_for_status()
assert int(response.headers["Content-Length"]) == (end - start + 1)
if int(response.headers["Content-Length"]) != (end - start + 1):
raise HTTPRangeRequestNotRespected(
f"server did not respect byte range request: "
f"requested {end - start + 1} bytes, got "
f"{response.headers['Content-Length']} bytes"
)
return response

def _fetch_content_range(self, start: int, end: int) -> Iterator[bytes]:
Expand Down
30 changes: 29 additions & 1 deletion tests/inspection/test_lazy_wheel.py
Expand Up @@ -14,6 +14,7 @@

from requests import codes

from poetry.inspection.lazy_wheel import HTTPRangeRequestNotRespected
from poetry.inspection.lazy_wheel import HTTPRangeRequestUnsupported
from poetry.inspection.lazy_wheel import InvalidWheel
from poetry.inspection.lazy_wheel import LazyWheelUnsupportedError
Expand All @@ -38,6 +39,7 @@ def __call__(
*,
accept_ranges: str | None = "bytes",
negative_offset_error: tuple[int, bytes] | None = None,
ignore_accept_ranges: bool = False,
) -> HTTPrettyRequestCallback: ...

class AssertMetadataFromWheelUrl(Protocol):
Expand Down Expand Up @@ -113,6 +115,7 @@ def _factory(
*,
accept_ranges: str | None = "bytes",
negative_offset_error: tuple[int, bytes] | None = None,
ignore_accept_ranges: bool = False,
) -> HTTPrettyRequestCallback:
def handle_request(
request: HTTPrettyRequest, uri: str, response_headers: dict[str, Any]
Expand Down Expand Up @@ -156,7 +159,7 @@ def handle_request(
response_headers,
negative_offset_error[1],
)
if accept_ranges == "bytes" and rng:
if accept_ranges == "bytes" and rng and not ignore_accept_ranges:
return build_partial_response(
rng,
wheel_bytes,
Expand Down Expand Up @@ -404,6 +407,31 @@ def test_metadata_from_wheel_url_range_requests_not_supported_two_requests(
assert latest_requests[1].method == "HEAD"


def test_metadata_from_wheel_url_range_requests_supported_but_not_respected(
http: type[httpretty.httpretty],
handle_request_factory: RequestCallbackFactory,
) -> None:
domain = "range-requests-not-respected.com"
uri_regex = re.compile(f"^https://{domain}/.*$")
request_callback = handle_request_factory(
negative_offset_error=(codes.method_not_allowed, b"Method not allowed"),
ignore_accept_ranges=True,
)
http.register_uri(http.GET, uri_regex, body=request_callback)
http.register_uri(http.HEAD, uri_regex, body=request_callback)

url = f"https://{domain}/poetry_core-1.5.0-py3-none-any.whl"

with pytest.raises(HTTPRangeRequestNotRespected):
metadata_from_wheel_url("poetry-core", url, requests.Session())

latest_requests = http.latest_requests()
assert len(latest_requests) == 3
assert latest_requests[0].method == "GET"
assert latest_requests[1].method == "HEAD"
assert latest_requests[2].method == "GET"


def test_metadata_from_wheel_url_invalid_wheel(
http: type[httpretty.httpretty],
handle_request_factory: RequestCallbackFactory,
Expand Down

0 comments on commit fd8489e

Please sign in to comment.