diff --git a/src/poetry/installation/executor.py b/src/poetry/installation/executor.py index 6ba544eb40d..a4ca1238cee 100644 --- a/src/poetry/installation/executor.py +++ b/src/poetry/installation/executor.py @@ -572,6 +572,8 @@ def _prepare_archive(self, operation: Install | Update) -> Path: if not Path(package.source_url).is_absolute() and package.root_dir: archive = package.root_dir / archive + self._populate_hashes_dict(archive, package) + return self._chef.prepare(archive, editable=package.develop) def _prepare_directory_archive(self, operation: Install | Update) -> Path: @@ -734,13 +736,15 @@ def _download_link(self, operation: Install | Update, link: Link) -> Path: archive = self._chef.prepare(archive, output_dir=output_dir) + self._populate_hashes_dict(archive, package) + + return archive + + def _populate_hashes_dict(self, archive: Path, package: Package) -> None: if package.files and archive.name in {f["file"] for f in package.files}: archive_hash = self._validate_archive_hash(archive, package) - self._hashes[package.name] = archive_hash - return archive - @staticmethod def _validate_archive_hash(archive: Path, package: Package) -> str: archive_hash: str = "sha256:" + get_file_hash(archive) @@ -874,20 +878,12 @@ def _create_git_url_reference(self, package: Package) -> dict[str, Any]: return reference def _create_url_url_reference(self, package: Package) -> dict[str, Any]: - archive_info = {} - - if package.name in self._hashes: - archive_info["hash"] = self._hashes[package.name] - - reference = {"url": package.source_url, "archive_info": archive_info} + archive_info = self._get_archive_info(package) - return reference + return {"url": package.source_url, "archive_info": archive_info} def _create_file_url_reference(self, package: Package) -> dict[str, Any]: - archive_info = {} - - if package.name in self._hashes: - archive_info["hash"] = self._hashes[package.name] + archive_info = self._get_archive_info(package) assert package.source_url is not None return { @@ -906,3 +902,20 @@ def _create_directory_url_reference(self, package: Package) -> dict[str, Any]: "url": Path(package.source_url).as_uri(), "dir_info": dir_info, } + + def _get_archive_info(self, package: Package) -> dict[str, Any]: + """ + Create dictionary `archive_info` for file `direct_url.json`. + + Specification: https://packaging.python.org/en/latest/specifications/direct-url + (it supersedes PEP 610) + + :param package: This must be a poetry package instance. + """ + archive_info = {} + + if package.name in self._hashes: + algorithm, value = self._hashes[package.name].split(":") + archive_info["hashes"] = {algorithm: value} + + return archive_info diff --git a/tests/installation/test_executor.py b/tests/installation/test_executor.py index c6277182f32..9ede4a63c5f 100644 --- a/tests/installation/test_executor.py +++ b/tests/installation/test_executor.py @@ -622,12 +622,27 @@ def test_executor_should_write_pep610_url_references_for_files( .resolve() ) package = Package("demo", "0.1.0", source_type="file", source_url=url.as_posix()) + # Set package.files so the executor will attempt to hash the package + package.files = [ + { + "file": "demo-0.1.0-py2.py3-none-any.whl", + "hash": "sha256:70e704135718fffbcbf61ed1fc45933cfd86951a744b681000eaaa75da31f17a", # noqa: E501 + } + ] executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) - verify_installed_distribution( - tmp_venv, package, {"archive_info": {}, "url": url.as_uri()} - ) + expected_url_reference = { + "archive_info": { + "hashes": { + "sha256": ( + "70e704135718fffbcbf61ed1fc45933cfd86951a744b681000eaaa75da31f17a" + ) + }, + }, + "url": url.as_uri(), + } + verify_installed_distribution(tmp_venv, package, expected_url_reference) def test_executor_should_write_pep610_url_references_for_directories( @@ -701,12 +716,27 @@ def test_executor_should_write_pep610_url_references_for_urls( source_type="url", source_url="https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl", ) + # Set package.files so the executor will attempt to hash the package + package.files = [ + { + "file": "demo-0.1.0-py2.py3-none-any.whl", + "hash": "sha256:70e704135718fffbcbf61ed1fc45933cfd86951a744b681000eaaa75da31f17a", # noqa: E501 + } + ] executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) - verify_installed_distribution( - tmp_venv, package, {"archive_info": {}, "url": package.source_url} - ) + expected_url_reference = { + "archive_info": { + "hashes": { + "sha256": ( + "70e704135718fffbcbf61ed1fc45933cfd86951a744b681000eaaa75da31f17a" + ) + }, + }, + "url": package.source_url, + } + verify_installed_distribution(tmp_venv, package, expected_url_reference) def test_executor_should_write_pep610_url_references_for_git(