symbian-qemu-0.9.1-12/python-2.6.1/Lib/distutils/file_util.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """distutils.file_util
       
     2 
       
     3 Utility functions for operating on single files.
       
     4 """
       
     5 
       
     6 # This module should be kept compatible with Python 2.1.
       
     7 
       
     8 __revision__ = "$Id: file_util.py 37828 2004-11-10 22:23:15Z loewis $"
       
     9 
       
    10 import os
       
    11 from distutils.errors import DistutilsFileError
       
    12 from distutils import log
       
    13 
       
    14 # for generating verbose output in 'copy_file()'
       
    15 _copy_action = { None:   'copying',
       
    16                  'hard': 'hard linking',
       
    17                  'sym':  'symbolically linking' }
       
    18 
       
    19 
       
    20 def _copy_file_contents (src, dst, buffer_size=16*1024):
       
    21     """Copy the file 'src' to 'dst'; both must be filenames.  Any error
       
    22     opening either file, reading from 'src', or writing to 'dst', raises
       
    23     DistutilsFileError.  Data is read/written in chunks of 'buffer_size'
       
    24     bytes (default 16k).  No attempt is made to handle anything apart from
       
    25     regular files.
       
    26     """
       
    27     # Stolen from shutil module in the standard library, but with
       
    28     # custom error-handling added.
       
    29 
       
    30     fsrc = None
       
    31     fdst = None
       
    32     try:
       
    33         try:
       
    34             fsrc = open(src, 'rb')
       
    35         except os.error, (errno, errstr):
       
    36             raise DistutilsFileError, \
       
    37                   "could not open '%s': %s" % (src, errstr)
       
    38 
       
    39         if os.path.exists(dst):
       
    40             try:
       
    41                 os.unlink(dst)
       
    42             except os.error, (errno, errstr):
       
    43                 raise DistutilsFileError, \
       
    44                       "could not delete '%s': %s" % (dst, errstr)
       
    45 
       
    46         try:
       
    47             fdst = open(dst, 'wb')
       
    48         except os.error, (errno, errstr):
       
    49             raise DistutilsFileError, \
       
    50                   "could not create '%s': %s" % (dst, errstr)
       
    51 
       
    52         while 1:
       
    53             try:
       
    54                 buf = fsrc.read(buffer_size)
       
    55             except os.error, (errno, errstr):
       
    56                 raise DistutilsFileError, \
       
    57                       "could not read from '%s': %s" % (src, errstr)
       
    58 
       
    59             if not buf:
       
    60                 break
       
    61 
       
    62             try:
       
    63                 fdst.write(buf)
       
    64             except os.error, (errno, errstr):
       
    65                 raise DistutilsFileError, \
       
    66                       "could not write to '%s': %s" % (dst, errstr)
       
    67 
       
    68     finally:
       
    69         if fdst:
       
    70             fdst.close()
       
    71         if fsrc:
       
    72             fsrc.close()
       
    73 
       
    74 # _copy_file_contents()
       
    75 
       
    76 def copy_file (src, dst,
       
    77                preserve_mode=1,
       
    78                preserve_times=1,
       
    79                update=0,
       
    80                link=None,
       
    81                verbose=0,
       
    82                dry_run=0):
       
    83 
       
    84     """Copy a file 'src' to 'dst'.  If 'dst' is a directory, then 'src' is
       
    85     copied there with the same name; otherwise, it must be a filename.  (If
       
    86     the file exists, it will be ruthlessly clobbered.)  If 'preserve_mode'
       
    87     is true (the default), the file's mode (type and permission bits, or
       
    88     whatever is analogous on the current platform) is copied.  If
       
    89     'preserve_times' is true (the default), the last-modified and
       
    90     last-access times are copied as well.  If 'update' is true, 'src' will
       
    91     only be copied if 'dst' does not exist, or if 'dst' does exist but is
       
    92     older than 'src'.
       
    93 
       
    94     'link' allows you to make hard links (os.link) or symbolic links
       
    95     (os.symlink) instead of copying: set it to "hard" or "sym"; if it is
       
    96     None (the default), files are copied.  Don't set 'link' on systems that
       
    97     don't support it: 'copy_file()' doesn't check if hard or symbolic
       
    98     linking is available.
       
    99 
       
   100     Under Mac OS, uses the native file copy function in macostools; on
       
   101     other systems, uses '_copy_file_contents()' to copy file contents.
       
   102 
       
   103     Return a tuple (dest_name, copied): 'dest_name' is the actual name of
       
   104     the output file, and 'copied' is true if the file was copied (or would
       
   105     have been copied, if 'dry_run' true).
       
   106     """
       
   107     # XXX if the destination file already exists, we clobber it if
       
   108     # copying, but blow up if linking.  Hmmm.  And I don't know what
       
   109     # macostools.copyfile() does.  Should definitely be consistent, and
       
   110     # should probably blow up if destination exists and we would be
       
   111     # changing it (ie. it's not already a hard/soft link to src OR
       
   112     # (not update) and (src newer than dst).
       
   113 
       
   114     from distutils.dep_util import newer
       
   115     from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE
       
   116 
       
   117     if not os.path.isfile(src):
       
   118         raise DistutilsFileError, \
       
   119               "can't copy '%s': doesn't exist or not a regular file" % src
       
   120 
       
   121     if os.path.isdir(dst):
       
   122         dir = dst
       
   123         dst = os.path.join(dst, os.path.basename(src))
       
   124     else:
       
   125         dir = os.path.dirname(dst)
       
   126 
       
   127     if update and not newer(src, dst):
       
   128         log.debug("not copying %s (output up-to-date)", src)
       
   129         return dst, 0
       
   130 
       
   131     try:
       
   132         action = _copy_action[link]
       
   133     except KeyError:
       
   134         raise ValueError, \
       
   135               "invalid value '%s' for 'link' argument" % link
       
   136     if os.path.basename(dst) == os.path.basename(src):
       
   137         log.info("%s %s -> %s", action, src, dir)
       
   138     else:
       
   139         log.info("%s %s -> %s", action, src, dst)
       
   140 
       
   141     if dry_run:
       
   142         return (dst, 1)
       
   143 
       
   144     # On Mac OS, use the native file copy routine
       
   145     if os.name == 'mac':
       
   146         import macostools
       
   147         try:
       
   148             macostools.copy(src, dst, 0, preserve_times)
       
   149         except os.error, exc:
       
   150             raise DistutilsFileError, \
       
   151                   "could not copy '%s' to '%s': %s" % (src, dst, exc[-1])
       
   152 
       
   153     # If linking (hard or symbolic), use the appropriate system call
       
   154     # (Unix only, of course, but that's the caller's responsibility)
       
   155     elif link == 'hard':
       
   156         if not (os.path.exists(dst) and os.path.samefile(src, dst)):
       
   157             os.link(src, dst)
       
   158     elif link == 'sym':
       
   159         if not (os.path.exists(dst) and os.path.samefile(src, dst)):
       
   160             os.symlink(src, dst)
       
   161 
       
   162     # Otherwise (non-Mac, not linking), copy the file contents and
       
   163     # (optionally) copy the times and mode.
       
   164     else:
       
   165         _copy_file_contents(src, dst)
       
   166         if preserve_mode or preserve_times:
       
   167             st = os.stat(src)
       
   168 
       
   169             # According to David Ascher <da@ski.org>, utime() should be done
       
   170             # before chmod() (at least under NT).
       
   171             if preserve_times:
       
   172                 os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
       
   173             if preserve_mode:
       
   174                 os.chmod(dst, S_IMODE(st[ST_MODE]))
       
   175 
       
   176     return (dst, 1)
       
   177 
       
   178 # copy_file ()
       
   179 
       
   180 
       
   181 # XXX I suspect this is Unix-specific -- need porting help!
       
   182 def move_file (src, dst,
       
   183                verbose=0,
       
   184                dry_run=0):
       
   185 
       
   186     """Move a file 'src' to 'dst'.  If 'dst' is a directory, the file will
       
   187     be moved into it with the same name; otherwise, 'src' is just renamed
       
   188     to 'dst'.  Return the new full name of the file.
       
   189 
       
   190     Handles cross-device moves on Unix using 'copy_file()'.  What about
       
   191     other systems???
       
   192     """
       
   193     from os.path import exists, isfile, isdir, basename, dirname
       
   194     import errno
       
   195 
       
   196     log.info("moving %s -> %s", src, dst)
       
   197 
       
   198     if dry_run:
       
   199         return dst
       
   200 
       
   201     if not isfile(src):
       
   202         raise DistutilsFileError, \
       
   203               "can't move '%s': not a regular file" % src
       
   204 
       
   205     if isdir(dst):
       
   206         dst = os.path.join(dst, basename(src))
       
   207     elif exists(dst):
       
   208         raise DistutilsFileError, \
       
   209               "can't move '%s': destination '%s' already exists" % \
       
   210               (src, dst)
       
   211 
       
   212     if not isdir(dirname(dst)):
       
   213         raise DistutilsFileError, \
       
   214               "can't move '%s': destination '%s' not a valid path" % \
       
   215               (src, dst)
       
   216 
       
   217     copy_it = 0
       
   218     try:
       
   219         os.rename(src, dst)
       
   220     except os.error, (num, msg):
       
   221         if num == errno.EXDEV:
       
   222             copy_it = 1
       
   223         else:
       
   224             raise DistutilsFileError, \
       
   225                   "couldn't move '%s' to '%s': %s" % (src, dst, msg)
       
   226 
       
   227     if copy_it:
       
   228         copy_file(src, dst)
       
   229         try:
       
   230             os.unlink(src)
       
   231         except os.error, (num, msg):
       
   232             try:
       
   233                 os.unlink(dst)
       
   234             except os.error:
       
   235                 pass
       
   236             raise DistutilsFileError, \
       
   237                   ("couldn't move '%s' to '%s' by copy/delete: " +
       
   238                    "delete '%s' failed: %s") % \
       
   239                   (src, dst, src, msg)
       
   240 
       
   241     return dst
       
   242 
       
   243 # move_file ()
       
   244 
       
   245 
       
   246 def write_file (filename, contents):
       
   247     """Create a file with the specified name and write 'contents' (a
       
   248     sequence of strings without line terminators) to it.
       
   249     """
       
   250     f = open(filename, "w")
       
   251     for line in contents:
       
   252         f.write(line + "\n")
       
   253     f.close()