Skip to content

Commit

Permalink
installer: write spec-compliant direct_url.json for file and url depe…
Browse files Browse the repository at this point in the history
…ndencies (#7475)

drop deprecated `hash` in favor of `hashes`
* https://packaging.python.org/en/latest/specifications/direct-url/ supersedes PEP 610
* keeping `hash` for compatibility probably does not make sense since it was not spec-compliant (":" instead of "=" as separator between algorithm and value)
  • Loading branch information
chopeen authored Feb 7, 2023
1 parent 58fe8f2 commit 3ed0133
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 20 deletions.
41 changes: 27 additions & 14 deletions src/poetry/installation/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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
42 changes: 36 additions & 6 deletions tests/installation/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 3ed0133

Please sign in to comment.