]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/distutils/dir_util.py
   3 Utility functions for manipulating directories and directory trees.""" 
   5 # This module should be kept compatible with Python 1.5.2. 
  11 from distutils
.errors 
import DistutilsFileError
, DistutilsInternalError
 
  12 from distutils 
import log
 
  14 # cache for by mkpath() -- in addition to cheapening redundant calls, 
  15 # eliminates redundant "creating /foo/bar/baz" messages in dry-run mode 
  18 # I don't use os.makedirs because a) it's new to Python 1.5.2, and 
  19 # b) it blows up if the directory already exists (I want to silently 
  20 # succeed in that case). 
  21 def mkpath (name
, mode
=0777, verbose
=0, dry_run
=0): 
  22     """Create a directory and any missing ancestor directories.  If the 
  23        directory already exists (or if 'name' is the empty string, which 
  24        means the current directory, which of course exists), then do 
  25        nothing.  Raise DistutilsFileError if unable to create some 
  26        directory along the way (eg. some sub-path exists, but is a file 
  27        rather than a directory).  If 'verbose' is true, print a one-line 
  28        summary of each mkdir to stdout.  Return the list of directories 
  33     # Detect a common bug -- name is None 
  34     if type(name
) is not StringType
: 
  35         raise DistutilsInternalError
, \
 
  36               "mkpath: 'name' must be a string (got %s)" % `name`
 
  38     # XXX what's the better way to handle verbosity? print as we create 
  39     # each directory in the path (the current behaviour), or only announce 
  40     # the creation of the whole path? (quite easy to do the latter since 
  41     # we're not using a recursive algorithm) 
  43     name 
= os
.path
.normpath(name
) 
  45     if os
.path
.isdir(name
) or name 
== '': 
  47     if _path_created
.get(os
.path
.abspath(name
)): 
  50     (head
, tail
) = os
.path
.split(name
) 
  51     tails 
= [tail
]                      # stack of lone dirs to create 
  53     while head 
and tail 
and not os
.path
.isdir(head
): 
  54         #print "splitting '%s': " % head, 
  55         (head
, tail
) = os
.path
.split(head
) 
  56         #print "to ('%s','%s')" % (head, tail) 
  57         tails
.insert(0, tail
)          # push next higher dir onto stack 
  59     #print "stack of tails:", tails 
  61     # now 'head' contains the deepest directory that already exists 
  62     # (that is, the child of 'head' in 'name' is the highest directory 
  63     # that does *not* exist) 
  65         #print "head = %s, d = %s: " % (head, d), 
  66         head 
= os
.path
.join(head
, d
) 
  67         abs_head 
= os
.path
.abspath(head
) 
  69         if _path_created
.get(abs_head
): 
  72         log
.info("creating %s", head
) 
  77                 created_dirs
.append(head
) 
  79                 raise DistutilsFileError
, \
 
  80                       "could not create '%s': %s" % (head
, exc
[-1]) 
  82         _path_created
