Commit cce1abc6 by Randy Döring

repositories/link_sources: support for yanked files according to PEP 592

parent 7fa563f0
......@@ -113,3 +113,17 @@ class LinkSource:
the link, it will be rewritten to %20 (while not over-quoting
% or other characters)."""
return self.CLEAN_REGEX.sub(lambda match: f"%{ord(match.group(0)):02x}", url)
def yanked(self, name: NormalizedName, version: Version) -> str | bool:
reasons = set()
for link in self.links_for_version(name, version):
if link.yanked:
if link.yanked_reason:
reasons.add(link.yanked_reason)
else:
# release is not yanked if at least one file is not yanked
return False
# if all files are yanked (or there are no files) the release is yanked
if reasons:
return "\n".join(sorted(reasons))
return True
......@@ -33,7 +33,13 @@ class HTMLPage(LinkSource):
url = self.clean_link(urllib.parse.urljoin(self._url, href))
pyrequire = anchor.get("data-requires-python")
pyrequire = unescape(pyrequire) if pyrequire else None
link = Link(url, requires_python=pyrequire)
yanked_value = anchor.get("data-yanked")
yanked: str | bool
if yanked_value:
yanked = unescape(yanked_value)
else:
yanked = "data-yanked" in anchor.attrib
link = Link(url, requires_python=pyrequire, yanked=yanked)
if link.ext not in self.SUPPORTED_FORMATS:
continue
......
......@@ -5,6 +5,7 @@ from unittest.mock import PropertyMock
import pytest
from packaging.utils import canonicalize_name
from poetry.core.packages.package import Package
from poetry.core.packages.utils.link import Link
from poetry.core.semver.version import Version
......@@ -87,4 +88,7 @@ def test_links_for_version(
) -> None:
version = Version.parse(version_string)
expected = {Link(f"{link_source.url}/{name}") for name in filenames}
assert set(link_source.links_for_version("demo", version)) == expected
assert (
set(link_source.links_for_version(canonicalize_name("demo"), version))
== expected
)
from __future__ import annotations
import pytest
from poetry.core.packages.utils.link import Link
from poetry.core.semver.version import Version
from poetry.repositories.link_sources.html import HTMLPage
DEMO_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<meta name="pypi:repository-version" content="1.0">
<title>Links for demo</title>
</head>
<body>
<h1>Links for demo</h1>
{}
</body>
</html>
"""
@pytest.mark.parametrize(
"attributes, expected_link",
[
("", Link("https://example.org/demo-0.1.whl")),
(
'data-requires-python="&gt;=3.7"',
Link("https://example.org/demo-0.1.whl", requires_python=">=3.7"),
),
(
"data-yanked",
Link("https://example.org/demo-0.1.whl", yanked=True),
),
(
'data-yanked=""',
Link("https://example.org/demo-0.1.whl", yanked=True),
),
(
'data-yanked="&lt;reason&gt;"',
Link("https://example.org/demo-0.1.whl", yanked="<reason>"),
),
(
'data-requires-python="&gt;=3.7" data-yanked',
Link(
"https://example.org/demo-0.1.whl", requires_python=">=3.7", yanked=True
),
),
],
)
def test_link_attributes(attributes: str, expected_link: Link) -> None:
anchor = (
f'<a href="https://example.org/demo-0.1.whl" {attributes}>demo-0.1.whl</a><br/>'
)
content = DEMO_TEMPLATE.format(anchor)
page = HTMLPage("https://example.org", content)
assert len(list(page.links)) == 1
link = list(page.links)[0]
assert link.url == expected_link.url
assert link.requires_python == expected_link.requires_python
assert link.yanked == expected_link.yanked
assert link.yanked_reason == expected_link.yanked_reason
@pytest.mark.parametrize(
"yanked_attrs, expected",
[
(("", ""), False),
(("data-yanked", ""), False),
(("", "data-yanked"), False),
(("data-yanked", "data-yanked"), True),
(("data-yanked='reason'", "data-yanked"), "reason"),
(("data-yanked", "data-yanked='reason'"), "reason"),
(("data-yanked='reason'", "data-yanked=''"), "reason"),
(("data-yanked=''", "data-yanked='reason'"), "reason"),
(("data-yanked='reason'", "data-yanked='reason'"), "reason"),
(("data-yanked='reason 1'", "data-yanked='reason 2'"), "reason 1\nreason 2"),
],
)
def test_yanked(yanked_attrs: tuple[str, str], expected: bool | str) -> None:
anchors = (
f'<a href="https://example.org/demo-0.1.tar.gz" {yanked_attrs[0]}>'
"demo-0.1.tar.gz</a>"
f'<a href="https://example.org/demo-0.1.whl" {yanked_attrs[1]}>demo-0.1.whl</a>'
)
content = DEMO_TEMPLATE.format(anchors)
page = HTMLPage("https://example.org", content)
assert page.yanked("demo", Version.parse("0.1")) == expected
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment