diff --git a/src/poetry/installation/chooser.py b/src/poetry/installation/chooser.py
index 424aaefe7bb..cdf2b87884d 100644
--- a/src/poetry/installation/chooser.py
+++ b/src/poetry/installation/chooser.py
@@ -6,6 +6,7 @@
from packaging.tags import Tag
+from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils.patterns import wheel_file_re
@@ -103,6 +104,15 @@ def _get_links(self, package: Package) -> list[Link]:
selected_links.append(link)
continue
+ if (
+ link.hash_name
+ and not link.hash_name.startswith("sha")
+ and isinstance(repository, PyPiRepository)
+ and repository.get_sha_hash_from_link(link) in hashes
+ ):
+ selected_links.append(link)
+ continue
+
h = link.hash_name + ":" + link.hash
if h not in hashes:
continue
diff --git a/src/poetry/installation/executor.py b/src/poetry/installation/executor.py
index 43ebfe51f69..00d9deddb48 100644
--- a/src/poetry/installation/executor.py
+++ b/src/poetry/installation/executor.py
@@ -655,16 +655,28 @@ def _validate_archive_hash(archive: Path | Link, package: Package) -> str:
package.name,
archive_path,
)
- archive_hash = "sha256:" + file_dep.hash()
known_hashes = {f["hash"] for f in package.files}
+ known_types = (h.split(":")[0] for h in known_hashes)
- if archive_hash not in known_hashes:
+ archive_hashes = set()
+ for hash_type in known_types:
+ archive_hashes.add(f"{hash_type}:{file_dep.hash(hash_type)}")
+
+ if archive_hashes.isdisjoint(known_hashes):
raise RuntimeError(
- f"Hash for {package} from archive {archive_path.name} not found in"
- f" known hashes (was: {archive_hash})"
+ f"Invalid hashes ({', '.join(sorted(archive_hashes))}) for"
+ f" {package} using archive {archive.name}. "
+ f"Expected one of {', '.join(sorted(known_hashes))}."
)
- return archive_hash
+ try:
+ _, sha256 = next(
+ filter(lambda h: h.startswith("sha256:"), archive_hashes)
+ ).split(":")
+ except StopIteration:
+ sha256 = file_dep.hash("sha256")
+
+ return f"sha256={sha256}"
def _download_archive(self, operation: Install | Update, link: Link) -> Path:
response = self._authenticator.request(
diff --git a/src/poetry/repositories/legacy_repository.py b/src/poetry/repositories/legacy_repository.py
index 5a48fa4b585..12923b8501a 100644
--- a/src/poetry/repositories/legacy_repository.py
+++ b/src/poetry/repositories/legacy_repository.py
@@ -1,14 +1,12 @@
from __future__ import annotations
import cgi
-import hashlib
import re
import urllib.parse
import warnings
from collections import defaultdict
from html import unescape
-from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Iterator
@@ -35,12 +33,12 @@
from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils.authenticator import Authenticator
from poetry.utils.helpers import canonicalize_name
-from poetry.utils.helpers import download_file
-from poetry.utils.helpers import temporary_directory
from poetry.utils.patterns import wheel_file_re
if TYPE_CHECKING:
+ from pathlib import Path
+
from poetry.core.packages.dependency import Dependency
with warnings.catch_warnings():
@@ -354,35 +352,9 @@ def _get_release_info(self, name: str, version: str) -> dict:
):
urls["sdist"].append(link.url)
- file_hash = f"{link.hash_name}:{link.hash}" if link.hash else None
-
- if not link.hash or (
- link.hash_name not in ("sha256", "sha384", "sha512")
- and hasattr(hashlib, link.hash_name)
- ):
- with temporary_directory() as temp_dir:
- filepath = Path(temp_dir) / link.filename
- self._download(link.url, str(filepath))
-
- known_hash = (
- getattr(hashlib, link.hash_name)() if link.hash_name else None
- )
- required_hash = hashlib.sha256()
-
- chunksize = 4096
- with filepath.open("rb") as f:
- while True:
- chunk = f.read(chunksize)
- if not chunk:
- break
- if known_hash:
- known_hash.update(chunk)
- required_hash.update(chunk)
-
- if not known_hash or known_hash.hexdigest() == link.hash:
- file_hash = f"{required_hash.name}:{required_hash.hexdigest()}"
-
- files.append({"file": link.filename, "hash": file_hash})
+ files.append(
+ {"file": link.filename, "hash": self.get_sha_hash_from_link(link)}
+ )
data.files = files
@@ -417,6 +389,3 @@ def _get_page(self, endpoint: str) -> Page | None:
)
return Page(response.url, response.content, response.headers)
-
- def _download(self, url: str, dest: str) -> None:
- return download_file(url, dest, session=self.session)
diff --git a/src/poetry/repositories/pypi_repository.py b/src/poetry/repositories/pypi_repository.py
index 467a5a9c8cb..a60e129c6bb 100644
--- a/src/poetry/repositories/pypi_repository.py
+++ b/src/poetry/repositories/pypi_repository.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import hashlib
import logging
import os
import urllib.parse
@@ -453,3 +454,40 @@ def _download(self, url: str, dest: str) -> None:
def _log(self, msg: str, level: str = "info") -> None:
getattr(logger, level)(f"