Skip to content

Commit c20c789

Browse files
authored
Merge pull request #11714 from uranusjr/strict-optional-free
Enable strict optional checking in PackageFinder
2 parents 9cc4e27 + dc8ac7b commit c20c789

File tree

2 files changed

+34
-27
lines changed

2 files changed

+34
-27
lines changed

src/pip/_internal/index/package_finder.py

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
"""Routines related to PyPI, indexes"""
22

3-
# The following comment should be removed at some point in the future.
4-
# mypy: strict-optional=False
5-
63
import enum
74
import functools
85
import itertools
96
import logging
107
import re
11-
from typing import FrozenSet, Iterable, List, Optional, Set, Tuple, Union
8+
from typing import TYPE_CHECKING, FrozenSet, Iterable, List, Optional, Set, Tuple, Union
129

1310
from pip._vendor.packaging import specifiers
1411
from pip._vendor.packaging.tags import Tag
@@ -39,6 +36,9 @@
3936
from pip._internal.utils.packaging import check_requires_python
4037
from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS
4138

39+
if TYPE_CHECKING:
40+
from pip._vendor.typing_extensions import TypeGuard
41+
4242
__all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"]
4343

4444

@@ -251,7 +251,7 @@ def evaluate_link(self, link: Link) -> Tuple[LinkType, str]:
251251

252252
def filter_unallowed_hashes(
253253
candidates: List[InstallationCandidate],
254-
hashes: Hashes,
254+
hashes: Optional[Hashes],
255255
project_name: str,
256256
) -> List[InstallationCandidate]:
257257
"""
@@ -540,6 +540,7 @@ def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey:
540540
binary_preference = 1
541541
if wheel.build_tag is not None:
542542
match = re.match(r"^(\d+)(.*)$", wheel.build_tag)
543+
assert match is not None, "guaranteed by filename validation"
543544
build_tag_groups = match.groups()
544545
build_tag = (int(build_tag_groups[0]), build_tag_groups[1])
545546
else: # sdist
@@ -942,43 +943,46 @@ def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str:
942943
"No matching distribution found for {}".format(req)
943944
)
944945

945-
best_installed = False
946-
if installed_version and (
947-
best_candidate is None or best_candidate.version <= installed_version
948-
):
949-
best_installed = True
946+
def _should_install_candidate(
947+
candidate: Optional[InstallationCandidate],
948+
) -> "TypeGuard[InstallationCandidate]":
949+
if installed_version is None:
950+
return True
951+
if best_candidate is None:
952+
return False
953+
return best_candidate.version > installed_version
950954

951955
if not upgrade and installed_version is not None:
952-
if best_installed:
956+
if _should_install_candidate(best_candidate):
953957
logger.debug(
954-
"Existing installed version (%s) is most up-to-date and "
955-
"satisfies requirement",
958+
"Existing installed version (%s) satisfies requirement "
959+
"(most up-to-date version is %s)",
956960
installed_version,
961+
best_candidate.version,
957962
)
958963
else:
959964
logger.debug(
960-
"Existing installed version (%s) satisfies requirement "
961-
"(most up-to-date version is %s)",
965+
"Existing installed version (%s) is most up-to-date and "
966+
"satisfies requirement",
962967
installed_version,
963-
best_candidate.version,
964968
)
965969
return None
966970

967-
if best_installed:
968-
# We have an existing version, and its the best version
971+
if _should_install_candidate(best_candidate):
969972
logger.debug(
970-
"Installed version (%s) is most up-to-date (past versions: %s)",
971-
installed_version,
973+
"Using version %s (newest of versions: %s)",
974+
best_candidate.version,
972975
_format_versions(best_candidate_result.iter_applicable()),
973976
)
974-
raise BestVersionAlreadyInstalled
977+
return best_candidate
975978

979+
# We have an existing version, and its the best version
976980
logger.debug(
977-
"Using version %s (newest of versions: %s)",
978-
best_candidate.version,
981+
"Installed version (%s) is most up-to-date (past versions: %s)",
982+
installed_version,
979983
_format_versions(best_candidate_result.iter_applicable()),
980984
)
981-
return best_candidate
985+
raise BestVersionAlreadyInstalled
982986

983987

984988
def _find_name_version_sep(fragment: str, canonical_name: str) -> int:

src/pip/_internal/self_outdated_check.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def was_installed_by_pip(pkg: str) -> bool:
155155

156156
def _get_current_remote_pip_version(
157157
session: PipSession, options: optparse.Values
158-
) -> str:
158+
) -> Optional[str]:
159159
# Lets use PackageFinder to see what the latest pip version is
160160
link_collector = LinkCollector.create(
161161
session,
@@ -176,7 +176,7 @@ def _get_current_remote_pip_version(
176176
)
177177
best_candidate = finder.find_best_candidate("pip").best_candidate
178178
if best_candidate is None:
179-
return
179+
return None
180180

181181
return str(best_candidate.version)
182182

@@ -186,11 +186,14 @@ def _self_version_check_logic(
186186
state: SelfCheckState,
187187
current_time: datetime.datetime,
188188
local_version: DistributionVersion,
189-
get_remote_version: Callable[[], str],
189+
get_remote_version: Callable[[], Optional[str]],
190190
) -> Optional[UpgradePrompt]:
191191
remote_version_str = state.get(current_time)
192192
if remote_version_str is None:
193193
remote_version_str = get_remote_version()
194+
if remote_version_str is None:
195+
logger.debug("No remote pip version found")
196+
return None
194197
state.set(remote_version_str, current_time)
195198

196199
remote_version = parse_version(remote_version_str)

0 commit comments

Comments
 (0)