Skip to content

fix for #1825 #1838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 26, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
=========

1.5.7
-----

* Fixed Issue #1825. When installing directly from wheel paths or urls,
previous versions were not uninstalled. (PR #1838)


1.5.6 (2014-05-16)
------------------

Expand Down
37 changes: 26 additions & 11 deletions pip/req.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,31 +141,46 @@ def from_line(cls, name, comes_from=None, prereleases=None):

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

Expand Down
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions tests/data/src/simplewheel-1.0/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python
from setuptools import setup, find_packages

setup(name='simplewheel',
version='1.0',
packages=find_packages()
)
1 change: 1 addition & 0 deletions tests/data/src/simplewheel-1.0/simple/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
7 changes: 7 additions & 0 deletions tests/data/src/simplewheel-2.0/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python
from setuptools import setup, find_packages

setup(name='simplewheel',
version='2.0',
packages=find_packages()
)
1 change: 1 addition & 0 deletions tests/data/src/simplewheel-2.0/simple/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
12 changes: 12 additions & 0 deletions tests/functional/test_install_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 8 additions & 1 deletion tests/unit/test_req.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

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,
Expand Down Expand Up @@ -85,6 +88,10 @@ def test_invalid_wheel_requirement_raises(self):
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()
Expand Down