fix finder version sorting with Inf object

This commit is contained in:
Marcus Smith 2012-09-23 14:58:14 -07:00
parent 4ea13f474c
commit 93bdb858d8
4 changed files with 67 additions and 19 deletions

View File

@ -165,7 +165,7 @@ class PackageFinder(object):
logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
raise DistributionNotFound('No distributions at all found for %s' % req)
if req.satisfied_by is not None:
found_versions.append((req.satisfied_by.parsed_version, Inf, req.satisfied_by.version))
found_versions.append((req.satisfied_by.parsed_version, InfLink, req.satisfied_by.version))
if file_versions:
file_versions.sort(reverse=True)
logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions]))
@ -177,31 +177,31 @@ class PackageFinder(object):
logger.info("Ignoring link %s, version %s doesn't match %s"
% (link, version, ','.join([''.join(s) for s in req.req.specs])))
continue
applicable_versions.append((link, version))
applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True)
existing_applicable = bool([link for link, version in applicable_versions if link is Inf])
applicable_versions.append((parsed_version, link, version))
applicable_versions = sorted(applicable_versions, reverse=True)
existing_applicable = bool([link for parsed_version, link, version in applicable_versions if link is InfLink])
if not upgrade and existing_applicable:
if applicable_versions[0][1] is Inf:
if applicable_versions[0][1] is InfLink:
logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
% req.satisfied_by.version)
raise BestVersionAlreadyInstalled
else:
logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)'
% (req.satisfied_by.version, applicable_versions[0][1]))
% (req.satisfied_by.version, applicable_versions[0][2]))
return None
if not applicable_versions:
logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)'
% (req, ', '.join([version for parsed_version, link, version in found_versions])))
raise DistributionNotFound('No distributions matching the version for %s' % req)
if applicable_versions[0][0] is Inf:
if applicable_versions[0][1] is InfLink:
# We have an existing version, and its the best version
logger.info('Installed version (%s) is most up-to-date (past versions: %s)'
% (req.satisfied_by.version, ', '.join([version for link, version in applicable_versions[1:]]) or 'none'))
% (req.satisfied_by.version, ', '.join([version for parsed_version, link, version in applicable_versions[1:]]) or 'none'))
raise BestVersionAlreadyInstalled
if len(applicable_versions) > 1:
logger.info('Using version %s (newest of versions: %s)' %
(applicable_versions[0][1], ', '.join([version for link, version in applicable_versions])))
return applicable_versions[0][0]
(applicable_versions[0][2], ', '.join([version for parsed_version, link, version in applicable_versions])))
return applicable_versions[0][1]
def _find_url_name(self, index_url, url_name, req):
"""Finds the true URL name of a package, when the given name isn't quite correct.
@ -595,7 +595,7 @@ class Link(object):
if self.comes_from:
return '%s (from %s)' % (self.url, self.comes_from)
else:
return self.url
return str(self.url)
def __repr__(self):
return '<Link %s>' % self
@ -673,6 +673,9 @@ class Link(object):
def show_url(self):
return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0])
#An "Infinite Link" that compares greater than other links
InfLink = Link(Inf)
def get_requirement_from_url(url):
"""Get a requirement from the URL, if possible. This looks for #egg

View File

@ -1,10 +1,12 @@
from pkg_resources import parse_version
from pip.backwardcompat import urllib
from pip.req import InstallRequirement
from pip.index import PackageFinder
from pip.exceptions import BestVersionAlreadyInstalled
from tests.path import Path
from tests.test_pip import here
from nose.tools import assert_raises
from mock import Mock
find_links = 'file://' + urllib.quote(str(Path(here).abspath/'packages').replace('\\', '/'))
find_links2 = 'file://' + urllib.quote(str(Path(here).abspath/'packages2').replace('\\', '/'))
@ -35,3 +37,41 @@ def test_duplicates_sort_ok():
found = finder.find_requirement(req, False)
assert found.url.endswith("duplicate-1.0.tar.gz"), found
def test_finder_detects_latest_find_links():
"""Test PackageFinder detects latest using find-links"""
req = InstallRequirement.from_line('simple', None)
finder = PackageFinder([find_links], [])
link = finder.find_requirement(req, False)
assert link.url.endswith("simple-3.0.tar.gz")
def test_finder_detects_latest_already_satisfied_find_links():
"""Test PackageFinder detects latest already satisified using find-links"""
req = InstallRequirement.from_line('simple', None)
#the latest simple in local pkgs is 3.0
latest_version = "3.0"
satisfied_by = Mock(
location = "/path",
parsed_version = parse_version(latest_version),
version = latest_version
)
req.satisfied_by = satisfied_by
finder = PackageFinder([find_links], [])
assert_raises(BestVersionAlreadyInstalled, finder.find_requirement, req, True)
def test_finder_detects_latest_already_satisfied_pypi_links():
"""Test PackageFinder detects latest already satisified using pypi links"""
req = InstallRequirement.from_line('initools', None)
#the latest initools on pypi is 0.3.1
latest_version = "0.3.1"
satisfied_by = Mock(
location = "/path",
parsed_version = parse_version(latest_version),
version = latest_version
)
req.satisfied_by = satisfied_by
finder = PackageFinder([], ["http://pypi.python.org/simple"])
assert_raises(BestVersionAlreadyInstalled, finder.find_requirement, req, True)

View File

@ -2,7 +2,7 @@ import os
from pip.backwardcompat import urllib
from tests.path import Path
from pip.index import package_to_requirement, HTMLPage, get_mirrors, DEFAULT_MIRROR_HOSTNAME
from pip.index import PackageFinder
from pip.index import PackageFinder, Link, InfLink
from tests.test_pip import reset_env, run_pip, pyversion, here
from string import ascii_lowercase
from mock import patch
@ -101,3 +101,7 @@ def test_file_index_url_quoting():
assert (env.site_packages/'simple') in result.files_created, str(result.stdout)
assert (env.site_packages/'simple-1.0-py%s.egg-info' % pyversion) in result.files_created, str(result)
def test_inflink_greater():
"""Test InfLink compares greater."""
assert InfLink > Link(object())

View File

@ -49,11 +49,12 @@ def test_upgrade_with_newest_already_installed():
not be reinstalled and the user should be informed.
"""
find_links = 'file://' + join(here, 'packages')
env = reset_env()
run_pip('install', 'INITools')
result = run_pip('install', '--upgrade', 'INITools')
assert not result.files_created, 'pip install --upgrade INITools upgraded when it should not have'
assert 'already up-to-date' in result.stdout
run_pip('install', '-f', find_links, '--no-index', 'simple')
result = run_pip('install', '--upgrade', '-f', find_links, '--no-index', 'simple')
assert not result.files_created, 'simple upgraded when it should not have'
assert 'already up-to-date' in result.stdout, result.stdout
def test_upgrade_force_reinstall_newest():