PyXR

c:\python24\lib \ shutil.py



0001 """Utility functions for copying files and directory trees.
0002 
0003 XXX The functions here don't copy the resource fork or other metadata on Mac.
0004 
0005 """
0006 
0007 import os
0008 import sys
0009 import stat
0010 import exceptions
0011 from os.path import abspath
0012 
0013 __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
0014            "copytree","move","rmtree","Error"]
0015 
0016 class Error(exceptions.EnvironmentError):
0017     pass
0018 
0019 def copyfileobj(fsrc, fdst, length=16*1024):
0020     """copy data from file-like object fsrc to file-like object fdst"""
0021     while 1:
0022         buf = fsrc.read(length)
0023         if not buf:
0024             break
0025         fdst.write(buf)
0026 
0027 def _samefile(src, dst):
0028     # Macintosh, Unix.
0029     if hasattr(os.path,'samefile'):
0030         try:
0031             return os.path.samefile(src, dst)
0032         except OSError:
0033             return False
0034 
0035     # All other platforms: check for same pathname.
0036     return (os.path.normcase(os.path.abspath(src)) ==
0037             os.path.normcase(os.path.abspath(dst)))
0038 
0039 def copyfile(src, dst):
0040     """Copy data from src to dst"""
0041     if _samefile(src, dst):
0042         raise Error, "`%s` and `%s` are the same file" % (src, dst)
0043 
0044     fsrc = None
0045     fdst = None
0046     try:
0047         fsrc = open(src, 'rb')
0048         fdst = open(dst, 'wb')
0049         copyfileobj(fsrc, fdst)
0050     finally:
0051         if fdst:
0052             fdst.close()
0053         if fsrc:
0054             fsrc.close()
0055 
0056 def copymode(src, dst):
0057     """Copy mode bits from src to dst"""
0058     if hasattr(os, 'chmod'):
0059         st = os.stat(src)
0060         mode = stat.S_IMODE(st.st_mode)
0061         os.chmod(dst, mode)
0062 
0063 def copystat(src, dst):
0064     """Copy all stat info (mode bits, atime and mtime) from src to dst"""
0065     st = os.stat(src)
0066     mode = stat.S_IMODE(st.st_mode)
0067     if hasattr(os, 'utime'):
0068         os.utime(dst, (st.st_atime, st.st_mtime))
0069     if hasattr(os, 'chmod'):
0070         os.chmod(dst, mode)
0071 
0072 
0073 def copy(src, dst):
0074     """Copy data and mode bits ("cp src dst").
0075 
0076     The destination may be a directory.
0077 
0078     """
0079     if os.path.isdir(dst):
0080         dst = os.path.join(dst, os.path.basename(src))
0081     copyfile(src, dst)
0082     copymode(src, dst)
0083 
0084 def copy2(src, dst):
0085     """Copy data and all stat info ("cp -p src dst").
0086 
0087     The destination may be a directory.
0088 
0089     """
0090     if os.path.isdir(dst):
0091         dst = os.path.join(dst, os.path.basename(src))
0092     copyfile(src, dst)
0093     copystat(src, dst)
0094 
0095 
0096 def copytree(src, dst, symlinks=False):
0097     """Recursively copy a directory tree using copy2().
0098 
0099     The destination directory must not already exist.
0100     If exception(s) occur, an Error is raised with a list of reasons.
0101 
0102     If the optional symlinks flag is true, symbolic links in the
0103     source tree result in symbolic links in the destination tree; if
0104     it is false, the contents of the files pointed to by symbolic
0105     links are copied.
0106 
0107     XXX Consider this example code rather than the ultimate tool.
0108 
0109     """
0110     names = os.listdir(src)
0111     os.mkdir(dst)
0112     errors = []
0113     for name in names:
0114         srcname = os.path.join(src, name)
0115         dstname = os.path.join(dst, name)
0116         try:
0117             if symlinks and os.path.islink(srcname):
0118                 linkto = os.readlink(srcname)
0119                 os.symlink(linkto, dstname)
0120             elif os.path.isdir(srcname):
0121                 copytree(srcname, dstname, symlinks)
0122             else:
0123                 copy2(srcname, dstname)
0124             # XXX What about devices, sockets etc.?
0125         except (IOError, os.error), why:
0126             errors.append((srcname, dstname, why))
0127     if errors:
0128         raise Error, errors
0129 
0130 def rmtree(path, ignore_errors=False, onerror=None):
0131     """Recursively delete a directory tree.
0132 
0133     If ignore_errors is set, errors are ignored; otherwise, if onerror
0134     is set, it is called to handle the error with arguments (func,
0135     path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
0136     path is the argument to that function that caused it to fail; and
0137     exc_info is a tuple returned by sys.exc_info().  If ignore_errors
0138     is false and onerror is None, an exception is raised.
0139 
0140     """
0141     if ignore_errors:
0142         def onerror(*args):
0143             pass
0144     elif onerror is None:
0145         def onerror(*args):
0146             raise
0147     names = []
0148     try:
0149         names = os.listdir(path)
0150     except os.error, err:
0151         onerror(os.listdir, path, sys.exc_info())
0152     for name in names:
0153         fullname = os.path.join(path, name)
0154         try:
0155             mode = os.lstat(fullname).st_mode
0156         except os.error:
0157             mode = 0
0158         if stat.S_ISDIR(mode):
0159             rmtree(fullname, ignore_errors, onerror)
0160         else:
0161             try:
0162                 os.remove(fullname)
0163             except os.error, err:
0164                 onerror(os.remove, fullname, sys.exc_info())
0165     try:
0166         os.rmdir(path)
0167     except os.error:
0168         onerror(os.rmdir, path, sys.exc_info())
0169 
0170 def move(src, dst):
0171     """Recursively move a file or directory to another location.
0172 
0173     If the destination is on our current filesystem, then simply use
0174     rename.  Otherwise, copy src to the dst and then remove src.
0175     A lot more could be done here...  A look at a mv.c shows a lot of
0176     the issues this implementation glosses over.
0177 
0178     """
0179 
0180     try:
0181         os.rename(src, dst)
0182     except OSError:
0183         if os.path.isdir(src):
0184             if destinsrc(src, dst):
0185                 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
0186             copytree(src, dst, symlinks=True)
0187             rmtree(src)
0188         else:
0189             copy2(src,dst)
0190             os.unlink(src)
0191 
0192 def destinsrc(src, dst):
0193     return abspath(dst).startswith(abspath(src))
0194 

Generated by PyXR 0.9.4
SourceForge.net Logo