def evaluate_link(self, link: Link) -> Tuple[bool, Optional[str]]: """ Determine whether a link is a candidate for installation. :return: A tuple (is_candidate, result), where `result` is (1) a version string if `is_candidate` is True, and (2) if `is_candidate` is False, an optional string to log the reason the link fails to qualify. """ version = None if link.is_yanked and not self._allow_yanked: reason = link.yanked_reason or "<none given>" return (False, f"yanked for reason: {reason}") if link.egg_fragment: egg_info = link.egg_fragment ext = link.ext else: egg_info, ext = link.splitext() if not ext: return (False, "not a file") if ext not in SUPPORTED_EXTENSIONS: return (False, f"unsupported archive format: {ext}") if "binary" not in self._formats and ext == WHEEL_EXTENSION: reason = "No binaries permitted for {}".format( self.project_name) return (False, reason) if "macosx10" in link.path and ext == ".zip": return (False, "macosx10 one") if ext == WHEEL_EXTENSION: try: wheel = Wheel(link.filename) except InvalidWheelFilename: return (False, "invalid wheel filename") if canonicalize_name(wheel.name) != self._canonical_name: reason = "wrong project name (not {})".format( self.project_name) return (False, reason) supported_tags = self._target_python.get_tags() if not wheel.supported(supported_tags): # Include the wheel's tags in the reason string to # simplify troubleshooting compatibility issues. file_tags = wheel.get_formatted_file_tags() reason = ( "none of the wheel's tags ({}) are compatible " "(run pip debug --verbose to show compatible tags)". format(", ".join(file_tags))) return (False, reason) version = wheel.version # This should be up by the self.ok_binary check, but see issue 2700. if "source" not in self._formats and ext != WHEEL_EXTENSION: reason = f"No sources permitted for {self.project_name}" return (False, reason) if not version: version = _extract_version_from_fragment( egg_info, self._canonical_name, ) if not version: reason = f"Missing project version for {self.project_name}" return (False, reason) match = self._py_version_re.search(version) if match: version = version[:match.start()] py_version = match.group(1) if py_version != self._target_python.py_version: return (False, "Python version is incorrect") supports_python = _check_link_requires_python( link, version_info=self._target_python.py_version_info, 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) logger.debug("Found link %s, version: %s", link, version) return (True, version)
def evaluate_link(self, link: Link) -> Tuple[LinkType, str]: """ Determine whether a link is a candidate for installation. :return: A tuple (result, detail), where *result* is an enum representing whether the evaluation found a candidate, or the reason why one is not found. If a candidate is found, *detail* will be the candidate's version string; if one is not found, it contains the reason the link fails to qualify. """ version = None if link.is_yanked and not self._allow_yanked: reason = link.yanked_reason or "<none given>" return (LinkType.yanked, f"yanked for reason: {reason}") if link.egg_fragment: egg_info = link.egg_fragment ext = link.ext else: egg_info, ext = link.splitext() if not ext: return (LinkType.format_unsupported, "not a file") if ext not in SUPPORTED_EXTENSIONS: return ( LinkType.format_unsupported, f"unsupported archive format: {ext}", ) if "binary" not in self._formats and ext == WHEEL_EXTENSION: reason = f"No binaries permitted for {self.project_name}" return (LinkType.format_unsupported, reason) if "macosx10" in link.path and ext == ".zip": return (LinkType.format_unsupported, "macosx10 one") if ext == WHEEL_EXTENSION: try: wheel = Wheel(link.filename) except InvalidWheelFilename: return ( LinkType.format_invalid, "invalid wheel filename", ) if canonicalize_name(wheel.name) != self._canonical_name: reason = f"wrong project name (not {self.project_name})" return (LinkType.different_project, reason) supported_tags = self._target_python.get_tags() if not wheel.supported(supported_tags): # Include the wheel's tags in the reason string to # simplify troubleshooting compatibility issues. file_tags = ", ".join(wheel.get_formatted_file_tags()) reason = ( f"none of the wheel's tags ({file_tags}) are compatible " f"(run pip debug --verbose to show compatible tags)") return (LinkType.platform_mismatch, reason) version = wheel.version # This should be up by the self.ok_binary check, but see issue 2700. if "source" not in self._formats and ext != WHEEL_EXTENSION: reason = f"No sources permitted for {self.project_name}" return (LinkType.format_unsupported, reason) if not version: version = _extract_version_from_fragment( egg_info, self._canonical_name, ) if not version: reason = f"Missing project version for {self.project_name}" return (LinkType.format_invalid, reason) match = self._py_version_re.search(version) if match: version = version[:match.start()] py_version = match.group(1) if py_version != self._target_python.py_version: return ( LinkType.platform_mismatch, "Python version is incorrect", ) supports_python = _check_link_requires_python( link, version_info=self._target_python.py_version_info, ignore_requires_python=self._ignore_requires_python, ) if not supports_python: reason = f"{version} Requires-Python {link.requires_python}" return (LinkType.requires_python_mismatch, reason) logger.debug("Found link %s, version: %s", link, version) return (LinkType.candidate, version)