[abs_head
] = 1 
  88 def create_tree (base_dir
, files
, mode
=0777, verbose
=0, dry_run
=0): 
  90     """Create all the empty directories under 'base_dir' needed to 
  91        put 'files' there.  'base_dir' is just the a name of a directory 
  92        which doesn't necessarily exist yet; 'files' is a list of filenames 
  93        to be interpreted relative to 'base_dir'.  'base_dir' + the 
  94        directory portion of every file in 'files' will be created if it 
  95        doesn't already exist.  'mode', 'verbose' and 'dry_run' flags are as 
  98     # First get the list of directories to create 
 101         need_dir
[os
.path
.join(base_dir
, os
.path
.dirname(file))] = 1 
 102     need_dirs 
= need_dir
.keys() 
 106     for dir in need_dirs
: 
 107         mkpath(dir, mode
, dry_run
=dry_run
) 
 112 def copy_tree (src
, dst
, 
 120     """Copy an entire directory tree 'src' to a new location 'dst'.  Both 
 121        'src' and 'dst' must be directory names.  If 'src' is not a 
 122        directory, raise DistutilsFileError.  If 'dst' does not exist, it is 
 123        created with 'mkpath()'.  The end result of the copy is that every 
 124        file in 'src' is copied to 'dst', and directories under 'src' are 
 125        recursively copied to 'dst'.  Return the list of files that were 
 126        copied or might have been copied, using their output name.  The 
 127        return value is unaffected by 'update' or 'dry_run': it is simply 
 128        the list of all files under 'src', with the names changed to be 
 131        'preserve_mode' and 'preserve_times' are the same as for 
 132        'copy_file'; note that they only apply to regular files, not to 
 133        directories.  If 'preserve_symlinks' is true, symlinks will be 
 134        copied as symlinks (on platforms that support them!); otherwise 
 135        (the default), the destination of the symlink will be copied. 
 136        'update' and 'verbose' are the same as for 'copy_file'.""" 
 138     from distutils
.file_util 
import copy_file
 
 140     if not dry_run 
and not os
.path
.isdir(src
): 
 141         raise DistutilsFileError
, \
 
 142               "cannot copy tree '%s': not a directory" % src
 
 144         names 
= os
.listdir(src
) 
 145     except os
.error
, (errno
, errstr
): 
 149             raise DistutilsFileError
, \
 
 150                   "error listing files in '%s': %s" % (src
, errstr
) 
 158         src_name 
= os
.path
.join(src
, n
) 
 159         dst_name 
= os
.path
.join(dst
, n
) 
 161         if preserve_symlinks 
and os
.path
.islink(src_name
): 
 162             link_dest 
= os
.readlink(src_name
) 
 163             log
.info("linking %s -> %s", dst_name
, link_dest
) 
 165                 os
.symlink(link_dest
, dst_name
) 
 166             outputs
.append(dst_name
) 
 168         elif os
.path
.isdir(src_name
): 
 170                 copy_tree(src_name
, dst_name
, preserve_mode
, 
 171                           preserve_times
, preserve_symlinks
, update
, 
 174             copy_file(src_name
, dst_name
, preserve_mode
, 
 175                       preserve_times
, update
, dry_run
=dry_run
) 
 176             outputs
.append(dst_name
) 
 182 # Helper for remove_tree() 
 183 def _build_cmdtuple(path
, cmdtuples
): 
 184     for f 
in os
.listdir(path
): 
 185         real_f 
= os
.path
.join(path
,f
) 
 186         if os
.path
.isdir(real_f
) and not os
.path
.islink(real_f
): 
 187             _build_cmdtuple(real_f
, cmdtuples
) 
 189             cmdtuples
.append((os
.remove
, real_f
)) 
 190     cmdtuples
.append((os
.rmdir
, path
)) 
 193 def remove_tree (directory
, verbose
=0, dry_run
=0): 
 194     """Recursively remove an entire directory tree.  Any errors are ignored 
 195     (apart from being reported to stdout if 'verbose' is true). 
 197     from distutils
.util 
import grok_environment_error
 
 200     log
.info("removing '%s' (and everything under it)", directory
) 
 204     _build_cmdtuple(directory
, cmdtuples
) 
 205     for cmd 
in cmdtuples
: 
 207             apply(cmd
[0], (cmd
[1],)) 
 208             # remove dir from cache if it's already there 
 209             abspath 
= os
.path
.abspath(cmd
[1]) 
 210             if _path_created
.has_key(abspath
): 
 211                 del _path_created
[abspath
] 
 212         except (IOError, OSError), exc
: 
 213             log
.warn(grok_environment_error( 
 214                     exc
, "error removing %s: " % directory
)) 
 217 def ensure_relative (path
): 
 218     """Take the full path 'path', and make it a relative path so 
 219     it can be the second argument to os.path.join(). 
 221     drive
, path 
= os
.path
.splitdrive(path
) 
 222     if sys
.platform 
== 'mac': 
 225         if path
[0:1] == os
.sep
: 
 226             path 
= drive 
+ path
[1:]