Repository: pypa/pip

Issue:
drop the use of "Inf"
`pip.util.Inf` stopped being used as a sortable 3 years ago.
https://github.com/pypa/pip/commit/62df4c2d4ad839af1660b6d30d8c18b7899565a6

It's just used as simple marker to represent the current installation.

we should use a simpler object, not one with sortable baggage.



Discussion:

Resolving patch:
diff --git a/pip/index.py b/pip/index.py
--- a/pip/index.py
+++ b/pip/index.py
@@ -17,7 +17,7 @@
 
 from pip.compat import ipaddress
 from pip.utils import (
-    Inf, cached_property, splitext, normalize_path,
+    cached_property, splitext, normalize_path,
     ARCHIVE_EXTENSIONS, SUPPORTED_EXTENSIONS, canonicalize_name)
 from pip.utils.deprecation import RemovedInPip9Warning
 from pip.utils.logging import indent_log
@@ -233,9 +233,7 @@ def _candidate_sort_key(self, candidate):
               with the same version, would have to be considered equal
         """
         support_num = len(supported_tags)
-        if candidate.location == INSTALLED_VERSION:
-            pri = 1
-        elif candidate.location.is_wheel:
+        if candidate.location.is_wheel:
             # can raise InvalidWheelFilename
             wheel = Wheel(candidate.location.filename)
             if not wheel.supported():
@@ -439,7 +437,7 @@ def find_requirement(self, req, upgrade):
         Returns a Link if found,
         Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise
         """
-        all_versions = self._find_all_versions(req.name)
+        all_candidates = self._find_all_versions(req.name)
 
         # Filter out anything which doesn't match our specifier
         _versions = set(
@@ -451,58 +449,33 @@ def find_requirement(self, req, upgrade):
                 # 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().
-                [str(x.version) for x in all_versions],
+                [str(c.version) for c in all_candidates],
                 prereleases=(
                     self.allow_all_prereleases
                     if self.allow_all_prereleases else None
                 ),
             )
         )
