Skip to content

Commit 4fc297f

Browse files
committed
Prefer compatible wheels over source distribution
1 parent d8c05c3 commit 4fc297f

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

src/poetry/repositories/http.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
import requests
1515

16+
from packaging.tags import Tag
17+
from packaging.tags import sys_tags
1618
from poetry.core.packages.dependency import Dependency
1719
from poetry.core.packages.utils.link import Link
1820
from poetry.core.semver.helpers import parse_constraint
@@ -111,7 +113,7 @@ def _get_info_from_urls(self, urls: dict[str, list[str]]) -> PackageInfo:
111113
universal_wheel = None
112114
universal_python2_wheel = None
113115
universal_python3_wheel = None
114-
platform_specific_wheels = []
116+
platform_specific_wheels = {}
115117
for wheel in wheels:
116118
link = Link(wheel)
117119
m = wheel_file_re.match(link.filename)
@@ -131,7 +133,12 @@ def _get_info_from_urls(self, urls: dict[str, list[str]]) -> PackageInfo:
131133
else:
132134
universal_python3_wheel = wheel
133135
else:
134-
platform_specific_wheels.append(wheel)
136+
pyvers = pyver.split(".")
137+
abis = abi.split(".")
138+
plats = plat.split(".")
139+
tags = (Tag(x, y, z) for x in pyvers for y in abis for z in plats)
140+
for tag in tags:
141+
platform_specific_wheels[tag] = wheel
135142

136143
if universal_wheel is not None:
137144
return self._get_info_from_wheel(universal_wheel)
@@ -195,9 +202,16 @@ def _get_info_from_urls(self, urls: dict[str, list[str]]) -> PackageInfo:
195202
if universal_python2_wheel:
196203
return self._get_info_from_wheel(universal_python2_wheel)
197204

205+
# Prefer compatible platform wheel over sdist
206+
system_tags = set(sys_tags())
207+
for tag, wheel in platform_specific_wheels.items():
208+
if tag in system_tags:
209+
return self._get_info_from_wheel(wheel)
210+
198211
if platform_specific_wheels and "sdist" not in urls:
199212
# Pick the first wheel available and hope for the best
200-
return self._get_info_from_wheel(platform_specific_wheels[0])
213+
first_wheel = next(iter(platform_specific_wheels.values()))
214+
return self._get_info_from_wheel(first_wheel)
201215

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

tests/repositories/test_legacy_repository.py

+42
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
import pytest
1111
import requests
1212

13+
from packaging.tags import Tag
1314
from packaging.utils import canonicalize_name
1415
from poetry.core.packages.dependency import Dependency
1516
from poetry.core.semver.version import Version
1617

1718
from poetry.factory import Factory
19+
from poetry.inspection.info import PackageInfo
1820
from poetry.repositories.exceptions import PackageNotFound
1921
from poetry.repositories.exceptions import RepositoryError
2022
from poetry.repositories.legacy_repository import LegacyRepository
@@ -30,6 +32,7 @@
3032
import httpretty
3133

3234
from _pytest.monkeypatch import MonkeyPatch
35+
from pytest_mock import MockerFixture
3336

3437
from poetry.config.config import Config
3538

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

248251

252+
@pytest.mark.parametrize(
253+
"tags,bdist",
254+
[
255+
(("cp37", "cp37m", "win32"), True),
256+
(("cp310", "cp310", "manylinux_2_7_x86_64"), False),
257+
],
258+
)
259+
def test_get_package_dependencies_with_sdist_and_bdist_platform_compatible(
260+
tags: tuple[str, str, str], bdist: bool, mocker: MockerFixture
261+
) -> None:
262+
get_info_from_wheel = mocker.patch(
263+
"poetry.repositories.legacy_repository.LegacyRepository._get_info_from_wheel"
264+
)
265+
get_info_from_sdist = mocker.patch(
266+
"poetry.repositories.legacy_repository.LegacyRepository._get_info_from_sdist"
267+
)
268+
name, version = "pyyaml", "3.13"
269+
get_info_from_wheel.return_value = PackageInfo(name=name, version=version)
270+
get_info_from_sdist.return_value = PackageInfo(name=name, version=version)
271+
272+
sys_tags = mocker.patch("poetry.repositories.http.sys_tags")
273+
sys_tags.return_value = [Tag(*tags)]
274+
275+
name, version = "pyyaml", "3.13"
276+
277+
repo = MockRepository()
278+
package = repo.package(name, Version.parse(version))
279+
280+
assert package.name == name
281+
assert package.version.text == version
282+
283+
if bdist:
284+
assert get_info_from_wheel.called
285+
assert not get_info_from_sdist.called
286+
else:
287+
assert not get_info_from_wheel.called
288+
assert get_info_from_sdist.called
289+
290+
249291
def test_get_package_information_chooses_correct_distribution() -> None:
250292
repo = MockRepository()
251293

0 commit comments

Comments
 (0)