diff --git a/news/13618.bugfix.rst b/news/13618.bugfix.rst new file mode 100644 index 0000000000..6e3d6cae78 --- /dev/null +++ b/news/13618.bugfix.rst @@ -0,0 +1,2 @@ +When installing packages, pip will no longer show a misleading +error message that included extra markers such as ``; extra == "..."``. diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 6c45d12fd0..2fc6b89fa6 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -1014,16 +1014,19 @@ def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str: ) if allows_pre is False: version_type = "final version" - + # pip sometimes includes environment markers like `;extra == "foo"` + # in requirement strings, which is confusing in error messages. + # Strip them so the user sees only the actual missing requirement. + req_disp = re.sub(r';\s*extra\s*==\s*".*?"', "", str(req)).strip() logger.critical( "Could not find a %s that satisfies the requirement %s " "(from versions: %s)", version_type, - req, + req_disp, _format_versions(best_candidate_result.all_candidates), ) - raise DistributionNotFound(f"No matching distribution found for {req}") + raise DistributionNotFound(f"No matching distribution found for {req_disp}") def _should_install_candidate( candidate: InstallationCandidate | None, diff --git a/src/pip/_internal/resolution/resolvelib/factory.py b/src/pip/_internal/resolution/resolvelib/factory.py index 75a64e7cd0..3800b7090e 100644 --- a/src/pip/_internal/resolution/resolvelib/factory.py +++ b/src/pip/_internal/resolution/resolvelib/factory.py @@ -4,6 +4,7 @@ import copy import functools import logging +import re from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence from typing import ( TYPE_CHECKING, @@ -724,7 +725,7 @@ def _report_single_requirement_conflict( req_disp = str(req) else: req_disp = f"{req} (from {parent.name})" - + req_disp = re.sub(r';\s*extra\s*==\s*".*?"', "", req_disp).strip() cands = self._finder.find_all_candidates(req.project_name) skipped_by_requires_python = self._finder.requires_python_skipped_reasons() @@ -776,8 +777,7 @@ def _report_single_requirement_conflict( "using the '-r' flag to install the packages listed in " "requirements.txt" ) - - return DistributionNotFound(f"No matching distribution found for {req}") + return DistributionNotFound(f"No matching distribution found for {req_disp}") def _has_any_candidates(self, project_name: str) -> bool: """ diff --git a/tests/functional/test_install_extras.py b/tests/functional/test_install_extras.py index 19e5b28c26..ae6d4afcd9 100644 --- a/tests/functional/test_install_extras.py +++ b/tests/functional/test_install_extras.py @@ -189,6 +189,10 @@ def test_install_special_extra( assert ( "Could not find a version that satisfies the requirement missing_pkg" ) in result.stderr, str(result) + assert "No matching distribution found for missing_pkg" in result.stderr, str( + result + ) + assert "extra ==" not in result.stderr, str(result) @pytest.mark.network