PyXR

c:\python24\lib \ distutils \ dir_util.py



0001 """distutils.dir_util
0002 
0003 Utility functions for manipulating directories and directory trees."""
0004 
0005 # This module should be kept compatible with Python 1.5.2.
0006 
0007 __revision__ = "$Id: dir_util.py,v 1.14 2004/07/18 06:14:42 tim_one Exp $"
0008 
0009 import os, sys
0010 from types import *
0011 from distutils.errors import DistutilsFileError, DistutilsInternalError
0012 from distutils import log
0013 
0014 # cache for by mkpath() -- in addition to cheapening redundant calls,
0015 # eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
0016 _path_created = {}
0017 
0018 # I don't use os.makedirs because a) it's new to Python 1.5.2, and
0019 # b) it blows up if the directory already exists (I want to silently
0020 # succeed in that case).
0021 def mkpath (name, mode=0777, verbose=0, dry_run=0):
0022     """Create a directory and any missing ancestor directories.  If the
0023        directory already exists (or if 'name' is the empty string, which
0024        means the current directory, which of course exists), then do
0025        nothing.  Raise DistutilsFileError if unable to create some
0026        directory along the way (eg. some sub-path exists, but is a file
0027        rather than a directory).  If 'verbose' is true, print a one-line
0028        summary of each mkdir to stdout.  Return the list of directories
0029        actually created."""
0030 
0031     global _path_created
0032 
0033     # Detect a common bug -- name is None
0034     if type(name) is not StringType:
0035         raise DistutilsInternalError, \
0036               "mkpath: 'name' must be a string (got %r)" % (name,)
0037 
0038     # XXX what's the better way to handle verbosity? print as we create
0039     # each directory in the path (the current behaviour), or only announce
0040     # the creation of the whole path? (quite easy to do the latter since
0041     # we're not using a recursive algorithm)
0042 
0043     name = os.path.normpath(name)
0044     created_dirs = []
0045     if os.path.isdir(name) or name == '':
0046         return created_dirs
0047     if _path_created.get(os.path.abspath(name)):
0048         return created_dirs
0049 
0050     (head, tail) = os.path.split(name)
0051     tails = [tail]                      # stack of lone dirs to create
0052 
0053     while head and tail and not os.path.isdir(head):
0054         #print "splitting '%s': " % head,
0055         (head, tail) = os.path.split(head)
0056         #print "to ('%s','%s')" % (head, tail)
0057         tails.insert(0, tail)          # push next higher dir onto stack
0058 
0059     #print "stack of tails:", tails
0060 
0061     # now 'head' contains the deepest directory that already exists
0062     # (that is, the child of 'head' in 'name' is the highest directory
0063     # that does *not* exist)
0064     for d in tails:
0065         #print "head = %s, d = %s: " % (head, d),
0066         head = os.path.join(head, d)
0067         abs_head = os.path.abspath(head)
0068 
0069         if _path_created.get(abs_head):
0070             continue
0071 
0072         log.info("creating %s", head)
0073 
0074         if not dry_run:
0075             try:
0076                 os.mkdir(head)
0077                 created_dirs.append(head)
0078             except OSError, exc:
0079                 raise DistutilsFileError, \
0080                       "could not create '%s': %s" % (head, exc[-1])
0081 
0082         _path_created[abs_head] = 1
0083     return created_dirs
0084 
0085 # mkpath ()
0086 
0087 
0088 def create_tree (base_dir, files, mode=0777, verbose=0, dry_run=0):
0089 
0090     """Create all the empty directories under 'base_dir' needed to
0091        put 'files' there.  'base_dir' is just the a name of a directory
0092        which doesn't necessarily exist yet; 'files' is a list of filenames
0093        to be interpreted relative to 'base_dir'.  'base_dir' + the
0094        directory portion of every file in 'files' will be created if it
0095        doesn't already exist.  'mode', 'verbose' and 'dry_run' flags are as
0096        for 'mkpath()'."""
0097 
0098     # First get the list of directories to create
0099     need_dir = {}
0100     for file in files:
0101         need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
0102     need_dirs = need_dir.keys()
0103     need_dirs.sort()
0104 
0105     # Now create them
0106     for dir in need_dirs:
0107         mkpath(dir, mode, dry_run=dry_run)
0108 
0109 # create_tree ()
0110 
0111 
0112 def copy_tree (src, dst,
0113                preserve_mode=1,
0114                preserve_times=1,
0115                preserve_symlinks=0,
0116                update=0,
0117                verbose=0,
0118                dry_run=0):
0119 
0120     """Copy an entire directory tree 'src' to a new location 'dst'.  Both
0121        'src' and 'dst' must be directory names.  If 'src' is not a
0122        directory, raise DistutilsFileError.  If 'dst' does not exist, it is
0123        created with 'mkpath()'.  The end result of the copy is that every
0124        file in 'src' is copied to 'dst', and directories under 'src' are
0125        recursively copied to 'dst'.  Return the list of files that were
0126        copied or might have been copied, using their output name.  The
0127        return value is unaffected by 'update' or 'dry_run': it is simply
0128        the list of all files under 'src', with the names changed to be
0129        under 'dst'.
0130 
0131        'preserve_mode' and 'preserve_times' are the same as for
0132        'copy_file'; note that they only apply to regular files, not to
0133        directories.  If 'preserve_symlinks' is true, symlinks will be
0134        copied as symlinks (on platforms that support them!); otherwise
0135        (the default), the destination of the symlink will be copied.
0136        'update' and 'verbose' are the same as for 'copy_file'."""
0137 
0138     from distutils.file_util import copy_file
0139 
0140     if not dry_run and not os.path.isdir(src):
0141         raise DistutilsFileError, \
0142               "cannot copy tree '%s': not a directory" % src
0143     try:
0144         names = os.listdir(src)
0145     except os.error, (errno, errstr):
0146         if dry_run:
0147             names = []
0148         else:
0149             raise DistutilsFileError, \
0150                   "error listing files in '%s': %s" % (src, errstr)
0151 
0152     if not dry_run:
0153         mkpath(dst)
0154 
0155     outputs = []
0156 
0157     for n in names:
0158         src_name = os.path.join(src, n)
0159         dst_name = os.path.join(dst, n)
0160 
0161         if preserve_symlinks and os.path.islink(src_name):
0162             link_dest = os.readlink(src_name)
0163             log.info("linking %s -> %s", dst_name, link_dest)
0164             if not dry_run:
0165                 os.symlink(link_dest, dst_name)
0166             outputs.append(dst_name)
0167 
0168         elif os.path.isdir(src_name):
0169             outputs.extend(
0170                 copy_tree(src_name, dst_name, preserve_mode,
0171                           preserve_times, preserve_symlinks, update,
0172                           dry_run=dry_run))
0173         else:
0174             copy_file(src_name, dst_name, preserve_mode,
0175                       preserve_times, update, dry_run=dry_run)
0176             outputs.append(dst_name)
0177 
0178     return outputs
0179 
0180 # copy_tree ()
0181 
0182 # Helper for remove_tree()
0183 def _build_cmdtuple(path, cmdtuples):
0184     for f in os.listdir(path):
0185         real_f = os.path.join(path,f)
0186         if os.path.isdir(real_f) and not os.path.islink(real_f):
0187             _build_cmdtuple(real_f, cmdtuples)
0188         else:
0189             cmdtuples.append((os.remove, real_f))
0190     cmdtuples.append((os.rmdir, path))
0191 
0192 
0193 def remove_tree (directory, verbose=0, dry_run=0):
0194     """Recursively remove an entire directory tree.  Any errors are ignored
0195     (apart from being reported to stdout if 'verbose' is true).
0196     """
0197     from distutils.util import grok_environment_error
0198     global _path_created
0199 
0200     log.info("removing '%s' (and everything under it)", directory)
0201     if dry_run:
0202         return
0203     cmdtuples = []
0204     _build_cmdtuple(directory, cmdtuples)
0205     for cmd in cmdtuples:
0206         try:
0207             apply(cmd[0], (cmd[1],))
0208             # remove dir from cache if it's already there
0209             abspath = os.path.abspath(cmd[1])
0210             if _path_created.has_key(abspath):
0211                 del _path_created[abspath]
0212         except (IOError, OSError), exc:
0213             log.warn(grok_environment_error(
0214                     exc, "error removing %s: " % directory))
0215 
0216 
0217 def ensure_relative (path):
0218     """Take the full path 'path', and make it a relative path so
0219     it can be the second argument to os.path.join().
0220     """
0221     drive, path = os.path.splitdrive(path)
0222     if sys.platform == 'mac':
0223         return os.sep + path
0224     else:
0225         if path[0:1] == os.sep:
0226             path = drive + path[1:]
0227         return path
0228 

Generated by PyXR 0.9.4
SourceForge.net Logo