Skip to content

Commit

Permalink
Prefer compatible wheels over source distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby committed Sep 17, 2022
1 parent d8c05c3 commit 4fc297f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/poetry/repositories/http.py
Expand Up @@ -13,6 +13,8 @@

import requests

from packaging.tags import Tag
from packaging.tags import sys_tags
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.utils.link import Link
from poetry.core.semver.helpers import parse_constraint
Expand Down Expand Up @@ -111,7 +113,7 @@ def _get_info_from_urls(self, urls: dict[str, list[str]]) -> PackageInfo:
universal_wheel = None
universal_python2_wheel = None
universal_python3_wheel = None
platform_specific_wheels = []
platform_specific_wheels = {}
for wheel in wheels:
link = Link(wheel)
m = wheel_file_re.match(link.filename)
Expand All @@ -131,7 +133,12 @@ def _get_info_from_urls(self, urls: dict[str, list[str]]) -> PackageInfo:
else:
universal_python3_wheel = wheel
else:
platform_specific_wheels.append(wheel)
pyvers = pyver.split(".")
abis = abi.split(".")
plats = plat.split(".")
tags = (Tag(x, y, z) for x in pyvers for y in abis for z in plats)
for tag in tags:
platform_specific_wheels[tag] = wheel

if universal_wheel is not None:
return self._get_info_from_wheel(universal_wheel)
Expand Down Expand Up @@ -195,9 +202,16 @@ def _get_info_from_urls(self, urls: dict[str, list[str]]) -> PackageInfo:
if universal_python2_wheel:
return self._get_info_from_wheel(universal_python2_wheel)

# Prefer compatible platform wheel over sdist
system_tags = set(sys_tags())
for tag, wheel in platform_specific_wheels.items():
if tag in system_tags:
return self._get_info_from_wheel(wheel)

if platform_specific_wheels and "sdist" not in urls:
# Pick the first wheel available and hope for the best
return self._get_info_from_wheel(platform_specific_wheels[0])
first_wheel = next(iter(platform_specific_wheels.values()))
return self._get_info_from_wheel(first_wheel)

return self._get_info_from_sdist(urls["sdist"][0])

Expand Down
42 changes: 42 additions & 0 deletions tests/repositories/test_legacy_repository.py
Expand Up @@ -10,11 +10,13 @@
import pytest
import requests

from packaging.tags import Tag
from packaging.utils import canonicalize_name
from poetry.core.packages.dependency import Dependency
from poetry.core.semver.version import Version

from poetry.factory import Factory
from poetry.inspection.info import PackageInfo
from poetry.repositories.exceptions import PackageNotFound
from poetry.repositories.exceptions import RepositoryError
from poetry.repositories.legacy_repository import LegacyRepository
Expand All @@ -30,6 +32,7 @@
import httpretty

from _pytest.monkeypatch import MonkeyPatch
from pytest_mock import MockerFixture

from poetry.config.config import Config

Expand Down Expand Up @@ -246,6 +249,45 @@ def test_find_packages_yanked(constraint: str, expected: list[str]) -> None:
assert [str(p.version) for p in packages] == expected


@pytest.mark.parametrize(
"tags,bdist",
[
(("cp37", "cp37m", "win32"), True),
(("cp310", "cp310", "manylinux_2_7_x86_64"), False),
],
)
def test_get_package_dependencies_with_sdist_and_bdist_platform_compatible(
tags: tuple[str, str, str], bdist: bool, mocker: MockerFixture
) -> None:
get_info_from_wheel = mocker.patch(
"poetry.repositories.legacy_repository.LegacyRepository._get_info_from_wheel"
)
get_info_from_sdist = mocker.patch(
"poetry.repositories.legacy_repository.LegacyRepository._get_info_from_sdist"
)
name, version = "pyyaml", "3.13"
get_info_from_wheel.return_value = PackageInfo(name=name, version=version)
get_info_from_sdist.return_value = PackageInfo(name=name, version=version)

sys_tags = mocker.patch("poetry.repositories.http.sys_tags")
sys_tags.return_value = [Tag(*tags)]

name, version = "pyyaml", "3.13"

repo = MockRepository()
package = repo.package(name, Version.parse(version))

assert package.name == name
assert package.version.text == version

if bdist:
assert get_info_from_wheel.called
assert not get_info_from_sdist.called
else:
assert not get_info_from_wheel.called
assert get_info_from_sdist.called


def test_get_package_information_chooses_correct_distribution() -> None:
repo = MockRepository()

Expand Down

0 comments on commit 4fc297f

Please sign in to comment.