summaryrefslogtreecommitdiffstats
path: root/Lib/packaging
diff options
context:
space:
mode:
authorTarek Ziade <tarek@ziade.org>2011-05-30 21:26:51 (GMT)
committerTarek Ziade <tarek@ziade.org>2011-05-30 21:26:51 (GMT)
commitf47fa58b62e6702f840625bff9fc8a07cef3408f (patch)
treec15db8280b00b1601f884756ec966cb840e91fd5 /Lib/packaging
parent58ab76696536b63f588f10eeb165deae6c0e4624 (diff)
downloadcpython-f47fa58b62e6702f840625bff9fc8a07cef3408f.zip
cpython-f47fa58b62e6702f840625bff9fc8a07cef3408f.tar.gz
cpython-f47fa58b62e6702f840625bff9fc8a07cef3408f.tar.bz2
better UI when the user does not have the perms to remove the project
Diffstat (limited to 'Lib/packaging')
-rw-r--r--Lib/packaging/install.py27
-rw-r--r--Lib/packaging/tests/test_uninstall.py28
2 files changed, 48 insertions, 7 deletions
diff --git a/Lib/packaging/install.py b/Lib/packaging/install.py
index cd2bbb6..9f94532 100644
--- a/Lib/packaging/install.py
+++ b/Lib/packaging/install.py
@@ -376,7 +376,10 @@ def _remove_dist(dist, paths=sys.path):
def remove(project_name, paths=sys.path, auto_confirm=True):
- """Removes a single project from the installation"""
+ """Removes a single project from the installation.
+
+ Returns True on success
+ """
dist = get_distribution(project_name, use_egg_info=True, paths=paths)
if dist is None:
raise PackagingError('Distribution "%s" not found' % project_name)
@@ -384,13 +387,26 @@ def remove(project_name, paths=sys.path, auto_confirm=True):
rmdirs = []
rmfiles = []
tmp = tempfile.mkdtemp(prefix=project_name + '-uninstall')
+
+ def _move_file(source, target):
+ try:
+ os.rename(source, target)
+ except OSError as err:
+ return err
+ return None
+
+ success = True
+ error = None
try:
for file_, md5, size in files:
if os.path.isfile(file_):
dirname, filename = os.path.split(file_)
tmpfile = os.path.join(tmp, filename)
try:
- os.rename(file_, tmpfile)
+ error = _move_file(file_, tmpfile)
+ if error is not None:
+ success = False
+ break
finally:
if not os.path.isfile(file_):
os.rename(tmpfile, file_)
@@ -401,6 +417,11 @@ def remove(project_name, paths=sys.path, auto_confirm=True):
finally:
shutil.rmtree(tmp)
+ if not success:
+ logger.info('%r cannot be removed.', project_name)
+ logger.info('Error: %s' % str(error))
+ return False
+
logger.info('Removing %r: ', project_name)
for file_ in rmfiles:
@@ -447,6 +468,8 @@ def remove(project_name, paths=sys.path, auto_confirm=True):
logger.info('Success: removed %d files and %d dirs',
file_count, dir_count)
+ return True
+
def install(project):
logger.info('Getting information about %r...', project)
diff --git a/Lib/packaging/tests/test_uninstall.py b/Lib/packaging/tests/test_uninstall.py
index 45ce4ca..4b37286 100644
--- a/Lib/packaging/tests/test_uninstall.py
+++ b/Lib/packaging/tests/test_uninstall.py
@@ -2,6 +2,7 @@
import os
import sys
from io import StringIO
+import stat
from packaging.database import disable_cache, enable_cache
from packaging.run import main
@@ -82,10 +83,7 @@ class UninstallTestCase(support.TempdirManager,
os.chdir(dirname)
old_out = sys.stderr
sys.stderr = StringIO()
- try:
- dist = self.run_setup('install_dist', '--prefix=' + self.root_dir)
- finally:
- sys.stderr = old_out
+ dist = self.run_setup('install_dist', '--prefix=' + self.root_dir)
install_lib = self.get_path(dist, 'purelib')
return dist, install_lib
@@ -99,10 +97,30 @@ class UninstallTestCase(support.TempdirManager,
self.assertIsFile(install_lib, 'foo', '__init__.py')
self.assertIsFile(install_lib, 'foo', 'sub', '__init__.py')
self.assertIsFile(install_lib, 'Foo-0.1.dist-info', 'RECORD')
- remove('Foo', paths=[install_lib])
+ self.assertTrue(remove('Foo', paths=[install_lib]))
self.assertIsNotFile(install_lib, 'foo', 'sub', '__init__.py')
self.assertIsNotFile(install_lib, 'Foo-0.1.dist-info', 'RECORD')
+ @unittest.skipIf(sys.platform == 'win32', 'deactivated for now')
+ def test_remove_issue(self):
+ # makes sure if there are OSErrors (like permission denied)
+ # remove() stops and display a clean error
+ dist, install_lib = self.install_dist('Meh')
+
+ # breaking os.rename
+ old = os.rename
+
+ def _rename(source, target):
+ raise OSError()
+
+ os.rename = _rename
+ try:
+ self.assertFalse(remove('Meh', paths=[install_lib]))
+ finally:
+ os.rename = old
+
+ self.assertTrue(remove('Meh', paths=[install_lib]))
+
def test_suite():
return unittest.makeSuite(UninstallTestCase)