1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

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) logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
raise DistributionNotFound('No distributions at all found for %s' % req) raise DistributionNotFound('No distributions at all found for %s' % req)
if req.satisfied_by is not None: 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: if file_versions:
file_versions.sort(reverse=True) file_versions.sort(reverse=True)
logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions])) 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" logger.info("Ignoring link %s, version %s doesn't match %s"
% (link, version, ','.join([''.join(s) for s in req.req.specs]))) % (link, version, ','.join([''.join(s) for s in req.req.specs])))
continue continue
applicable_versions.append((link, version)) applicable_versions.append((parsed_version, link, version))
applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True) applicable_versions = sorted(applicable_versions, reverse=True)
existing_applicable = bool([link for link, version in applicable_versions if link is Inf]) existing_applicable = bool([link for parsed_version, link, version in applicable_versions if link is InfLink])
if not upgrade and existing_applicable: 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' logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
% req.satisfied_by.version) % req.satisfied_by.version)
raise BestVersionAlreadyInstalled
else: else:
logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)' 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 return None
if not applicable_versions: if not applicable_versions:
logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)' 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]))) % (req, ', '.join([version for parsed_version, link, version in found_versions])))
raise DistributionNotFound('No distributions matching the version for %s' % req) 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 # We have an existing version, and its the best version
logger.info('Installed version (%s) is most up-to-date (past versions: %s)' 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 raise BestVersionAlreadyInstalled
if len(applicable_versions) > 1: if len(applicable_versions) > 1:
logger.info('Using version %s (newest of versions: %s)' % logger.info('Using version %s (newest of versions: %s)' %
(applicable_versions[0][1], ', '.join([version for link, version in applicable_versions]))) (applicable_versions[0][2], ', '.join([version for parsed_version, link, version in applicable_versions])))
return applicable_versions[0][0] return applicable_versions[0][1]
def _find_url_name(self, index_url, url_name, req): 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. """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: if self.comes_from:
return '%s (from %s)' % (self.url, self.comes_from) return '%s (from %s)' % (self.url, self.comes_from)
else: else:
return self.url return str(self.url)
def __repr__(self): def __repr__(self):
return '<Link %s>' % self return '<Link %s>' % self
@ -673,6 +673,9 @@ class Link(object):
def show_url(self): def show_url(self):
return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0]) 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): def get_requirement_from_url(url):
"""Get a requirement from the URL, if possible. This looks for #egg """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.backwardcompat import urllib
from pip.req import InstallRequirement from pip.req import InstallRequirement
from pip.index import PackageFinder from pip.index import PackageFinder
from pip.exceptions import BestVersionAlreadyInstalled
from tests.path import Path from tests.path import Path
from tests.test_pip import here 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_links = 'file://' + urllib.quote(str(Path(here).abspath/'packages').replace('\\', '/'))
find_links2 = 'file://' + urllib.quote(str(Path(here).abspath/'packages2').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) found = finder.find_requirement(req, False)
assert found.url.endswith("duplicate-1.0.tar.gz"), found 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 pip.backwardcompat import urllib
from tests.path import Path from tests.path import Path
from pip.index import package_to_requirement, HTMLPage, get_mirrors, DEFAULT_MIRROR_HOSTNAME 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 tests.test_pip import reset_env, run_pip, pyversion, here
from string import ascii_lowercase from string import ascii_lowercase
from mock import patch 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') 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) 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. not be reinstalled and the user should be informed.
""" """
find_links = 'file://' + join(here, 'packages')
env = reset_env() env = reset_env()
run_pip('install', 'INITools') run_pip('install', '-f', find_links, '--no-index', 'simple')
result = run_pip('install', '--upgrade', 'INITools') result = run_pip('install', '--upgrade', '-f', find_links, '--no-index', 'simple')
assert not result.files_created, 'pip install --upgrade INITools upgraded when it should not have' assert not result.files_created, 'simple upgraded when it should not have'
assert 'already up-to-date' in result.stdout assert 'already up-to-date' in result.stdout, result.stdout
def test_upgrade_force_reinstall_newest(): def test_upgrade_force_reinstall_newest():