pip/tests/functional/test_uninstall.py

231 lines
10 KiB
Python
Raw Normal View History

from __future__ import with_statement
import textwrap
2013-01-23 05:52:35 +01:00
import os
import sys
from os.path import join, abspath, normpath
2010-02-24 11:24:55 +01:00
from tempfile import mkdtemp
from mock import patch
from tests.lib import assert_all_changes, pyversion
from tests.lib.local_repos import local_repo, local_checkout
2010-02-24 11:24:55 +01:00
from pip.util import rmtree
def test_simple_uninstall(script):
"""
Test simple install and uninstall.
"""
result = script.pip('install', 'INITools==0.2')
assert join(script.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
script.run('python', '-c', "import initools")
result2 = script.pip('uninstall', 'INITools', '-y')
assert_all_changes(result, result2, [script.venv/'build', 'cache'])
2010-02-24 11:24:55 +01:00
def test_uninstall_with_scripts(script):
"""
Uninstall an easy_installed package with scripts.
"""
result = script.run('easy_install', 'PyLogo', expect_stderr=True)
easy_install_pth = script.site_packages/ 'easy-install.pth'
pylogo = sys.platform == 'win32' and 'pylogo' or 'PyLogo'
assert(pylogo in result.files_updated[easy_install_pth].bytes)
result2 = script.pip('uninstall', 'pylogo', '-y')
assert_all_changes(result, result2, [script.venv/'build', 'cache', easy_install_pth])
2010-02-24 11:24:55 +01:00
def test_uninstall_easy_install_after_import(script):
2012-08-19 00:26:17 +02:00
"""
Uninstall an easy_installed package after it's been imported
"""
result = script.run('easy_install', 'INITools==0.2', expect_stderr=True)
2012-08-19 00:26:17 +02:00
#the import forces the generation of __pycache__ if the version of python supports it
script.run('python', '-c', "import initools")
result2 = script.pip('uninstall', 'INITools', '-y')
assert_all_changes(result, result2, [script.venv/'build', 'cache', script.site_packages/'easy-install.pth'])
2012-08-19 00:26:17 +02:00
def test_uninstall_namespace_package(script):
"""
2010-02-24 11:24:55 +01:00
Uninstall a distribution with a namespace package without clobbering
the namespace and everything in it.
"""
result = script.pip('install', 'pd.requires==0.0.3', expect_error=True)
assert join(script.site_packages, 'pd') in result.files_created, sorted(result.files_created.keys())
result2 = script.pip('uninstall', 'pd.find', '-y', expect_error=True)
assert join(script.site_packages, 'pd') not in result2.files_deleted, sorted(result2.files_deleted.keys())
assert join(script.site_packages, 'pd', 'find') in result2.files_deleted, sorted(result2.files_deleted.keys())
2010-02-24 11:24:55 +01:00
def test_uninstall_overlapping_package(script, data):
2012-07-09 09:04:46 +02:00
"""
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 = data.packages.join("parent-0.1.tar.gz")
child_pkg = data.packages.join("child-0.1.tar.gz")
result1 = script.pip('install', parent_pkg, expect_error=False)
assert join(script.site_packages, 'parent') in result1.files_created, sorted(result1.files_created.keys())
result2 = script.pip('install', child_pkg, expect_error=False)
assert join(script.site_packages, 'child') in result2.files_created, sorted(result2.files_created.keys())
assert normpath(join(script.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
script.run('python', '-c', "import parent.plugins.child_plugin, child")
result3 = script.pip('uninstall', '-y', 'child', expect_error=False)
assert join(script.site_packages, 'child') in result3.files_deleted, sorted(result3.files_created.keys())
assert normpath(join(script.site_packages, 'parent/plugins/child_plugin.py')) in result3.files_deleted, sorted(result3.files_deleted.keys())
assert join(script.site_packages, 'parent') not in result3.files_deleted, sorted(result3.files_deleted.keys())
2012-07-09 09:04:46 +02:00
# Additional check: uninstalling 'child' should return things to the
# previous state, without unintended side effects.
assert_all_changes(result2, result3, [])
def test_uninstall_console_scripts(script):
"""
Test uninstalling a package with more files (console_script entry points, extra directories).
"""
2011-03-15 20:49:48 +01:00
args = ['install']
args.append('discover')
result = script.pip(*args, **{"expect_error": True})
assert script.bin/'discover'+script.exe in result.files_created, sorted(result.files_created.keys())
result2 = script.pip('uninstall', 'discover', '-y', expect_error=True)
assert_all_changes(result, result2, [script.venv/'build', 'cache'])
2010-02-24 11:24:55 +01:00
def test_uninstall_easy_installed_console_scripts(script):
"""
Test uninstalling package with console_scripts that is easy_installed.
"""
2011-03-15 20:49:48 +01:00
args = ['easy_install']
args.append('discover')
result = script.run(*args, **{"expect_stderr": True})
assert script.bin/'discover'+script.exe in result.files_created, sorted(result.files_created.keys())
result2 = script.pip('uninstall', 'discover', '-y')
assert_all_changes(result, result2, [script.venv/'build', 'cache', script.site_packages/'easy-install.pth'])
2010-02-24 11:24:55 +01:00
def test_uninstall_editable_from_svn(script, tmpdir):
"""
Test uninstalling an editable installation from svn.
"""
result = script.pip('install', '-e', '%s#egg=initools-dev' %
local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache")))
result.assert_installed('INITools')
result2 = script.pip('uninstall', '-y', 'initools')
assert (script.venv/'src'/'initools' in result2.files_after), 'oh noes, pip deleted my sources!'
assert_all_changes(result, result2, [script.venv/'src', script.venv/'build', script.site_packages/'easy-install.pth'])
2010-02-24 11:24:55 +01:00
def test_uninstall_editable_with_source_outside_venv(script, tmpdir):
"""
Test uninstalling editable install from existing source outside the venv.
"""
cache_dir = tmpdir.join("cache")
try:
temp = mkdtemp()
tmpdir = join(temp, 'virtualenv')
_test_uninstall_editable_with_source_outside_venv(script, tmpdir, cache_dir)
finally:
rmtree(temp)
def _test_uninstall_editable_with_source_outside_venv(script, tmpdir, cache_dir):
result = script.run('git', 'clone', local_repo('git+git://github.com/pypa/virtualenv', cache_dir), tmpdir, expect_stderr=True)
result2 = script.pip('install', '-e', tmpdir)
assert (join(script.site_packages, 'virtualenv.egg-link') in result2.files_created), list(result2.files_created.keys())
result3 = script.pip('uninstall', '-y', 'virtualenv', expect_error=True)
assert_all_changes(result, result3, [script.venv/'build', script.site_packages/'easy-install.pth'])
def test_uninstall_from_reqs_file(script, tmpdir):
"""
Test uninstall from a requirements file.
"""
script.scratch_path.join("test-req.txt").write(textwrap.dedent("""\
-e %s#egg=initools-dev
2010-02-24 11:24:55 +01:00
# and something else to test out:
PyLogo<0.4
""" % local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache"))))
result = script.pip('install', '-r', 'test-req.txt')
script.scratch_path.join("test-req.txt").write(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
-e %s#egg=initools-dev
# and something else to test out:
PyLogo<0.4
""" % local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache"))))
result2 = script.pip('uninstall', '-r', 'test-req.txt', '-y')
assert_all_changes(
result, result2, [script.venv/'build', script.venv/'src', script.scratch/'test-req.txt',
script.site_packages/'easy-install.pth'])
2012-05-22 12:54:40 +02:00
def test_uninstall_as_egg(script, data):
2012-05-22 12:54:40 +02:00
"""
Test uninstall package installed as egg.
"""
to_install = data.packages.join("FSPkg")
result = script.pip('install', to_install, '--egg', expect_error=False)
fspkg_folder = script.site_packages/'fspkg'
egg_folder = script.site_packages/'FSPkg-0.1dev-py%s.egg' % pyversion
2012-05-22 12:54:40 +02:00
assert fspkg_folder not in result.files_created, str(result.stdout)
assert egg_folder in result.files_created, str(result)
result2 = script.pip('uninstall', 'FSPkg', '-y', expect_error=True)
assert_all_changes(result, result2, [script.venv/'build', 'cache', script.site_packages/'easy-install.pth'])
2012-05-22 12:54:40 +02:00
@patch('pip.req.req_uninstall.logger')
2012-09-03 19:55:29 +02:00
def test_uninstallpathset_no_paths(mock_logger):
"""
2012-09-04 21:40:50 +02:00
Test UninstallPathSet logs notification when there are no paths to uninstall
"""
from pip.req.req_uninstall import UninstallPathSet
2012-09-03 19:55:29 +02:00
from pkg_resources import get_distribution
test_dist = get_distribution('pip')
# ensure that the distribution is "local"
with patch("pip.req.req_uninstall.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.req_uninstall.logger')
2012-09-04 21:40:50 +02:00
def test_uninstallpathset_non_local(mock_logger):
"""
Test UninstallPathSet logs notification and returns (with no exception) when dist is non-local
"""
2013-01-23 05:52:35 +01:00
nonlocal_path = os.path.abspath("/nonlocal")
from pip.req.req_uninstall import UninstallPathSet
2012-09-04 21:40:50 +02:00
from pkg_resources import get_distribution
test_dist = get_distribution('pip')
2013-01-23 05:52:35 +01:00
test_dist.location = nonlocal_path
# 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.req_uninstall.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
2013-01-23 05:52:35 +01:00
mock_logger.notify.assert_any_call("Not uninstalling pip at %s, outside environment %s" % (nonlocal_path, sys.prefix)), mock_logger.notify.mock_calls