mirror of https://github.com/pypa/pip
Give markers chance to remove incompat wheel links
`pip install -r reqs.txt` was failing when the requirements file includes an unsupported wheel, regardless of whether it is conditionally removed by a marker. This patch fixes that issue. Additionally, this patch makes pip check local file wheels for compatibility. Previously, a requirements file could include a path to a valid wheel for any platform and pip would happily install it.
This commit is contained in:
parent
e69cc372b8
commit
3c11bb4de9
|
@ -2,6 +2,9 @@
|
|||
|
||||
* Fix a regression on systems with uninitialized locale (:issue:`3575`).
|
||||
|
||||
* Use environment markers to filter packages before determining if a
|
||||
required wheel is supported. Solves (:issue:`3254`).
|
||||
|
||||
|
||||
**8.1.1 (2016-03-17)**
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import pip.wheel
|
|||
from pip.compat import native_str, get_stdlib, WINDOWS
|
||||
from pip.download import is_url, url_to_path, path_to_url, is_archive_file
|
||||
from pip.exceptions import (
|
||||
InstallationError, UninstallationError, UnsupportedWheel,
|
||||
InstallationError, UninstallationError,
|
||||
)
|
||||
from pip.locations import (
|
||||
bin_py, running_under_virtualenv, PIP_DELETE_MARKER_FILENAME, bin_user,
|
||||
|
@ -210,11 +210,6 @@ class InstallRequirement(object):
|
|||
# wheel file
|
||||
if link.is_wheel:
|
||||
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
|
||||
if not wheel.supported():
|
||||
raise UnsupportedWheel(
|
||||
"%s is not a supported wheel on this platform." %
|
||||
wheel.filename
|
||||
)
|
||||
req = "%s==%s" % (wheel.name, wheel.version)
|
||||
else:
|
||||
# set the req to the egg fragment. when it's not there, this
|
||||
|
|
|
@ -21,7 +21,7 @@ from pip.utils import (
|
|||
from pip.utils.hashes import MissingHashes
|
||||
from pip.utils.logging import indent_log
|
||||
from pip.vcs import vcs
|
||||
|
||||
from pip.wheel import Wheel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -227,6 +227,16 @@ class RequirementSet(object):
|
|||
install_req.markers)
|
||||
return []
|
||||
|
||||
# This check has to come after we filter requirements with the
|
||||
# environment markers.
|
||||
if install_req.link and install_req.link.is_wheel:
|
||||
wheel = Wheel(install_req.link.filename)
|
||||
if not wheel.supported():
|
||||
raise InstallationError(
|
||||
"%s is not a supported wheel on this platform." %
|
||||
wheel.filename
|
||||
)
|
||||
|
||||
install_req.as_egg = self.as_egg
|
||||
install_req.use_user_site = self.use_user_site
|
||||
install_req.target_dir = self.target_dir
|
||||
|
|
|
@ -457,3 +457,41 @@ def test_install_distribution_union_conflicting_extras(script, data):
|
|||
expect_error=True)
|
||||
assert 'installed' not in result.stdout
|
||||
assert "Conflict" in result.stderr
|
||||
|
||||
|
||||
def test_install_unsupported_wheel_link_with_marker(script, data):
|
||||
script.scratch_path.join("with-marker.txt").write(
|
||||
textwrap.dedent("""\
|
||||
%s; %s
|
||||
""") %
|
||||
(
|
||||
'https://github.com/a/b/c/asdf-1.5.2-cp27-none-xyz.whl',
|
||||
'sys_platform == "xyz"'
|
||||
)
|
||||
)
|
||||
result = script.pip(
|
||||
'install', '-r', script.scratch_path / 'with-marker.txt',
|
||||
expect_error=False,
|
||||
expect_stderr=True,
|
||||
)
|
||||
|
||||
s = "Ignoring asdf: markers %r don't match your environment" %\
|
||||
u'sys_platform == "xyz"'
|
||||
assert s in result.stderr
|
||||
assert len(result.files_created) == 0
|
||||
|
||||
|
||||
def test_install_unsupported_wheel_file(script, data):
|
||||
# Trying to install a local wheel with an incompatible version/type
|
||||
# should fail.
|
||||
script.scratch_path.join("wheel-file.txt").write(textwrap.dedent("""\
|
||||
%s
|
||||
""" % data.packages.join("simple.dist-0.1-py1-none-invalid.whl")))
|
||||
result = script.pip(
|
||||
'install', '-r', script.scratch_path / 'wheel-file.txt',
|
||||
expect_error=True,
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert ("simple.dist-0.1-py1-none-invalid.whl is not a supported " +
|
||||
"wheel on this platform" in result.stderr)
|
||||
assert len(result.files_created) == 0
|
||||
|
|
|
@ -8,7 +8,7 @@ import pytest
|
|||
from mock import Mock, patch, mock_open
|
||||
from pip.commands.install import InstallCommand
|
||||
from pip.exceptions import (PreviousBuildDirError, InvalidWheelFilename,
|
||||
InstallationError, UnsupportedWheel, HashErrors)
|
||||
InstallationError, HashErrors)
|
||||
from pip.download import path_to_url, PipSession
|
||||
from pip.index import PackageFinder
|
||||
from pip.req import (InstallRequirement, RequirementSet, Requirements)
|
||||
|
@ -301,6 +301,20 @@ def test_egg_info_data(file_contents, expected):
|
|||
|
||||
|
||||
class TestInstallRequirement(object):
|
||||
def setup(self):
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
|
||||
def teardown(self):
|
||||
shutil.rmtree(self.tempdir, ignore_errors=True)
|
||||
|
||||
def basic_reqset(self, **kwargs):
|
||||
return RequirementSet(
|
||||
build_dir=os.path.join(self.tempdir, 'build'),
|
||||
src_dir=os.path.join(self.tempdir, 'src'),
|
||||
download_dir=None,
|
||||
session=PipSession(),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def test_url_with_query(self):
|
||||
"""InstallRequirement should strip the fragment, but not the query."""
|
||||
|
@ -309,11 +323,29 @@ class TestInstallRequirement(object):
|
|||
req = InstallRequirement.from_line(url + fragment)
|
||||
assert req.link.url == url + fragment, req.link
|
||||
|
||||
def test_unsupported_wheel_requirement_raises(self):
|
||||
with pytest.raises(UnsupportedWheel):
|
||||
InstallRequirement.from_line(
|
||||
'peppercorn-0.4-py2.py3-bogus-any.whl',
|
||||
)
|
||||
def test_unsupported_wheel_link_requirement_raises(self):
|
||||
reqset = self.basic_reqset()
|
||||
req = InstallRequirement.from_line(
|
||||
'https://whatever.com/peppercorn-0.4-py2.py3-bogus-any.whl',
|
||||
)
|
||||
assert req.link is not None
|
||||
assert req.link.is_wheel
|
||||
assert req.link.scheme == "https"
|
||||
|
||||
with pytest.raises(InstallationError):
|
||||
reqset.add_requirement(req)
|
||||
|
||||
def test_unsupported_wheel_local_file_requirement_raises(self, data):
|
||||
reqset = self.basic_reqset()
|
||||
req = InstallRequirement.from_line(
|
||||
data.packages.join('simple.dist-0.1-py1-none-invalid.whl'),
|
||||
)
|
||||
assert req.link is not None
|
||||
assert req.link.is_wheel
|
||||
assert req.link.scheme == "file"
|
||||
|
||||
with pytest.raises(InstallationError):
|
||||
reqset.add_requirement(req)
|
||||
|
||||
def test_installed_version_not_installed(self):
|
||||
req = InstallRequirement.from_line('simple-0.1-py2.py3-none-any.whl')
|
||||
|
|
Loading…
Reference in New Issue