Ensure wheel-Version is compatible with pip

This commit is contained in:
Matthew Iversen 2014-02-15 17:21:22 +11:00
parent 19ef5973cd
commit 13f6c68f0c
8 changed files with 85 additions and 0 deletions

View File

@ -710,6 +710,17 @@ exec(compile(
self.install_editable(install_options, global_options)
return
if self.is_wheel:
wheel_version = pip.wheel.wheel_version(self.source_dir)
if ((not wheel_version) or
(wheel_version[0] > pip.wheel.VERSION_COMPATIBLE[0])):
raise UnsupportedWheel(
"%s's wheel version is not compatible with this version "
"of pip" % self.name
)
elif (wheel_version[0] == pip.wheel.VERSION_COMPATIBLE[0] and
wheel_version > pip.wheel.VERSION_COMPATIBLE):
logger.warn('Installing a newer Wheel-Version: %s'
% '.'.join(map(str, wheel_version)))
self.move_wheel_files(self.source_dir, root=root)
self.install_succeeded = True
return

View File

@ -21,9 +21,14 @@ from pip.log import logger
from pip import pep425tags
from pip.util import call_subprocess, normalize_path, make_path_relative
from pip._vendor.distlib.scripts import ScriptMaker
from pip._vendor.pkg_resources import (
Distribution, FileMetadata, PathMetadata
)
wheel_ext = '.whl'
VERSION_COMPATIBLE = (1, 0)
def rehash(path, algo='sha256', blocksize=1 << 20):
"""Return (hash, length) for path using hashlib.new(algo)"""
@ -392,6 +397,35 @@ def uninstallation_paths(dist):
yield path
def wheel_version(source_dir):
"""
Return the Wheel-Version of an extracted wheel, if possible.
Otherwise, return False if we couldn't parse / extract it.
"""
wheel_version_re = "Wheel-Version:(?P<version>.+)\n"
try:
entries = [e for e in os.listdir(source_dir)
if e.lower().endswith('.dist-info')]
entry = entries[0]
fullpath = os.path.join(source_dir, entry)
if os.path.isdir(fullpath):
# egg-info directory, allow getting metadata
metadata = PathMetadata(source_dir, fullpath)
else:
metadata = FileMetadata(fullpath)
dist = Distribution.from_location(
source_dir, entry, metadata
)
wheel_data = dist.get_metadata('WHEEL')
match = re.search(wheel_version_re, wheel_data)
version = match.group('version').strip()
version = tuple(map(int, version.split('.')))
return version
except:
return False
class Wheel(object):
"""A wheel file"""

View File

@ -29,6 +29,10 @@ FSPkg
-----
for installing from the file system
futurewheel
-----------
Wheels of a Wheel-Version that is newer in minor and major series.
gmpy-1.15.tar.gz
----------------
hash testing (although this pkg isn't needed explicitly)

View File

@ -5,6 +5,27 @@ import glob
from tests.lib.path import Path
def test_install_from_future_wheel_version(script, data):
"""
Test installing a future wheel (minor series)
"""
package = data.packages.join("futurewheel-1.9-py2.py3-none-any.whl")
result = script.pip('install', package, '--no-index', expect_error=False)
# TODO: test that warning is produced
package = data.packages.join("futurewheel-3.0-py2.py3-none-any.whl")
result = script.pip('install', package, '--no-index', expect_error=True)
# TODO: test that package didn't install, anything else necessary?
def test_install_from_broken_wheel(script, data):
"""
Test installing a future wheel (minor series)
"""
package = data.packages.join("brokenwheel-1.0-py2.py3-none-any.whl")
result = script.pip('install', package, '--no-index', expect_error=True)
# TODO: test that package didn't install, anything else necessary?
def test_install_from_wheel(script, data):
"""
Test installing from a wheel (that has a script)

View File

@ -4,6 +4,7 @@ import pytest
from mock import patch
from pip import wheel
from pip.exceptions import InvalidWheelFilename
from pip.util import unpack_file
def test_get_entrypoints(tmpdir):
@ -46,6 +47,20 @@ def test_uninstallation_paths():
assert paths2 == paths
def test_version_compatible(tmpdir, data):
future_wheel = 'futurewheel-1.9-py2.py3-none-any.whl'
broken_wheel = 'brokenwheel-1.0-py2.py3-none-any.whl'
future_version = (1, 9)
unpack_file(data.packages.join(future_wheel),
tmpdir + 'future', None, None)
unpack_file(data.packages.join(broken_wheel),
tmpdir + 'broken', None, None)
assert wheel.wheel_version(tmpdir + 'future') == future_version
assert not wheel.wheel_version(tmpdir + 'broken')
class TestWheelFile(object):
def test_std_wheel_pattern(self):