[Python-checkins] distutils2: Merge with upstream.
tarek.ziade
python-checkins at python.org
Wed Feb 16 22:23:58 CET 2011
tarek.ziade pushed b61e8db532cd to distutils2:
http://hg.python.org/distutils2/rev/b61e8db532cd
changeset: 1067:b61e8db532cd
parent: 1066:e4474c0740d7
parent: 985:22028f4d78bc
user: FELD Boris <lothiraldan at gmail.com>
date: Sun Jan 30 18:35:07 2011 +0100
summary:
Merge with upstream.
files:
distutils2/_backport/pkgutil.py
distutils2/util.py
diff --git a/distutils2/_backport/pkgutil.py b/distutils2/_backport/pkgutil.py
--- a/distutils2/_backport/pkgutil.py
+++ b/distutils2/_backport/pkgutil.py
@@ -7,6 +7,13 @@
import warnings
from csv import reader as csv_reader
from types import ModuleType
+from stat import ST_SIZE
+
+try:
+ from hashlib import md5
+except ImportError:
+ from md5 import md5
+
from distutils2.errors import DistutilsError
from distutils2.index.errors import DistributionNotFound
from distutils2.metadata import DistributionMetadata
@@ -979,6 +986,33 @@
return '%s-%s at %s' % (self.name, self.metadata.version, self.path)
def get_installed_files(self, local=False):
+
+ def _md5(path):
+ f = open(path)
+ try:
+ content = f.read()
+ finally:
+ f.close()
+ return md5(content).hexdigest()
+
+ def _size(path):
+ return os.stat(path)[ST_SIZE]
+
+ path = self.path
+ if local:
+ path = path.replace('/', os.sep)
+
+ # XXX What about scripts and data files ?
+ if os.path.isfile(path):
+ return [(path, _md5(path), _size(path))]
+ else:
+ files = []
+ for root, dir, files_ in os.walk(path):
+ for item in files_:
+ item = os.path.join(root, item)
+ files.append((item, _md5(item), _size(item)))
+ return files
+
return []
def uses(self, path):
diff --git a/distutils2/install.py b/distutils2/install.py
--- a/distutils2/install.py
+++ b/distutils2/install.py
@@ -334,37 +334,65 @@
def remove(project_name, paths=sys.path):
"""Removes a single project from the installation"""
- dist = get_distribution(project_name, paths=paths)
+ dist = get_distribution(project_name, use_egg_info=True, paths=paths)
if dist is None:
- raise DistutilsError('Distribution %s not found' % project_name)
+ raise DistutilsError('Distribution "%s" not found' % project_name)
files = dist.get_installed_files(local=True)
rmdirs = []
rmfiles = []
tmp = tempfile.mkdtemp(prefix=project_name + '-uninstall')
try:
- for file, md5, size in files:
- if os.path.isfile(file):
- dirname, filename = os.path.split(file)
+ 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)
+ os.rename(file_, tmpfile)
finally:
- if not os.path.isfile(file):
- os.rename(tmpfile, file)
- if file not in rmfiles:
- rmfiles.append(file)
+ if not os.path.isfile(file_):
+ os.rename(tmpfile, file_)
+ if file_ not in rmfiles:
+ rmfiles.append(file_)
if dirname not in rmdirs:
rmdirs.append(dirname)
finally:
shutil.rmtree(tmp)
- for file in rmfiles:
- os.remove(file)
+ logger.info('Removing %r...' % project_name)
+ file_count = 0
+ for file_ in rmfiles:
+ os.remove(file_)
+ file_count +=1
+
+ dir_count = 0
for dirname in rmdirs:
- if not os.listdir(dirname):
- if bool(os.stat(dirname).st_mode & stat.S_IWUSR):
- os.rmdir(dirname)
+ if not os.path.exists(dirname):
+ # could
+ continue
+
+ files_count = 0
+ for root, dir, files in os.walk(dirname):
+ files_count += len(files)
+
+ if files_count > 0:
+ # XXX Warning
+ continue
+
+ # empty dirs with only empty dirs
+ if bool(os.stat(dirname).st_mode & stat.S_IWUSR):
+ # XXX Add a callable in shutil.rmtree to count
+ # the number of deleted elements
+ shutil.rmtree(dirname)
+ dir_count += 1
+
+ # removing the top path
+ # XXX count it ?
+ if os.path.exists(dist.path):
+ shutil.rmtree(dist.path)
+
+ logger.info('Success ! Removed %d files and %d dirs' % \
+ (file_count, dir_count))
def install(project):
diff --git a/distutils2/run.py b/distutils2/run.py
--- a/distutils2/run.py
+++ b/distutils2/run.py
@@ -11,7 +11,7 @@
from distutils2 import __version__
from distutils2._backport.pkgutil import get_distributions, get_distribution
from distutils2.depgraph import generate_graph
-from distutils2.install import install
+from distutils2.install import install, remove
# This is a barebones help message generated displayed when the user
# runs the setup script with no arguments at all. More useful help
@@ -225,6 +225,10 @@
install(options.install)
return 0
+ if options.remove is not None:
+ remove(options.remove)
+ return 0
+
if len(args) == 0:
parser.print_help()
return 0
diff --git a/distutils2/tests/test_util.py b/distutils2/tests/test_util.py
--- a/distutils2/tests/test_util.py
+++ b/distutils2/tests/test_util.py
@@ -414,6 +414,10 @@
@unittest.skipUnless(os.name in ('nt', 'posix'),
'runs only under posix or nt')
def test_spawn(self):
+ # Do not patch subprocess on unix because
+ # distutils2.util._spawn_posix uses it
+ if os.name in 'posix':
+ subprocess.Popen = self.old_popen
tmpdir = self.mkdtemp()
# creating something executable
diff --git a/distutils2/util.py b/distutils2/util.py
--- a/distutils2/util.py
+++ b/distutils2/util.py
@@ -12,6 +12,7 @@
import shutil
import tarfile
import zipfile
+from subprocess import call as sub_call
from copy import copy
from fnmatch import fnmatchcase
from glob import iglob as std_iglob
@@ -801,65 +802,17 @@
"command '%s' failed with exit status %d" % (cmd[0], rc))
-def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0, env=None):
- logger.info(' '.join(cmd))
+def _spawn_posix(cmd, search_path=1, verbose=1, dry_run=0, env=None):
+ cmd = ' '.join(cmd)
+ if verbose:
+ logger.info(cmd)
+ logger.info(env)
if dry_run:
return
-
- if env is None:
- exec_fn = search_path and os.execvp or os.execv
- else:
- exec_fn = search_path and os.execvpe or os.execve
-
- pid = os.fork()
-
- if pid == 0: # in the child
- try:
- if env is None:
- exec_fn(cmd[0], cmd)
- else:
- exec_fn(cmd[0], cmd, env)
- except OSError, e:
- sys.stderr.write("unable to execute %s: %s\n" %
- (cmd[0], e.strerror))
- os._exit(1)
-
- sys.stderr.write("unable to execute %s for unknown reasons" % cmd[0])
- os._exit(1)
- else: # in the parent
- # Loop until the child either exits or is terminated by a signal
- # (ie. keep waiting if it's merely stopped)
- while 1:
- try:
- pid, status = os.waitpid(pid, 0)
- except OSError, exc:
- import errno
- if exc.errno == errno.EINTR:
- continue
- raise DistutilsExecError(
- "command '%s' failed: %s" % (cmd[0], exc[-1]))
- if os.WIFSIGNALED(status):
- raise DistutilsExecError(
- "command '%s' terminated by signal %d" % \
- (cmd[0], os.WTERMSIG(status)))
-
- elif os.WIFEXITED(status):
- exit_status = os.WEXITSTATUS(status)
- if exit_status == 0:
- return # hey, it succeeded!
- else:
- raise DistutilsExecError(
- "command '%s' failed with exit status %d" % \
- (cmd[0], exit_status))
-
- elif os.WIFSTOPPED(status):
- continue
-
- else:
- raise DistutilsExecError(
- "unknown error executing '%s': termination status %d" % \
- (cmd[0], status))
-
+ exit_status = sub_call(cmd, shell=True, env=env)
+ if exit_status != 0:
+ msg = "command '%s' failed with exit status %d"
+ raise DistutilsExecError(msg % (cmd, exit_status))
def find_executable(executable, path=None):
"""Tries to find 'executable' in the directories listed in 'path'.
--
Repository URL: http://hg.python.org/distutils2
More information about the Python-checkins
mailing list