Skip to content

Commit 5ace29f

Browse files
committed
Merge pull request #1838 from qwcode/issue_1825_1.5
fix for #1825
2 parents 52ffb9f + a36f663 commit 5ace29f

File tree

10 files changed

+69
-12
lines changed

10 files changed

+69
-12
lines changed

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
1.5.7
5+
-----
6+
7+
* Fixed Issue #1825. When installing directly from wheel paths or urls,
8+
previous versions were not uninstalled. (PR #1838)
9+
10+
411
1.5.6 (2014-05-16)
512
------------------
613

pip/req.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -141,31 +141,46 @@ def from_line(cls, name, comes_from=None, prereleases=None):
141141

142142
if is_url(name):
143143
link = Link(name)
144-
elif os.path.isdir(path) and (os.path.sep in name or name.startswith('.')):
144+
elif (os.path.isdir(path)
145+
and (os.path.sep in name or name.startswith('.'))):
145146
if not is_installable_dir(path):
146-
raise InstallationError("Directory %r is not installable. File 'setup.py' not found." % name)
147+
raise InstallationError(
148+
"Directory %r is not installable. File 'setup.py' not "
149+
"found." % name
150+
)
147151
link = Link(path_to_url(name))
148152
elif is_archive_file(path):
149153
if not os.path.isfile(path):
150-
logger.warn('Requirement %r looks like a filename, but the file does not exist', name)
154+
logger.warn(
155+
'Requirement %r looks like a filename, but the file does '
156+
'not exist',
157+
name
158+
)
151159
link = Link(path_to_url(name))
152160

153-
# If the line has an egg= definition, but isn't editable, pull the requirement out.
154-
# Otherwise, assume the name is the req for the non URL/path/archive case.
155-
if link and req is None:
156-
url = link.url_without_fragment
157-
req = link.egg_fragment #when fragment is None, this will become an 'unnamed' requirement
161+
# it's a local file, dir, or url
162+
if link:
158163

164+
url = link.url_without_fragment
159165
# Handle relative file URLs
160166
if link.scheme == 'file' and re.search(r'\.\./', url):
161167
url = path_to_url(os.path.normpath(os.path.abspath(link.path)))
162168

163-
# fail early for invalid or unsupported wheels
169+
# wheel file
164170
if link.ext == wheel_ext:
165-
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
171+
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
166172
if not wheel.supported():
167-
raise UnsupportedWheel("%s is not a supported wheel on this platform." % wheel.filename)
173+
raise UnsupportedWheel(
174+
"%s is not a supported wheel on this platform." %
175+
wheel.filename
176+
)
177+
req = "%s==%s" % (wheel.name, wheel.version)
178+
else:
179+
# set the req to the egg fragment. when it's not there, this
180+
# will become an 'unnamed' requirement
181+
req = link.egg_fragment
168182

183+
# a requirement specifier
169184
else:
170185
req = name
171186

Binary file not shown.
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env python
2+
from setuptools import setup, find_packages
3+
4+
setup(name='simplewheel',
5+
version='1.0',
6+
packages=find_packages()
7+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env python
2+
from setuptools import setup, find_packages
3+
4+
setup(name='simplewheel',
5+
version='2.0',
6+
packages=find_packages()
7+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#

tests/functional/test_install_wheel.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,15 @@ def test_wheel_no_compiles_pyc(script, data):
272272
)
273273

274274
assert not any(exists)
275+
276+
277+
def test_install_from_wheel_uninstalls_old_version(script, data):
278+
# regression test for https://github.com/pypa/pip/issues/1825
279+
package = data.packages.join("simplewheel-1.0-py2.py3-none-any.whl")
280+
result = script.pip('install', package, '--no-index', expect_error=True)
281+
package = data.packages.join("simplewheel-2.0-py2.py3-none-any.whl")
282+
result = script.pip('install', package, '--no-index', expect_error=False)
283+
dist_info_folder = script.site_packages / 'simplewheel-2.0.dist-info'
284+
assert dist_info_folder in result.files_created
285+
dist_info_folder = script.site_packages / 'simplewheel-1.0.dist-info'
286+
assert dist_info_folder not in result.files_created

tests/unit/test_req.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88

99
from pkg_resources import Distribution
1010
from mock import Mock, patch, mock_open
11-
from pip.exceptions import PreviousBuildDirError, InvalidWheelFilename, UnsupportedWheel
11+
from pip.exceptions import (
12+
PreviousBuildDirError, InvalidWheelFilename, UnsupportedWheel,
13+
)
14+
from pip._vendor import pkg_resources
1215
from pip.index import PackageFinder
1316
from pip.log import logger
1417
from pip.req import (read_text_file, InstallRequirement, RequirementSet,
@@ -85,6 +88,10 @@ def test_invalid_wheel_requirement_raises(self):
8588
with pytest.raises(InvalidWheelFilename):
8689
req = InstallRequirement.from_line('invalid.whl')
8790

91+
def test_wheel_requirement_sets_req_attribute(self):
92+
req = InstallRequirement.from_line('simple-0.1-py2.py3-none-any.whl')
93+
assert req.req == pkg_resources.Requirement.parse('simple==0.1')
94+
8895

8996
def test_requirements_data_structure_keeps_order():
9097
requirements = Requirements()

0 commit comments

Comments
 (0)