Skip to content

Commit

Permalink
utils.link: add PEP 658 (metadata) support
Browse files Browse the repository at this point in the history
  • Loading branch information
abn committed May 2, 2022
1 parent 16cb159 commit f20cd70
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 9 deletions.
33 changes: 33 additions & 0 deletions src/poetry/core/packages/utils/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def __init__(
url: str,
comes_from: Any | None = None,
requires_python: str | None = None,
metadata: str | None = None,
) -> None:
"""
Object representing a parsed link from https://pypi.python.org/simple/*
Expand All @@ -28,6 +29,11 @@ def __init__(
String containing the `Requires-Python` metadata field, specified
in PEP 345. This may be specified by a data-requires-python
attribute in the HTML link tag, as described in PEP 503.
metadata:
String of the syntax `<hashname>=<hashvalue>` representing the hash
of the Core Metadata file. This may be specified by a
data-dist-info-metadata attribute in the HTML link tag, as described
in PEP 658.
"""

# url can be a UNC windows share
Expand All @@ -37,6 +43,7 @@ def __init__(
self.url = url
self.comes_from = comes_from
self.requires_python = requires_python if requires_python else None
self._metadata = metadata

def __str__(self) -> str:
if self.requires_python:
Expand Down Expand Up @@ -136,6 +143,32 @@ def subdirectory_fragment(self) -> str | None:

_hash_re = re.compile(r"(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)")

@property
def has_metadata(self) -> bool:
return self._metadata is not None and (self.is_wheel or self.is_sdist)

@property
def metadata_url(self) -> str | None:
if self.has_metadata:
return f"{self.url_without_fragment.split('?', 1)[0]}.metadata"
return None

@property
def metadata_hash(self) -> str | None:
if self.has_metadata:
match = self._hash_re.search(self._metadata or "")
if match:
return match.group(2)
return None

@property
def metadata_hash_name(self) -> str | None:
if self.has_metadata:
match = self._hash_re.search(self._metadata or "")
if match:
return match.group(1)
return None

@property
def hash(self) -> str | None:
match = self._hash_re.search(self.url)
Expand Down
87 changes: 78 additions & 9 deletions tests/packages/utils/test_utils_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,89 @@

from hashlib import sha256

import pytest

from poetry.core.packages.utils.link import Link


def make_url(ext: str) -> Link:
checksum = sha256(str(uuid.uuid4()).encode())
def make_checksum() -> str:
return sha256(str(uuid.uuid4()).encode()).hexdigest()


@pytest.fixture()
def file_checksum() -> str:
return make_checksum()


@pytest.fixture()
def metadata_checksum() -> str:
return make_checksum()


def make_url(
ext: str, file_checksum: str | None = None, metadata_checksum: str | None = None
) -> Link:
file_checksum = file_checksum or make_checksum()
return Link(
"https://files.pythonhosted.org/packages/16/52/dead/"
f"demo-1.0.0.{ext}#sha256={checksum}"
f"demo-1.0.0.{ext}#sha256={file_checksum}",
metadata=f"sha256={metadata_checksum}" if metadata_checksum else None,
)


def test_package_link_is_checks() -> None:
assert make_url("egg").is_egg
assert make_url("tar.gz").is_sdist
assert make_url("zip").is_sdist
assert make_url("exe").is_wininst
assert make_url("cp36-cp36m-manylinux1_x86_64.whl").is_wheel
def test_package_link_hash(file_checksum: str) -> None:
link = make_url(ext="whl", file_checksum=file_checksum)
assert link.hash_name == "sha256"
assert link.hash == file_checksum
assert link.show_url == "demo-1.0.0.whl"

# this is legacy PEP 503, no metadata hash is present
assert not link.has_metadata
assert not link.metadata_url
assert not link.metadata_hash
assert not link.metadata_hash_name


@pytest.mark.parametrize(
("ext", "check"),
[
("whl", "wheel"),
("egg", "egg"),
("tar.gz", "sdist"),
("zip", "sdist"),
("cp36-cp36m-manylinux1_x86_64.whl", "wheel"),
],
)
def test_package_link_is_checks(ext: str, check: str) -> None:
link = make_url(ext=ext)
assert getattr(link, f"is_{check}")


@pytest.mark.parametrize(
("ext", "has_metadata"),
[("whl", True), ("egg", False), ("tar.gz", True), ("zip", True)],
)
def test_package_link_pep658(
ext: str, has_metadata: bool, metadata_checksum: str
) -> None:
link = make_url(ext=ext, metadata_checksum=metadata_checksum)

if has_metadata:
assert link.has_metadata
assert link.metadata_url == f"{link.url_without_fragment}.metadata"
assert link.metadata_hash == metadata_checksum
assert link.metadata_hash_name == "sha256"
else:
assert not link.has_metadata
assert not link.metadata_url
assert not link.metadata_hash
assert not link.metadata_hash_name


def test_package_link_pep658_no_default_metadata() -> None:
link = make_url(ext="whl")

assert not link.has_metadata
assert not link.metadata_url
assert not link.metadata_hash
assert not link.metadata_hash_name

0 comments on commit f20cd70

Please sign in to comment.