Skip to content

Move “is yanked” warning out of PackageFinder #8123

@uranusjr

Description

@uranusjr

Environment

  • pip version: >=19.3 (i.e. post PEP 592 implementation)
  • Python version: All
  • OS: All

Description
Currently PackageFinder issues a warning immediately when it decides a yanked link is the chosen as “best”:

def sort_best_candidate(
self,
candidates, # type: List[InstallationCandidate]
):
# type: (...) -> Optional[InstallationCandidate]
"""
Return the best candidate per the instance's sort order, or None if
no candidate is acceptable.
"""
if not candidates:
return None
best_candidate = max(candidates, key=self._sort_key)
# Log a warning per PEP 592 if necessary before returning.
link = best_candidate.link
if link.is_yanked:
reason = link.yanked_reason or '<none given>'
msg = (
# Mark this as a unicode string to prevent
# "UnicodeEncodeError: 'ascii' codec can't encode character"
# in Python 2 when the reason contains non-ascii characters.
u'The candidate selected for download or install is a '
'yanked version: {candidate}\n'
'Reason for being yanked: {reason}'
).format(candidate=best_candidate, reason=reason)
logger.warning(msg)
return best_candidate

There are fouer code paths in pip that can reach it. One of them (self_outdated_check.pip_self_version_check) never triggers the warning since the finder is constructed to exclude all yanked versions. Two are in the legacy resolver. The legacy resolver always selects the best available candidate. So the warning is valid because user should be warned if that candidate is yanked.

The other path is from the new resolver, which presents a problem. The candidate it chooses may be “unchosen” later (i.e. backtracking). The result is PackageFinder may show yanked warnings for candidates that are chosen during resolution but eventually discarded.

I worked on this briefly in #7796 but abandoned the work because there’s no easy way to refactor it, and the issue was only theoratical at the time anyway. But now we have the new resolver out for testing, and that PyPI actually starts supporting yanking, we’ll need to look into this soon.

Expected behavior
I think the warning needs to be moved into the resolver. This is not too difficult for the legacy resolver; just move it to the call site. It will be more difficult for the new resolver. We can issue a warning only when we know for sure the candidate is chosen (i.e. after the resolution completes), but before the link is resolved to the wheel cache (otherwise be loose the yank information). But OTOH the cache resolution must be done during the resolution (to fetch package metadata). So some additional refactoring is likely needed to make this work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions