Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check wheel tags in pip check #11088

Merged
merged 4 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ 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
35 changes: 33 additions & 2 deletions src/pip/_internal/operations/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,29 @@
"""

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._internal.distributions import make_distribution_for_install_requirement
from pip._internal.metadata import get_default_environment
from pip._internal.metadata.base import DistributionVersion
from pip._internal.metadata.base import BaseDistribution, DistributionVersion
from pip._internal.req.req_install import InstallRequirement

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -113,6 +128,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 @@ -309,3 +313,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