2012-09-07 18:32:45 +02:00
|
|
|
from __future__ import with_statement
|
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
import textwrap
|
|
|
|
import sys
|
2012-07-29 11:40:14 +02:00
|
|
|
from os.path import join, abspath, normpath
|
2010-02-24 11:24:55 +01:00
|
|
|
from tempfile import mkdtemp
|
2012-09-07 18:32:45 +02:00
|
|
|
from mock import patch
|
2012-05-22 12:54:40 +02:00
|
|
|
from tests.test_pip import here, reset_env, run_pip, assert_all_changes, write_file, pyversion
|
2011-03-15 20:49:48 +01:00
|
|
|
from tests.local_repos import local_repo, local_checkout
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2011-03-20 16:52:54 +01:00
|
|
|
from pip.util import rmtree
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2011-05-04 09:44:02 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_simple_uninstall():
|
|
|
|
"""
|
|
|
|
Test simple install and uninstall.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2012-06-14 06:00:10 +02:00
|
|
|
result = run_pip('install', 'INITools==0.2')
|
2010-04-15 01:33:32 +02:00
|
|
|
assert join(env.site_packages, 'initools') in result.files_created, sorted(result.files_created.keys())
|
2012-08-19 00:26:17 +02:00
|
|
|
#the import forces the generation of __pycache__ if the version of python supports it
|
|
|
|
env.run('python', '-c', "import initools")
|
2012-06-14 06:00:10 +02:00
|
|
|
result2 = run_pip('uninstall', 'INITools', '-y')
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_with_scripts():
|
|
|
|
"""
|
|
|
|
Uninstall an easy_installed package with scripts.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2010-06-06 05:35:00 +02:00
|
|
|
result = env.run('easy_install', 'PyLogo', expect_stderr=True)
|
2010-04-15 01:33:32 +02:00
|
|
|
easy_install_pth = env.site_packages/ 'easy-install.pth'
|
2010-05-26 14:06:27 +02:00
|
|
|
pylogo = sys.platform == 'win32' and 'pylogo' or 'PyLogo'
|
2010-05-03 04:08:03 +02:00
|
|
|
assert(pylogo in result.files_updated[easy_install_pth].bytes)
|
2010-02-24 11:24:55 +01:00
|
|
|
result2 = run_pip('uninstall', 'pylogo', '-y', expect_error=True)
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2012-08-19 00:26:17 +02:00
|
|
|
def test_uninstall_easy_install_after_import():
|
|
|
|
"""
|
|
|
|
Uninstall an easy_installed package after it's been imported
|
|
|
|
|
|
|
|
"""
|
|
|
|
env = reset_env()
|
|
|
|
result = env.run('easy_install', 'INITools==0.2', expect_stderr=True)
|
|
|
|
#the import forces the generation of __pycache__ if the version of python supports it
|
|
|
|
env.run('python', '-c', "import initools")
|
|
|
|
result2 = run_pip('uninstall', 'INITools', '-y')
|
|
|
|
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
|
|
|
|
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_namespace_package():
|
|
|
|
"""
|
2010-02-24 11:24:55 +01:00
|
|
|
Uninstall a distribution with a namespace package without clobbering
|
2010-02-25 00:16:43 +01:00
|
|
|
the namespace and everything in it.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2010-02-24 11:24:55 +01:00
|
|
|
result = run_pip('install', 'pd.requires==0.0.3', expect_error=True)
|
2010-04-15 01:33:32 +02:00
|
|
|
assert join(env.site_packages, 'pd') in result.files_created, sorted(result.files_created.keys())
|
2010-02-24 11:24:55 +01:00
|
|
|
result2 = run_pip('uninstall', 'pd.find', '-y', expect_error=True)
|
2010-04-15 01:33:32 +02:00
|
|
|
assert join(env.site_packages, 'pd') not in result2.files_deleted, sorted(result2.files_deleted.keys())
|
|
|
|
assert join(env.site_packages, 'pd', 'find') in result2.files_deleted, sorted(result2.files_deleted.keys())
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2012-07-09 09:04:46 +02:00
|
|
|
def test_uninstall_overlapping_package():
|
|
|
|
"""
|
|
|
|
Uninstalling a distribution that adds modules to a pre-existing package
|
|
|
|
should only remove those added modules, not the rest of the existing
|
|
|
|
package.
|
|
|
|
|
|
|
|
See: GitHub issue #355 (pip uninstall removes things it didn't install)
|
|
|
|
"""
|
|
|
|
parent_pkg = abspath(join(here, 'packages', 'parent-0.1.tar.gz'))
|
|
|
|
child_pkg = abspath(join(here, 'packages', 'child-0.1.tar.gz'))
|
|
|
|
env = reset_env()
|
|
|
|
result1 = run_pip('install', parent_pkg, expect_error=False)
|
|
|
|
assert join(env.site_packages, 'parent') in result1.files_created, sorted(result1.files_created.keys())
|
|
|
|
result2 = run_pip('install', child_pkg, expect_error=False)
|
|
|
|
assert join(env.site_packages, 'child') in result2.files_created, sorted(result2.files_created.keys())
|
2012-07-29 11:40:14 +02:00
|
|
|
assert normpath(join(env.site_packages, 'parent/plugins/child_plugin.py')) in result2.files_created, sorted(result2.files_created.keys())
|
2012-08-19 00:26:17 +02:00
|
|
|
#the import forces the generation of __pycache__ if the version of python supports it
|
|
|
|
env.run('python', '-c', "import parent.plugins.child_plugin, child")
|
2012-07-09 09:04:46 +02:00
|
|
|
result3 = run_pip('uninstall', '-y', 'child', expect_error=False)
|
|
|
|
assert join(env.site_packages, 'child') in result3.files_deleted, sorted(result3.files_created.keys())
|
2012-07-29 11:40:14 +02:00
|
|
|
assert normpath(join(env.site_packages, 'parent/plugins/child_plugin.py')) in result3.files_deleted, sorted(result3.files_deleted.keys())
|
2012-07-09 09:04:46 +02:00
|
|
|
assert join(env.site_packages, 'parent') not in result3.files_deleted, sorted(result3.files_deleted.keys())
|
|
|
|
# Additional check: uninstalling 'child' should return things to the
|
|
|
|
# previous state, without unintended side effects.
|
|
|
|
assert_all_changes(result2, result3, [])
|
|
|
|
|
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_console_scripts():
|
|
|
|
"""
|
|
|
|
Test uninstalling a package with more files (console_script entry points, extra directories).
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2011-03-15 20:49:48 +01:00
|
|
|
args = ['install']
|
2011-03-19 06:54:04 +01:00
|
|
|
args.append('discover')
|
2011-03-19 19:40:06 +01:00
|
|
|
result = run_pip(*args, **{"expect_error": True})
|
2011-03-19 06:54:04 +01:00
|
|
|
assert env.bin/'discover'+env.exe in result.files_created, sorted(result.files_created.keys())
|
|
|
|
result2 = run_pip('uninstall', 'discover', '-y', expect_error=True)
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_easy_installed_console_scripts():
|
|
|
|
"""
|
|
|
|
Test uninstalling package with console_scripts that is easy_installed.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2011-03-15 20:49:48 +01:00
|
|
|
args = ['easy_install']
|
2011-03-19 06:54:04 +01:00
|
|
|
args.append('discover')
|
2011-03-19 19:40:06 +01:00
|
|
|
result = env.run(*args, **{"expect_stderr": True})
|
2011-03-19 06:54:04 +01:00
|
|
|
assert env.bin/'discover'+env.exe in result.files_created, sorted(result.files_created.keys())
|
|
|
|
result2 = run_pip('uninstall', 'discover', '-y')
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_editable_from_svn():
|
|
|
|
"""
|
|
|
|
Test uninstalling an editable installation from svn.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2010-06-22 00:48:28 +02:00
|
|
|
result = run_pip('install', '-e', '%s#egg=initools-dev' %
|
|
|
|
local_checkout('svn+http://svn.colorstudy.com/INITools/trunk'))
|
2010-04-28 22:55:10 +02:00
|
|
|
result.assert_installed('INITools')
|
|
|
|
result2 = run_pip('uninstall', '-y', 'initools')
|
2010-05-02 20:11:45 +02:00
|
|
|
assert (env.venv/'src'/'initools' in result2.files_after), 'oh noes, pip deleted my sources!'
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(result, result2, [env.venv/'src', env.venv/'build'])
|
2010-02-24 11:24:55 +01:00
|
|
|
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_editable_with_source_outside_venv():
|
|
|
|
"""
|
|
|
|
Test uninstalling editable install from existing source outside the venv.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-09-13 07:21:10 +02:00
|
|
|
try:
|
|
|
|
temp = mkdtemp()
|
|
|
|
tmpdir = join(temp, 'virtualenv')
|
|
|
|
_test_uninstall_editable_with_source_outside_venv(tmpdir)
|
|
|
|
finally:
|
2011-03-19 20:57:37 +01:00
|
|
|
rmtree(temp)
|
2010-09-13 07:21:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
def _test_uninstall_editable_with_source_outside_venv(tmpdir):
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2011-03-19 06:54:04 +01:00
|
|
|
result = env.run('git', 'clone', local_repo('git+git://github.com/pypa/virtualenv'), tmpdir)
|
2010-02-24 11:24:55 +01:00
|
|
|
result2 = run_pip('install', '-e', tmpdir)
|
2011-03-15 20:49:48 +01:00
|
|
|
assert (join(env.site_packages, 'virtualenv.egg-link') in result2.files_created), list(result2.files_created.keys())
|
2010-02-24 11:24:55 +01:00
|
|
|
result3 = run_pip('uninstall', '-y', 'virtualenv', expect_error=True)
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(result, result3, [env.venv/'build'])
|
2010-06-03 04:25:26 +02:00
|
|
|
|
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
def test_uninstall_from_reqs_file():
|
|
|
|
"""
|
|
|
|
Test uninstall from a requirements file.
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-02-25 00:16:43 +01:00
|
|
|
"""
|
2010-04-15 01:33:32 +02:00
|
|
|
env = reset_env()
|
2010-02-25 00:16:43 +01:00
|
|
|
write_file('test-req.txt', textwrap.dedent("""\
|
2010-06-22 00:48:28 +02:00
|
|
|
-e %s#egg=initools-dev
|
2010-02-24 11:24:55 +01:00
|
|
|
# and something else to test out:
|
|
|
|
PyLogo<0.4
|
2010-06-22 00:48:28 +02:00
|
|
|
""" % local_checkout('svn+http://svn.colorstudy.com/INITools/trunk')))
|
2010-02-24 11:24:55 +01:00
|
|
|
result = run_pip('install', '-r', 'test-req.txt')
|
2010-04-16 17:53:04 +02:00
|
|
|
write_file('test-req.txt', textwrap.dedent("""\
|
|
|
|
# -f, -i, and --extra-index-url should all be ignored by uninstall
|
|
|
|
-f http://www.example.com
|
|
|
|
-i http://www.example.com
|
|
|
|
--extra-index-url http://www.example.com
|
2010-06-03 04:25:26 +02:00
|
|
|
|
2010-06-22 00:48:28 +02:00
|
|
|
-e %s#egg=initools-dev
|
2010-04-16 17:53:04 +02:00
|
|
|
# and something else to test out:
|
|
|
|
PyLogo<0.4
|
2010-06-22 00:48:28 +02:00
|
|
|
""" % local_checkout('svn+http://svn.colorstudy.com/INITools/trunk')))
|
2010-02-24 11:24:55 +01:00
|
|
|
result2 = run_pip('uninstall', '-r', 'test-req.txt', '-y')
|
2010-05-03 04:08:03 +02:00
|
|
|
assert_all_changes(
|
|
|
|
result, result2, [env.venv/'build', env.venv/'src', env.scratch/'test-req.txt'])
|
2012-05-22 12:54:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_uninstall_as_egg():
|
|
|
|
"""
|
|
|
|
Test uninstall package installed as egg.
|
|
|
|
|
|
|
|
"""
|
|
|
|
env = reset_env()
|
|
|
|
to_install = abspath(join(here, 'packages', 'FSPkg'))
|
|
|
|
result = run_pip('install', to_install, '--egg', expect_error=False)
|
|
|
|
fspkg_folder = env.site_packages/'fspkg'
|
|
|
|
egg_folder = env.site_packages/'FSPkg-0.1dev-py%s.egg' % pyversion
|
|
|
|
assert fspkg_folder not in result.files_created, str(result.stdout)
|
|
|
|
assert egg_folder in result.files_created, str(result)
|
|
|
|
|
|
|
|
result2 = run_pip('uninstall', 'FSPkg', '-y', expect_error=True)
|
|
|
|
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
|
|
|
|
2012-06-26 07:35:27 +02:00
|
|
|
|
2012-09-03 19:55:29 +02:00
|
|
|
@patch('pip.req.logger')
|
|
|
|
def test_uninstallpathset_no_paths(mock_logger):
|
2012-06-26 07:35:27 +02:00
|
|
|
"""
|
2012-09-04 21:40:50 +02:00
|
|
|
Test UninstallPathSet logs notification when there are no paths to uninstall
|
2012-06-26 07:35:27 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
from pip.req import UninstallPathSet
|
2012-09-03 19:55:29 +02:00
|
|
|
from pkg_resources import get_distribution
|
|
|
|
test_dist = get_distribution('pip')
|
2012-09-07 18:32:45 +02:00
|
|
|
# ensure that the distribution is "local"
|
|
|
|
with patch("pip.req.dist_is_local") as mock_dist_is_local:
|
|
|
|
mock_dist_is_local.return_value = True
|
|
|
|
uninstall_set = UninstallPathSet(test_dist)
|
|
|
|
uninstall_set.remove() #with no files added to set
|
2012-09-03 19:55:29 +02:00
|
|
|
mock_logger.notify.assert_any_call("Can't uninstall 'pip'. No files were found to uninstall.")
|
|
|
|
|
2012-09-04 21:40:50 +02:00
|
|
|
|
|
|
|
@patch('pip.req.logger')
|
|
|
|
def test_uninstallpathset_non_local(mock_logger):
|
|
|
|
"""
|
|
|
|
Test UninstallPathSet logs notification and returns (with no exception) when dist is non-local
|
|
|
|
|
|
|
|
"""
|
|
|
|
from pip.req import UninstallPathSet
|
|
|
|
from pkg_resources import get_distribution
|
|
|
|
test_dist = get_distribution('pip')
|
2012-09-07 18:32:45 +02:00
|
|
|
test_dist.location = "/NON_LOCAL"
|
|
|
|
# ensure that the distribution is "non-local"
|
|
|
|
# setting location isn't enough, due to egg-link file checking for
|
|
|
|
# develop-installs
|
|
|
|
with patch("pip.req.dist_is_local") as mock_dist_is_local:
|
|
|
|
mock_dist_is_local.return_value = False
|
|
|
|
uninstall_set = UninstallPathSet(test_dist)
|
|
|
|
uninstall_set.remove() #with no files added to set; which is the case when trying to remove non-local dists
|
2012-09-04 21:40:50 +02:00
|
|
|
mock_logger.notify.assert_any_call("Not uninstalling pip at /NON_LOCAL, outside environment %s" % sys.prefix)
|
|
|
|
|
|
|
|
|
|
|
|
|