From 23cf811b5e4440b9014e8df37f656dd44f40de5c Mon Sep 17 00:00:00 2001 From: Damian Shaw Date: Wed, 15 Apr 2026 09:37:39 -0400 Subject: [PATCH 1/2] Avoid version set construction in get applicable candidates --- src/pip/_internal/index/package_finder.py | 26 +++++++++-------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index b56ffb1c43b..cd97df01daa 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -19,7 +19,7 @@ from pip._vendor.packaging import specifiers from pip._vendor.packaging.tags import Tag from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import InvalidVersion, Version, _BaseVersion +from pip._vendor.packaging.version import InvalidVersion, _BaseVersion from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import ( @@ -493,7 +493,6 @@ def get_applicable_candidates( else: allow_prereleases = None specifier = self._specifier - # When using the pkg_resources backend we turn the version object into # a str here because otherwise when we're debundled but setuptools isn't, # Python will see packaging.version.Version and @@ -501,22 +500,17 @@ def get_applicable_candidates( # types. This way we'll use a str as a common data interchange # format. If we stop using the pkg_resources provided specifier # and start using our own, we can drop the cast to str(). - if select_backend().NAME == "pkg_resources": - candidates_and_versions: list[ - tuple[InstallationCandidate, str | Version] - ] = [(c, str(c.version)) for c in candidates] - else: - candidates_and_versions = [(c, c.version) for c in candidates] - versions = set( - specifier.filter( - (v for _, v in candidates_and_versions), - prereleases=allow_prereleases, - ) + applicable_candidates = specifier.filter( + candidates, + prereleases=allow_prereleases, + key=lambda c: ( + str(c.version) + if select_backend().NAME == "pkg_resources" + else c.version + ), ) - - applicable_candidates = [c for c, v in candidates_and_versions if v in versions] filtered_applicable_candidates = filter_unallowed_hashes( - candidates=applicable_candidates, + candidates=list(applicable_candidates), hashes=self._hashes, project_name=self._project_name, ) From 297383c471e2aa0eb4ba7686e5cdd634514ff5ce Mon Sep 17 00:00:00 2001 From: Damian Shaw Date: Wed, 15 Apr 2026 09:43:58 -0400 Subject: [PATCH 2/2] News Entry --- news/13916.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/13916.bugfix.rst diff --git a/news/13916.bugfix.rst b/news/13916.bugfix.rst new file mode 100644 index 00000000000..991d15e6c8b --- /dev/null +++ b/news/13916.bugfix.rst @@ -0,0 +1 @@ +Minor performance improvement when filtering candidates during resolution.