Skip to content

Commit

Permalink
link_sources: fix parsing of non-wheel non-sdist links
Browse files Browse the repository at this point in the history
  • Loading branch information
radoering authored and abn committed May 6, 2022
1 parent cd3026f commit 0d418fc
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 14 deletions.
34 changes: 20 additions & 14 deletions src/poetry/repositories/link_sources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def versions(self, name: str) -> Iterator[Version]:
for link in self.links:
pkg = self.link_package_data(link)

if pkg and pkg.name == name and pkg.version and pkg.version not in seen:
if pkg and pkg.name == name and pkg.version not in seen:
seen.add(pkg.version)
yield pkg.version

Expand All @@ -58,44 +58,50 @@ def packages(self) -> Iterator[Package]:
for link in self.links:
pkg = self.link_package_data(link)

if pkg and pkg.name and pkg.version:
if pkg:
yield pkg

@property
@abstractmethod
def links(self) -> Iterator[Link]:
raise NotImplementedError()

def link_package_data(self, link: Link) -> Package | None:
name, version = None, None
@classmethod
def link_package_data(cls, link: Link) -> Package | None:
name, version_string, version = None, None, None
m = wheel_file_re.match(link.filename) or sdist_file_re.match(link.filename)

if m:
name = canonicalize_name(m.group("name"))
version_string = m.group("ver")
else:
info, ext = link.splitext()
match = self.VERSION_REGEX.match(info)
match = cls.VERSION_REGEX.match(info)
if match:
name = match.group(1)
version_string = match.group(2)

try:
version = Version.parse(version_string)
except ValueError:
logger.debug(
"Skipping url (%s) due to invalid version (%s)", link.url, version
)
return None
if version_string:
try:
version = Version.parse(version_string)
except ValueError:
logger.debug(
"Skipping url (%s) due to invalid version (%s)", link.url, version
)
return None

return Package(name, version, source_url=link.url)
pkg = None
if name and version:
pkg = Package(name, version, source_url=link.url)
return pkg

def links_for_version(self, name: str, version: Version) -> Iterator[Link]:
name = canonicalize_name(name)

for link in self.links:
pkg = self.link_package_data(link)

if pkg and pkg.name == name and pkg.version and pkg.version == version:
if pkg and pkg.name == name and pkg.version == version:
yield link

def clean_link(self, url: str) -> str:
Expand Down
Empty file.
89 changes: 89 additions & 0 deletions tests/repositories/link_sources/test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from typing import Iterable
from unittest.mock import PropertyMock

import pytest

from poetry.core.packages.package import Package
from poetry.core.packages.utils.link import Link
from poetry.core.semver.version import Version

from poetry.repositories.link_sources.base import LinkSource


if TYPE_CHECKING:
from pytest_mock import MockerFixture


@pytest.fixture
def link_source(mocker: MockerFixture) -> LinkSource:
url = "https://example.org"
link_source = LinkSource(url)
mocker.patch(
f"{LinkSource.__module__}.{LinkSource.__qualname__}.links",
new_callable=PropertyMock,
return_value=iter(
[
Link(f"{url}/demo-0.1.0.tar.gz"),
Link(f"{url}/demo-0.1.0_invalid.tar.gz"),
Link(f"{url}/invalid.tar.gz"),
Link(f"{url}/demo-0.1.0-py2.py3-none-any.whl"),
Link(f"{url}/demo-0.1.1.tar.gz"),
]
),
)
return link_source


@pytest.mark.parametrize(
"filename, expected",
[
("demo-0.1.0-py2.py3-none-any.whl", Package("demo", "0.1.0")),
("demo-0.1.0.tar.gz", Package("demo", "0.1.0")),
("demo-0.1.0.egg", Package("demo", "0.1.0")),
("demo-0.1.0_invalid-py2.py3-none-any.whl", None), # invalid version
("demo-0.1.0_invalid.egg", None), # invalid version
("no-package-at-all.txt", None),
],
)
def test_link_package_data(filename: str, expected: Package | None) -> None:
link = Link(f"https://example.org/{filename}")
assert LinkSource.link_package_data(link) == expected


@pytest.mark.parametrize(
"name, expected",
[
("demo", {Version.parse("0.1.0"), Version.parse("0.1.1")}),
("invalid", set()),
],
)
def test_versions(name: str, expected: set[Version], link_source: LinkSource) -> None:
assert set(link_source.versions(name)) == expected


def test_packages(link_source: LinkSource) -> None:
expected = {
Package("demo", "0.1.0"),
Package("demo", "0.1.0"),
Package("demo", "0.1.1"),
}
assert set(link_source.packages) == expected


@pytest.mark.parametrize(
"version_string, filenames",
[
("0.1.0", ["demo-0.1.0.tar.gz", "demo-0.1.0-py2.py3-none-any.whl"]),
("0.1.1", ["demo-0.1.1.tar.gz"]),
("0.1.2", []),
],
)
def test_links_for_version(
version_string: str, filenames: Iterable[str], link_source: LinkSource
) -> 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

0 comments on commit 0d418fc

Please sign in to comment.