Skip to content

Commit

Permalink
Check wheel tags in pip check (pypa#11088)
Browse files Browse the repository at this point in the history
  • Loading branch information
q0w authored Jul 14, 2024
1 parent c2d706f commit db062e8
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 4 deletions.
1 change: 1 addition & 0 deletions news/11054.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Check unsupported packages for the current platform.
18 changes: 16 additions & 2 deletions src/pip/_internal/commands/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

from pip._internal.cli.base_command import Command
from pip._internal.cli.status_codes import ERROR, SUCCESS
from pip._internal.metadata import get_default_environment
from pip._internal.operations.check import (
check_package_set,
check_unsupported,
create_package_set_from_installed,
)
from pip._internal.utils.compatibility_tags import get_supported
from pip._internal.utils.misc import write_output

logger = logging.getLogger(__name__)
Expand All @@ -23,6 +26,12 @@ class CheckCommand(Command):
def run(self, options: Values, args: List[str]) -> int:
package_set, parsing_probs = create_package_set_from_installed()
missing, conflicting = check_package_set(package_set)
unsupported = list(
check_unsupported(
get_default_environment().iter_installed_distributions(),
get_supported(),
)
)

for project_name in missing:
version = package_set[project_name].version
Expand All @@ -45,8 +54,13 @@ def run(self, options: Values, args: List[str]) -> int:
dep_name,
dep_version,
)

if missing or conflicting or parsing_probs:
for package in unsupported:
write_output(
"%s %s is not supported on this platform",
package.raw_name,
package.version,
)
if missing or conflicting or parsing_probs or unsupported:
return ERROR
else:
write_output("No broken requirements found.")
Expand Down
34 changes: 33 additions & 1 deletion src/pip/_internal/operations/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,30 @@
"""

import logging
from typing import Callable, Dict, List, NamedTuple, Optional, Set, Tuple
from contextlib import suppress
from email.parser import Parser
from functools import reduce
from typing import (
Callable,
Dict,
FrozenSet,
Generator,
Iterable,
List,
NamedTuple,
Optional,
Set,
Tuple,
)

from pip._vendor.packaging.requirements import Requirement
from pip._vendor.packaging.tags import Tag, parse_tag
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
from pip._vendor.packaging.version import Version

from pip._internal.distributions import make_distribution_for_install_requirement
from pip._internal.metadata import get_default_environment
from pip._internal.metadata.base import BaseDistribution
from pip._internal.req.req_install import InstallRequirement

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -113,6 +129,22 @@ def check_install_conflicts(to_install: List[InstallRequirement]) -> ConflictDet
)


def check_unsupported(
packages: Iterable[BaseDistribution],
supported_tags: Iterable[Tag],
) -> Generator[BaseDistribution, None, None]:
for p in packages:
with suppress(FileNotFoundError):
wheel_file = p.read_text("WHEEL")
wheel_tags: FrozenSet[Tag] = reduce(
frozenset.union,
map(parse_tag, Parser().parsestr(wheel_file).get_all("Tag", [])),
frozenset(),
)
if wheel_tags.isdisjoint(supported_tags):
yield p


def _simulate_installation_of(
to_install: List[InstallRequirement], package_set: PackageSet
) -> Set[NormalizedName]:
Expand Down
29 changes: 28 additions & 1 deletion tests/functional/test_check.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from typing import Collection

from tests.lib import PipTestEnvironment, create_test_package_with_setup
from tests.lib import (
PipTestEnvironment,
create_really_basic_wheel,
create_test_package_with_setup,
)


def matches_expected_lines(string: str, expected_lines: Collection[str]) -> bool:
Expand Down Expand Up @@ -321,3 +325,26 @@ def test_check_include_work_dir_pkg(script: PipTestEnvironment) -> None:
expected_lines = ("simple 1.0 requires missing, which is not installed.",)
assert matches_expected_lines(result.stdout, expected_lines)
assert result.returncode == 1


def test_check_unsupported(
script: PipTestEnvironment,
) -> None:
script.scratch_path.joinpath("base-0.1.0-py2.py3-none-any.whl").write_bytes(
create_really_basic_wheel("base", "0.1.0")
)
script.pip(
"install",
"--no-cache-dir",
"--no-index",
"--find-links",
script.scratch_path,
"base==0.1.0",
)
with open(
script.site_packages_path.joinpath("base-0.1.0.dist-info/WHEEL"), "a"
) as f:
f.write("\nTag: cp310-cp310-musllinux_1_1_x86_64\n")
result = script.pip("check", expect_error=True)
assert "base 0.1.0 is not supported on this platform" in result.stdout
assert result.returncode == 1

0 comments on commit db062e8

Please sign in to comment.