when installing from wheel files, parse the filename to build the requirement

This commit is contained in:
Marcus Smith 2014-05-25 21:00:39 -07:00
parent 52ffb9f9ea
commit 3066157cc3
9 changed files with 62 additions and 12 deletions

View File

@ -141,31 +141,46 @@ class InstallRequirement(object):
if is_url(name):
link = Link(name)
elif os.path.isdir(path) and (os.path.sep in name or name.startswith('.')):
elif (os.path.isdir(path)
and (os.path.sep in name or name.startswith('.'))):
if not is_installable_dir(path):
raise InstallationError("Directory %r is not installable. File 'setup.py' not found." % name)
raise InstallationError(
"Directory %r is not installable. File 'setup.py' not "
"found." % name
)
link = Link(path_to_url(name))
elif is_archive_file(path):
if not os.path.isfile(path):
logger.warn('Requirement %r looks like a filename, but the file does not exist', name)
logger.warn(
'Requirement %r looks like a filename, but the file does '
'not exist',
name
)
link = Link(path_to_url(name))
# If the line has an egg= definition, but isn't editable, pull the requirement out.
# Otherwise, assume the name is the req for the non URL/path/archive case.
if link and req is None:
url = link.url_without_fragment
req = link.egg_fragment #when fragment is None, this will become an 'unnamed' requirement
# it's a local file, dir, or url
if link:
url = link.url_without_fragment
# Handle relative file URLs
if link.scheme == 'file' and re.search(r'\.\./', url):
url = path_to_url(os.path.normpath(os.path.abspath(link.path)))
# fail early for invalid or unsupported wheels
# wheel file
if link.ext == wheel_ext:
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
if not wheel.supported():
raise UnsupportedWheel("%s is not a supported wheel on this platform." % wheel.filename)
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
# will become an 'unnamed' requirement
req = link.egg_fragment
# a requirement specifier
else:
req = name

View File

@ -0,0 +1,7 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='simplewheel',
version='1.0',
packages=find_packages()
)

View File

@ -0,0 +1 @@
#

View File

@ -0,0 +1,7 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='simplewheel',
version='2.0',
packages=find_packages()
)

View File

@ -0,0 +1 @@
#

View File

@ -272,3 +272,15 @@ def test_wheel_no_compiles_pyc(script, data):
)
assert not any(exists)
def test_install_from_wheel_uninstalls_old_version(script, data):
# regression test for https://github.com/pypa/pip/issues/1825
package = data.packages.join("simplewheel-1.0-py2.py3-none-any.whl")
result = script.pip('install', package, '--no-index', expect_error=True)
package = data.packages.join("simplewheel-2.0-py2.py3-none-any.whl")
result = script.pip('install', package, '--no-index', expect_error=False)
dist_info_folder = script.site_packages / 'simplewheel-2.0.dist-info'
assert dist_info_folder in result.files_created
dist_info_folder = script.site_packages / 'simplewheel-1.0.dist-info'
assert dist_info_folder not in result.files_created

View File

@ -8,7 +8,10 @@ import pip.wheel
from pkg_resources import Distribution
from mock import Mock, patch, mock_open
from pip.exceptions import PreviousBuildDirError, InvalidWheelFilename, UnsupportedWheel
from pip.exceptions import (
PreviousBuildDirError, InvalidWheelFilename, UnsupportedWheel,
)
from pip._vendor import pkg_resources
from pip.index import PackageFinder
from pip.log import logger
from pip.req import (read_text_file, InstallRequirement, RequirementSet,
@ -85,6 +88,10 @@ class TestInstallRequirement(object):
with pytest.raises(InvalidWheelFilename):
req = InstallRequirement.from_line('invalid.whl')
def test_wheel_requirement_sets_req_attribute(self):
req = InstallRequirement.from_line('simple-0.1-py2.py3-none-any.whl')
assert req.req == pkg_resources.Requirement.parse('simple==0.1')
def test_requirements_data_structure_keeps_order():
requirements = Requirements()