diff --git a/pip/req/req_install.py b/pip/req/req_install.py index ec7524f54..cc72b6ee9 100644 --- a/pip/req/req_install.py +++ b/pip/req/req_install.py @@ -560,22 +560,18 @@ exec(compile( paths_to_remove = UninstallPathSet(dist) develop_egg_link = egg_link_path(dist) + develop_egg_link_egg_info = '{0}.egg-info'.format( + pkg_resources.to_filename(dist.project_name)) egg_info_exists = dist.egg_info and os.path.exists(dist.egg_info) # Special case for distutils installed package distutils_egg_info = getattr(dist._provider, 'path', None) - if develop_egg_link: - # develop egg - with open(develop_egg_link, 'r') as fh: - link_pointer = os.path.normcase(fh.readline().strip()) - assert (link_pointer == dist.location), ( - 'Egg-link %s does not match installed location of %s ' - '(at %s)' % (link_pointer, self.name, dist.location) - ) - paths_to_remove.add(develop_egg_link) - easy_install_pth = os.path.join(os.path.dirname(develop_egg_link), - 'easy-install.pth') - paths_to_remove.add_pth(easy_install_pth, dist.location) - elif egg_info_exists and dist.egg_info.endswith('.egg-info'): + + # Uninstall cases order do matter as in the case of 2 installs of the + # same package, pip needs to uninstall the currently detected version + if (egg_info_exists and dist.egg_info.endswith('.egg-info') and + not dist.egg_info.endswith(develop_egg_link_egg_info)): + # if dist.egg_info.endswith(develop_egg_link_egg_info), we + # are in fact in the develop_egg_link case paths_to_remove.add(dist.egg_info) if dist.has_metadata('installed-files.txt'): for installed_file in dist.get_metadata( @@ -621,9 +617,23 @@ exec(compile( 'easy-install.pth') paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg) + elif develop_egg_link: + # develop egg + with open(develop_egg_link, 'r') as fh: + link_pointer = os.path.normcase(fh.readline().strip()) + assert (link_pointer == dist.location), ( + 'Egg-link %s does not match installed location of %s ' + '(at %s)' % (link_pointer, self.name, dist.location) + ) + paths_to_remove.add(develop_egg_link) + easy_install_pth = os.path.join(os.path.dirname(develop_egg_link), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, dist.location) + elif egg_info_exists and dist.egg_info.endswith('.dist-info'): for path in pip.wheel.uninstallation_paths(dist): paths_to_remove.add(path) + else: logger.debug( 'Not sure how to uninstall: %s - Check: %s', diff --git a/tests/functional/test_uninstall.py b/tests/functional/test_uninstall.py index 431027a18..22c2d81fc 100644 --- a/tests/functional/test_uninstall.py +++ b/tests/functional/test_uninstall.py @@ -388,3 +388,24 @@ def test_uninstall_wheel(script, data): assert dist_info_folder in result.files_created result2 = script.pip('uninstall', 'simple.dist', '-y') assert_all_changes(result, result2, []) + + +def test_uninstall_setuptools_develop_install(script, data): + """Try uninstall after setup.py develop followed of setup.py install""" + pkg_path = data.packages.join("FSPkg") + script.run('python', 'setup.py', 'develop', + expect_stderr=True, cwd=pkg_path) + script.run('python', 'setup.py', 'install', + expect_stderr=True, cwd=pkg_path) + list_result = script.pip('list') + assert "FSPkg (0.1.dev0)" in list_result.stdout + # Uninstall both develop and install + uninstall = script.pip('uninstall', 'FSPkg', '-y') + assert any(filename.endswith('.egg') + for filename in uninstall.files_deleted.keys()) + uninstall2 = script.pip('uninstall', 'FSPkg', '-y') + assert join( + script.site_packages, 'FSPkg.egg-link' + ) in uninstall2.files_deleted, list(uninstall2.files_deleted.keys()) + list_result2 = script.pip('list') + assert "FSPkg" not in list_result2.stdout