diff --git a/news/12225.bugfix.rst b/news/12225.bugfix.rst new file mode 100644 index 000000000..e1e0c323d --- /dev/null +++ b/news/12225.bugfix.rst @@ -0,0 +1 @@ +Filter out yanked links from the available versions error message: "(from versions: 1.0, 2.0, 3.0)" will not contain yanked versions conform PEP 592. The yanked versions (if any) will be mentioned in a separate error message. diff --git a/src/pip/_internal/resolution/resolvelib/factory.py b/src/pip/_internal/resolution/resolvelib/factory.py index ed78580ab..2eb80d4d5 100644 --- a/src/pip/_internal/resolution/resolvelib/factory.py +++ b/src/pip/_internal/resolution/resolvelib/factory.py @@ -603,8 +603,26 @@ class Factory: cands = self._finder.find_all_candidates(req.project_name) skipped_by_requires_python = self._finder.requires_python_skipped_reasons() - versions = [str(v) for v in sorted({c.version for c in cands})] + versions_set: Set[CandidateVersion] = set() + yanked_versions_set: Set[CandidateVersion] = set() + for c in cands: + is_yanked = c.link.is_yanked if c.link else False + if is_yanked: + yanked_versions_set.add(c.version) + else: + versions_set.add(c.version) + + versions = [str(v) for v in sorted(versions_set)] + yanked_versions = [str(v) for v in sorted(yanked_versions_set)] + + if yanked_versions: + # Saying "version X is yanked" isn't entirely accurate. + # https://github.com/pypa/pip/issues/11745#issuecomment-1402805842 + logger.critical( + "Ignored the following yanked versions: %s", + ", ".join(yanked_versions) or "none", + ) if skipped_by_requires_python: logger.critical( "Ignored the following versions that require a different python " diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index 5e8a82fb3..161881419 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -2242,6 +2242,33 @@ def test_install_yanked_file_and_print_warning( assert "Successfully installed simple-3.0\n" in result.stdout, str(result) +def test_yanked_version_missing_from_availble_versions_error_message( + script: PipTestEnvironment, data: TestData +) -> None: + """ + Test yanked version is missing from available versions error message. + + Yanked files are always ignored, unless they are the only file that + matches a version specifier that "pins" to an exact version (PEP 592). + """ + result = script.pip( + "install", + "simple==", + "--index-url", + data.index_url("yanked"), + expect_error=True, + ) + # the yanked version (3.0) is filtered out from the output: + expected_warning = ( + "Could not find a version that satisfies the requirement simple== " + "(from versions: 1.0, 2.0)" + ) + assert expected_warning in result.stderr, str(result) + # and mentioned in a separate warning: + expected_warning = "Ignored the following yanked versions: 3.0" + assert expected_warning in result.stderr, str(result) + + def test_error_all_yanked_files_and_no_pin( script: PipTestEnvironment, data: TestData ) -> None: