1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Add download_info to InstallRequirement

This commit is contained in:
Stéphane Bidoul 2022-05-22 18:41:43 +02:00
parent b69f505757
commit c6baa7514a
No known key found for this signature in database
GPG key ID: BCAB2555446B5B92
3 changed files with 145 additions and 1 deletions

View file

@ -25,6 +25,7 @@ from pip._internal.exceptions import (
)
from pip._internal.index.package_finder import PackageFinder
from pip._internal.metadata import BaseDistribution
from pip._internal.models.direct_url import ArchiveInfo
from pip._internal.models.link import Link
from pip._internal.models.wheel import Wheel
from pip._internal.network.download import BatchDownloader, Downloader
@ -35,9 +36,18 @@ from pip._internal.network.lazy_wheel import (
from pip._internal.network.session import PipSession
from pip._internal.operations.build.build_tracker import BuildTracker
from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.direct_url_helpers import (
direct_url_for_editable,
direct_url_from_link,
)
from pip._internal.utils.hashes import Hashes, MissingHashes
from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import display_path, hide_url, is_installable_dir
from pip._internal.utils.misc import (
display_path,
hash_file,
hide_url,
is_installable_dir,
)
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.utils.unpacking import unpack_file
from pip._internal.vcs import vcs
@ -489,10 +499,26 @@ class RequirementPreparer:
hashes.check_against_path(file_path)
local_file = File(file_path, content_type=None)
# If download_info is set, we got it from the wheel cache.
if req.download_info is None:
# Editables don't go through this function (see
# prepare_editable_requirement).
assert not req.editable
req.download_info = direct_url_from_link(link, req.source_dir)
# For use in later processing,
# preserve the file path on the requirement.
if local_file:
req.local_file_path = local_file.path
# Make sure we have a hash in download_info. If we got it as part of the
# URL, it will have been verified and we can rely on it. Otherwise we
# compute it from the downloaded file.
if (
isinstance(req.download_info.info, ArchiveInfo)
and not req.download_info.info.hash
):
hash = hash_file(local_file.path)[0].hexdigest()
req.download_info.info.hash = f"sha256={hash}"
dist = _get_prepared_distribution(
req,
@ -547,6 +573,8 @@ class RequirementPreparer:
)
req.ensure_has_source_dir(self.src_dir)
req.update_editable()
assert req.source_dir
req.download_info = direct_url_for_editable(req.unpacked_source_directory)
dist = _get_prepared_distribution(
req,

View file

@ -26,6 +26,7 @@ from pip._internal.metadata import (
get_default_environment,
get_directory_distribution,
)
from pip._internal.models.direct_url import DirectUrl
from pip._internal.models.link import Link
from pip._internal.operations.build.metadata import generate_metadata
from pip._internal.operations.build.metadata_editable import generate_editable_metadata
@ -112,6 +113,10 @@ class InstallRequirement:
self.link = self.original_link = link
self.original_link_is_in_wheel_cache = False
# Information about the location of the artifact that was downloaded . This
# property is guaranteed to be set in resolver results.
self.download_info: Optional[DirectUrl] = None
# Path to any downloaded or already-existing package.
self.local_file_path: Optional[str] = None
if self.link and self.link.is_file:
@ -762,6 +767,7 @@ class InstallRequirement:
if self.is_wheel:
assert self.local_file_path
direct_url = None
# TODO this can be refactored to direct_url = self.download_info
if self.editable:
direct_url = direct_url_for_editable(self.unpacked_source_directory)
elif self.original_link:

View file

@ -22,6 +22,7 @@ from pip._internal.exceptions import (
)
from pip._internal.index.package_finder import PackageFinder
from pip._internal.metadata import select_backend
from pip._internal.models.direct_url import ArchiveInfo, DirInfo, VcsInfo
from pip._internal.network.session import PipSession
from pip._internal.operations.build.build_tracker import get_build_tracker
from pip._internal.operations.prepare import RequirementPreparer
@ -342,6 +343,115 @@ class TestRequirementSet:
)
)
def test_download_info_find_links(self, data: TestData) -> None:
"""Test that download_info is set for requirements via find_links."""
finder = make_test_finder(find_links=[data.find_links])
with self._basic_resolver(finder) as resolver:
ireq = get_processed_req_from_line("simple")
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert isinstance(req.download_info.info, ArchiveInfo)
assert req.download_info.info.hash
@pytest.mark.network
def test_download_info_index_url(self) -> None:
"""Test that download_info is set for requirements via index."""
finder = make_test_finder(index_urls=["https://pypi.org/simple"])
with self._basic_resolver(finder) as resolver:
ireq = get_processed_req_from_line("initools")
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert isinstance(req.download_info.info, ArchiveInfo)
assert req.download_info.info.hash
@pytest.mark.network
def test_download_info_web_archive(self) -> None:
"""Test that download_info is set for requirements from a web archive."""
finder = make_test_finder()
with self._basic_resolver(finder) as resolver:
ireq = get_processed_req_from_line(
"pip-test-package @ "
"https://github.com/pypa/pip-test-package/tarball/0.1.1"
)
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert (
req.download_info.url
== "https://github.com/pypa/pip-test-package/tarball/0.1.1"
)
assert isinstance(req.download_info.info, ArchiveInfo)
assert (
req.download_info.info.hash == "sha256="
"ad977496000576e1b6c41f6449a9897087ce9da6db4f15b603fe8372af4bf3c6"
)
def test_download_info_local_wheel(self, data: TestData) -> None:
"""Test that download_info is set for requirements from a local wheel."""
finder = make_test_finder()
with self._basic_resolver(finder) as resolver:
ireq = get_processed_req_from_line(
f"{data.packages}/simplewheel-1.0-py2.py3-none-any.whl"
)
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert req.download_info.url.startswith("file://")
assert isinstance(req.download_info.info, ArchiveInfo)
assert (
req.download_info.info.hash == "sha256="
"e63aa139caee941ec7f33f057a5b987708c2128238357cf905429846a2008718"
)
def test_download_info_local_dir(self, data: TestData) -> None:
"""Test that download_info is set for requirements from a local dir."""
finder = make_test_finder()
with self._basic_resolver(finder) as resolver:
ireq_url = path_to_url(data.packages / "FSPkg")
ireq = get_processed_req_from_line(f"FSPkg @ {ireq_url}")
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert req.download_info.url.startswith("file://")
assert isinstance(req.download_info.info, DirInfo)
def test_download_info_local_editable_dir(self, data: TestData) -> None:
"""Test that download_info is set for requirements from a local editable dir."""
finder = make_test_finder()
with self._basic_resolver(finder) as resolver:
ireq_url = path_to_url(data.packages / "FSPkg")
ireq = get_processed_req_from_line(f"-e {ireq_url}#egg=FSPkg")
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert req.download_info.url.startswith("file://")
assert isinstance(req.download_info.info, DirInfo)
assert req.download_info.info.editable
@pytest.mark.network
def test_download_info_vcs(self) -> None:
"""Test that download_info is set for requirements from git."""
finder = make_test_finder()
with self._basic_resolver(finder) as resolver:
ireq = get_processed_req_from_line(
"pip-test-package @ git+https://github.com/pypa/pip-test-package"
)
reqset = resolver.resolve([ireq], True)
assert len(reqset.all_requirements) == 1
req = reqset.all_requirements[0]
assert req.download_info
assert isinstance(req.download_info.info, VcsInfo)
assert req.download_info.url == "https://github.com/pypa/pip-test-package"
assert req.download_info.info.vcs == "git"
class TestInstallRequirement:
def setup(self) -> None: