[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