Skip to content

Commit

Permalink
Merge pull request #9708 from ronaudinho/requires-python
Browse files Browse the repository at this point in the history
  • Loading branch information
pradyunsg authored Mar 10, 2022
2 parents bc45b93 + 60fe6c0 commit c679319
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 9 deletions.
1 change: 1 addition & 0 deletions news/9615.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Explains why specified version cannot be retrieved when *Requires-Python* is not satisfied.
19 changes: 11 additions & 8 deletions src/pip/_internal/index/package_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,8 @@ def evaluate_link(self, link: Link) -> Tuple[bool, Optional[str]]:
ignore_requires_python=self._ignore_requires_python,
)
if not supports_python:
# Return None for the reason text to suppress calling
# _log_skipped_link().
return (False, None)
reason = f"{version} Requires-Python {link.requires_python}"
return (False, reason)

logger.debug("Found link %s, version: %s", link, version)

Expand Down Expand Up @@ -610,7 +609,7 @@ def __init__(
self.format_control = format_control

# These are boring links that have already been logged somehow.
self._logged_links: Set[Link] = set()
self._logged_links: Set[Tuple[Link, str]] = set()

# Don't include an allow_yanked default value to make sure each call
# site considers whether yanked releases are allowed. This also causes
Expand Down Expand Up @@ -690,6 +689,11 @@ def prefer_binary(self) -> bool:
def set_prefer_binary(self) -> None:
self._candidate_prefs.prefer_binary = True

def skipped_links_requires_python(self) -> List[str]:
return sorted(
{reason for _, reason in self._logged_links if "Requires-Python" in reason}
)

def make_link_evaluator(self, project_name: str) -> LinkEvaluator:
canonical_name = canonicalize_name(project_name)
formats = self.format_control.get_allowed_formats(canonical_name)
Expand Down Expand Up @@ -720,11 +724,11 @@ def _sort_links(self, links: Iterable[Link]) -> List[Link]:
return no_eggs + eggs

def _log_skipped_link(self, link: Link, reason: str) -> None:
if link not in self._logged_links:
if (link, reason) not in self._logged_links:
# Put the link at the end so the reason is more visible and because
# the link string is usually very long.
logger.debug("Skipping link: %s: %s", reason, link)
self._logged_links.add(link)
self._logged_links.add((link, reason))

def get_install_candidate(
self, link_evaluator: LinkEvaluator, link: Link
Expand All @@ -735,8 +739,7 @@ def get_install_candidate(
"""
is_candidate, result = link_evaluator.evaluate_link(link)
if not is_candidate:
if result:
self._log_skipped_link(link, reason=result)
self._log_skipped_link(link, result)
return None

return InstallationCandidate(
Expand Down
7 changes: 7 additions & 0 deletions src/pip/_internal/resolution/resolvelib/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,15 @@ def _report_single_requirement_conflict(
req_disp = f"{req} (from {parent.name})"

cands = self._finder.find_all_candidates(req.project_name)
skips = self._finder.skipped_links_requires_python()
versions = [str(v) for v in sorted({c.version for c in cands})]

if skips:
logger.critical(
"Ignored the following versions that require a different python "
"version: %s",
"; ".join(skips) or "none",
)
logger.critical(
"Could not find a version that satisfies the requirement %s "
"(from versions: %s)",
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class TestLinkEvaluator:
[
((3, 6, 5), False, (True, "1.12")),
# Test an incompatible Python.
((3, 6, 4), False, (False, None)),
((3, 6, 4), False, (False, "1.12 Requires-Python == 3.6.5")),
# Test an incompatible Python with ignore_requires_python=True.
((3, 6, 4), True, (True, "1.12")),
],
Expand Down

0 comments on commit c679319

Please sign in to comment.