Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revise lazy wheel and its tests #8584

Merged
merged 2 commits into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/pip/_internal/network/lazy_wheel.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Lazy ZIP over HTTP"""

__all__ = ['dist_from_wheel_url']
__all__ = ['HTTPRangeRequestUnsupported', 'dist_from_wheel_url']

from bisect import bisect_left, bisect_right
from contextlib import contextmanager
Expand All @@ -23,13 +23,18 @@
from pip._internal.network.session import PipSession


class HTTPRangeRequestUnsupported(Exception):
pass


def dist_from_wheel_url(name, url, session):
# type: (str, str, PipSession) -> Distribution
"""Return a pkg_resources.Distribution from the given wheel URL.

This uses HTTP range requests to only fetch the potion of the wheel
containing metadata, just enough for the object to be constructed.
If such requests are not supported, RuntimeError is raised.
If such requests are not supported, HTTPRangeRequestUnsupported
is raised.
"""
with LazyZipOverHTTP(url, session) as wheel:
# For read-only ZIP files, ZipFile only needs methods read,
Expand All @@ -45,7 +50,8 @@ class LazyZipOverHTTP(object):

This uses HTTP range requests to lazily fetch the file's content,
which is supposed to be fed to ZipFile. If such requests are not
supported by the server, raise RuntimeError during initialization.
supported by the server, raise HTTPRangeRequestUnsupported
during initialization.
"""

def __init__(self, url, session, chunk_size=CONTENT_CHUNK_SIZE):
Expand All @@ -60,7 +66,7 @@ def __init__(self, url, session, chunk_size=CONTENT_CHUNK_SIZE):
self._left = [] # type: List[int]
self._right = [] # type: List[int]
if 'bytes' not in head.headers.get('Accept-Ranges', 'none'):
raise RuntimeError('range request is not supported')
raise HTTPRangeRequestUnsupported('range request is not supported')
self._check_zip()

@property
Expand Down
Binary file added tests/data/packages/mypy-0.782-py3-none-any.whl
Binary file not shown.
25 changes: 18 additions & 7 deletions tests/unit/test_network_lazy_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
from pip._vendor.pkg_resources import Requirement
from pytest import fixture, mark, raises

from pip._internal.network.lazy_wheel import dist_from_wheel_url
from pip._internal.network.lazy_wheel import (
HTTPRangeRequestUnsupported,
dist_from_wheel_url,
)
from pip._internal.network.session import PipSession
from tests.lib.requests_mocks import MockResponse
from tests.lib.server import file_response

MYPY_0_782_WHL = (
'https://files.pythonhosted.org/packages/9d/65/'
Expand All @@ -25,6 +28,16 @@ def session():
return PipSession()


@fixture
def mypy_whl_no_range(mock_server, shared_data):
mypy_whl = shared_data.packages / 'mypy-0.782-py3-none-any.whl'
mock_server.set_responses([file_response(mypy_whl)])
mock_server.start()
base_address = 'http://{}:{}'.format(mock_server.host, mock_server.port)
yield "{}/{}".format(base_address, 'mypy-0.782-py3-none-any.whl')
mock_server.stop()


@mark.network
def test_dist_from_wheel_url(session):
"""Test if the acquired distribution contain correct information."""
Expand All @@ -35,12 +48,10 @@ def test_dist_from_wheel_url(session):
assert set(dist.requires(dist.extras)) == MYPY_0_782_REQS


@mark.network
def test_dist_from_wheel_url_no_range(session, monkeypatch):
def test_dist_from_wheel_url_no_range(session, mypy_whl_no_range):
"""Test handling when HTTP range requests are not supported."""
monkeypatch.setattr(session, 'head', lambda *a, **kw: MockResponse(b''))
with raises(RuntimeError):
dist_from_wheel_url('mypy', MYPY_0_782_WHL, session)
with raises(HTTPRangeRequestUnsupported):
dist_from_wheel_url('mypy', mypy_whl_no_range, session)


@mark.network
Expand Down