Skip to content

Commit 7255b61

Browse files
committed
Remove existing package before develop mode install
setuptools has changed its default behaviour whe installing packages installed in "develop mode" (i.e. pip -e) from being inserted first in sys.path to being added last (for details, see the bug). This means that if "pip install -e" a git tree to work on something but have the original package installed from PyPi (etc.), you will not actually be importing the development version. During interactive development you'll probably notice that your changes aren't applying and start digging around, but this behaviour change could be very bad in a CI situation where you *think* you've installed a development version but really, with setuptools>=25, you're just testing the release version. This change removes an existing install before deploying in develop mode. This way we only have one copy of the package and avoid ordering issues. A new test is added. Fixes #3874
1 parent 933c7f8 commit 7255b61

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

pip/req/req_set.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ def install(self, install_options, global_options=(), *args, **kwargs):
718718
the packages)
719719
"""
720720
to_install = self._to_install()
721+
editable_reinstall = False
721722

722723
if to_install:
723724
logger.info(
@@ -734,6 +735,23 @@ def install(self, install_options, global_options=(), *args, **kwargs):
734735
)
735736
with indent_log():
736737
requirement.uninstall(auto_confirm=True)
738+
739+
if requirement.installed_version and requirement.editable:
740+
# If we have an existing installation but are
741+
# re-installing as editable, make sure we remove
742+
# the existing version. Note that with
743+
# setuptools<25 this is not strictly required, as
744+
# there setuptools will modify easy-install.pth to
745+
# put the "develop" mode install first in sys.path
746+
# (see SETUPTOOLS_SYS_PATH_TECHNIQUE), effectively
747+
# overwriting the prior installed version.
748+
logger.info(
749+
'Found prior install %s, reinstalling for develop mode'
750+
% requirement.installed_version)
751+
with indent_log():
752+
requirement.uninstall(auto_confirm=True)
753+
editable_reinstall = True
754+
737755
try:
738756
requirement.install(
739757
install_options,
@@ -743,12 +761,12 @@ def install(self, install_options, global_options=(), *args, **kwargs):
743761
)
744762
except:
745763
# if install did not succeed, rollback previous uninstall
746-
if (requirement.conflicts_with and not
747-
requirement.install_succeeded):
764+
if ((requirement.conflicts_with or editable_reinstall) and
765+
not requirement.install_succeeded):
748766
requirement.rollback_uninstall()
749767
raise
750768
else:
751-
if (requirement.conflicts_with and
769+
if ((requirement.conflicts_with or editable_reinstall) and
752770
requirement.install_succeeded):
753771
requirement.commit_uninstall()
754772
requirement.remove_temporary_source()

tests/functional/test_install.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from tests.lib import (pyversion, pyversion_tuple,
1313
_create_test_package, _create_svn_repo, path_to_url,
1414
requirements_file)
15-
from tests.lib.local_repos import local_checkout
15+
from tests.lib.local_repos import local_checkout, local_repo
1616
from tests.lib.path import Path
1717

1818

@@ -1026,3 +1026,25 @@ def test_double_install_fail(script, data):
10261026
msg = ("Double requirement given: pip==7.1.2 (already in pip==*, "
10271027
"name='pip')")
10281028
assert msg in result.stderr
1029+
1030+
1031+
@pytest.mark.network
1032+
def test_update_to_develop(script, tmpdir):
1033+
"""
1034+
Test updating from install to develop mode removes original package
1035+
"""
1036+
path = local_repo(
1037+
'git+http://github.com/pypa/pip-test-package.git',
1038+
tmpdir.join("cache"),
1039+
)
1040+
1041+
# regular install, then re-install with develop mode
1042+
result = script.pip(
1043+
'install', '%s' % path, expect_error=False)
1044+
result = script.pip(
1045+
'install', '-e', '%s' % path, expect_error=False)
1046+
1047+
# make sure we have overwritten the non-develop install with the
1048+
# git version.
1049+
result = script.pip('freeze', expect_stderr=True)
1050+
assert 'pip-test-package.git' in result.stdout

0 commit comments

Comments
 (0)