-        applicable_versions = [
+        applicable_candidates = [
             # Again, converting to str to deal with debundling.
-            x for x in all_versions if str(x.version) in _versions
+            c for c in all_candidates if str(c.version) in _versions
         ]
 
+        applicable_candidates = self._sort_versions(applicable_candidates)
+
         if req.satisfied_by is not None:
-            # Finally add our existing versions to the front of our versions.
-            applicable_versions.insert(
-                0,
-                InstallationCandidate(
-                    req.name,
-                    req.satisfied_by.version,
-                    INSTALLED_VERSION,
-                )
-            )
-            existing_applicable = True
+            installed_version = parse_version(req.satisfied_by.version)
         else:
-            existing_applicable = False
+            installed_version = None
 
-        applicable_versions = self._sort_versions(applicable_versions)
-
-        if not upgrade and existing_applicable:
-            if applicable_versions[0].location is INSTALLED_VERSION:
-                logger.debug(
-                    'Existing installed version (%s) is most up-to-date and '
-                    'satisfies requirement',
-                    req.satisfied_by.version,
-                )
-            else:
-                logger.debug(
-                    'Existing installed version (%s) satisfies requirement '
-                    '(most up-to-date version is %s)',
-                    req.satisfied_by.version,
-                    applicable_versions[0][2],
-                )
-            return None
-
-        if not applicable_versions:
+        if installed_version is None and not applicable_candidates:
             logger.critical(
                 'Could not find a version that satisfies the requirement %s '
                 '(from versions: %s)',
                 req,
                 ', '.join(
                     sorted(
-                        set(str(i.version) for i in all_versions),
+                        set(str(c.version) for c in all_candidates),
                         key=parse_version,
                     )
                 )
@@ -512,27 +485,46 @@ def find_requirement(self, req, upgrade):
                 'No matching distribution found for %s' % req
             )
 
-        if applicable_versions[0].location is INSTALLED_VERSION:
+        best_installed = False
+        if installed_version and (
+                not applicable_candidates or
+                applicable_candidates[0].version <= installed_version):
+            best_installed = True
+
+        if not upgrade and installed_version is not None:
+            if best_installed:
+                logger.debug(
+                    'Existing installed version (%s) is most up-to-date and '
+                    'satisfies requirement',
+                    installed_version,
+                )
+            else:
+                logger.debug(
+                    'Existing installed version (%s) satisfies requirement '
+                    '(most up-to-date version is %s)',
+                    installed_version,
+                    applicable_candidates[0].version,
+                )
+            return None
+
+        if best_installed:
             # We have an existing version, and its the best version
             logger.debug(
                 'Installed version (%s) is most up-to-date (past versions: '
                 '%s)',
-                req.satisfied_by.version,
-                ', '.join(str(i.version) for i in applicable_versions[1:]) or
+                installed_version,
+                ', '.join(str(c.version) for c in applicable_candidates) or
                 "none",
             )
             raise BestVersionAlreadyInstalled
 
-        if len(applicable_versions) > 1:
-            logger.debug(
-                'Using version %s (newest of versions: %s)',
-                applicable_versions[0].version,
-                ', '.join(str(i.version) for i in applicable_versions)
-            )
-
-        selected_version = applicable_versions[0].location
-
-        return selected_version
+        selected_candidate = applicable_candidates[0]
+        logger.debug(
+            'Using version %s (newest of versions: %s)',
+            selected_candidate.version,
+            ', '.join(str(c.version) for c in applicable_candidates)
+        )
+        return selected_candidate.location
 
     def _get_pages(self, locations, project_name):
         """
@@ -873,7 +865,7 @@ class Link(object):
     def __init__(self, url, comes_from=None):
 
         # url can be a UNC windows share
-        if url != Inf and url.startswith('\\\\'):
+        if url.startswith('\\\\'):
             url = path_to_url(url)
 
         self.url = url
@@ -1002,11 +994,6 @@ def is_artifact(self):
         return True
 
 
-# An object to represent the "link" for the installed version of a requirement.
-# Using Inf as the url makes it sort higher.
-INSTALLED_VERSION = Link(Inf)
-
-
 FormatControl = namedtuple('FormatControl', 'no_binary only_binary')
 """This object has two fields, no_binary and only_binary.
 
diff --git a/pip/utils/__init__.py b/pip/utils/__init__.py
--- a/pip/utils/__init__.py
+++ b/pip/utils/__init__.py
@@ -31,7 +31,7 @@
     from io import StringIO
 
 __all__ = ['rmtree', 'display_path', 'backup_dir',
-           'ask', 'Inf', 'splitext',
+           'ask', 'splitext',
            'format_size', 'is_installable_dir',
            'is_svn_page', 'file_contents',
            'split_leading_dir', 'has_leading_dir',
@@ -154,38 +154,6 @@ def ask(message, options):
             return response
 
 
-class _Inf(object):
-    """I am bigger than everything!"""
-
-    def __eq__(self, other):
-        if self is other:
-            return True
-        else:
-            return False
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __lt__(self, other):
-        return False
-
-    def __le__(self, other):
-        return False
-
-    def __gt__(self, other):
-        return True
-
-    def __ge__(self, other):
-        return True
-
-    def __repr__(self):
-        return 'Inf'
-
-
-Inf = _Inf()  # this object is not currently used as a sortable in our code
-del _Inf
-
-
 def format_size(bytes):
     if bytes > 1000 * 1000:
         return '%.1fMB' % (bytes / 1000.0 / 1000)


Test patch:
diff --git a/tests/unit/test_finder.py b/tests/unit/test_finder.py
--- a/tests/unit/test_finder.py
+++ b/tests/unit/test_finder.py
@@ -11,7 +11,6 @@
 from pip.exceptions import (
     BestVersionAlreadyInstalled, DistributionNotFound, InstallationError,
 )
-from pip.utils import Inf
 from pip.download import PipSession
 
 from mock import Mock, patch
@@ -225,7 +224,6 @@ def test_link_sorting(self):
         Test link sorting
         """
         links = [
-            InstallationCandidate("simple", "2.0", Link(Inf)),
             InstallationCandidate("simple", "2.0", Link('simple-2.0.tar.gz')),
             InstallationCandidate(
                 "simple",
diff --git a/tests/unit/test_index.py b/tests/unit/test_index.py
--- a/tests/unit/test_index.py
+++ b/tests/unit/test_index.py
@@ -2,7 +2,7 @@
 
 from pip.download import PipSession
 from pip.index import HTMLPage
-from pip.index import PackageFinder, Link, INSTALLED_VERSION
+from pip.index import PackageFinder, Link
 
 
 def test_sort_locations_file_expand_dir(data):
@@ -27,11 +27,6 @@ def test_sort_locations_file_not_find_link(data):
     assert urls and not files, "urls, but not files should have been found"
 
 
-def test_INSTALLED_VERSION_greater():
-    """Test INSTALLED_VERSION compares greater."""
-    assert INSTALLED_VERSION > Link("some link")
-
-
 class TestLink(object):
 
     def test_splitext(self):
diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
--- a/tests/unit/test_utils.py
+++ b/tests/unit/test_utils.py
@@ -12,7 +12,7 @@
 import pytest
 
 from mock import Mock, patch
-from pip.utils import (egg_link_path, Inf, get_installed_distributions,
+from pip.utils import (egg_link_path, get_installed_distributions,
                        untar_file, unzip_file, rmtree, normalize_path)
 from pip.operations.freeze import freeze_excludes
 
@@ -151,16 +151,6 @@ def test_noegglink_in_sitepkgs_venv_global(self):
         assert egg_link_path(self.mock_dist) is None
 
 
-def test_Inf_greater():
-    """Test Inf compares greater."""
-    assert Inf > object()
-
-
-def test_Inf_equals_Inf():
-    """Test Inf compares greater."""
-    assert Inf == Inf
-
-
 @patch('pip.utils.dist_in_usersite')
 @patch('pip.utils.dist_is_local')
 @patch('pip.utils.dist_is_editable')