shutil.py

Go to the documentation of this file.
00001 ##
00002 # Utility functions for copying files and directory trees on remote servers via sshUtils.
00003 # 
00004 # XXX The functions here don't copy the resource fork or other metadata on Mac.
00005 # 
00006 # 
00007 
00008 import sshUtils as os
00009 import sys
00010 import stat
00011 from os.path import abspath
00012 
00013 __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
00014            "copytree","move","rmtree","Error"]
00015 
00016 class Error(EnvironmentError):
00017     pass
00018 
00019 ##
00020 # copy data from file-like object fsrc to file-like object fdst
00021 def copyfileobj(fsrc, fdst, length=16*1024):
00022     while 1:
00023         buf = fsrc.read(length)
00024         if not buf:
00025             break
00026         fdst.write(buf)
00027 
00028 def _samefile(src, dst):
00029     # Macintosh, Unix.
00030     if hasattr(os.path,'samefile'):
00031         try:
00032             return os.path.samefile(src, dst)
00033         except OSError:
00034             return False
00035 
00036     # All other platforms: check for same pathname.
00037     return (os.path.normcase(os.path.abspath(src)) ==
00038             os.path.normcase(os.path.abspath(dst)))
00039 
00040 ##
00041 # Copy data from src to dst
00042 def copyfile(src, dst):
00043     if _samefile(src, dst):
00044         raise Error, "`%s` and `%s` are the same file" % (src, dst)
00045 
00046     fsrc = None
00047     fdst = None
00048     try:
00049         fsrc = open(src, 'rb')
00050         fdst = open(dst, 'wb')
00051         copyfileobj(fsrc, fdst)
00052     finally:
00053         if fdst:
00054             fdst.close()
00055         if fsrc:
00056             fsrc.close()
00057 
00058 ##
00059 # Copy mode bits from src to dst
00060 def copymode(src, dst):
00061     if hasattr(os, 'chmod'):
00062         st = os.stat(src)
00063         mode = stat.S_IMODE(st.st_mode)
00064         os.chmod(dst, mode)
00065 
00066 ##
00067 # Copy all stat info (mode bits, atime and mtime) from src to dst
00068 def copystat(src, dst):
00069     st = os.stat(src)
00070     mode = stat.S_IMODE(st.st_mode)
00071     if hasattr(os, 'utime'):
00072         os.utime(dst, (st.st_atime, st.st_mtime))
00073     if hasattr(os, 'chmod'):
00074         os.chmod(dst, mode)
00075 
00076 
00077 ##
00078 # Copy data and mode bits ("cp src dst").
00079 # 
00080 #     The destination may be a directory.
00081 # 
00082 #     
00083 def copy(src, dst):
00084     if os.path.isdir(dst):
00085         dst = os.path.join(dst, os.path.basename(src))
00086     copyfile(src, dst)
00087     copymode(src, dst)
00088 
00089 ##
00090 # Copy data and all stat info ("cp -p src dst").
00091 # 
00092 #     The destination may be a directory.
00093 # 
00094 #     
00095 def copy2(src, dst):
00096     if os.path.isdir(dst):
00097         dst = os.path.join(dst, os.path.basename(src))
00098     copyfile(src, dst)
00099     copystat(src, dst)
00100 
00101 
00102 ##
00103 # Recursively copy a directory tree using copy2().
00104 # 
00105 #     The destination directory must not already exist.
00106 #     If exception(s) occur, an Error is raised with a list of reasons.
00107 # 
00108 #     If the optional symlinks flag is true, symbolic links in the
00109 #     source tree result in symbolic links in the destination tree; if
00110 #     it is false, the contents of the files pointed to by symbolic
00111 #     links are copied.
00112 # 
00113 #     XXX Consider this example code rather than the ultimate tool.
00114 # 
00115 #     
00116 def copytree(src, dst, symlinks=False):
00117     names = os.listdir(src)
00118     os.makedirs(dst)
00119     errors = []
00120     for name in names:
00121         srcname = os.path.join(src, name)
00122         dstname = os.path.join(dst, name)
00123         try:
00124             if symlinks and os.path.islink(srcname):
00125                 linkto = os.readlink(srcname)
00126                 os.symlink(linkto, dstname)
00127             elif os.path.isdir(srcname):
00128                 copytree(srcname, dstname, symlinks)
00129             else:
00130                 copy2(srcname, dstname)
00131             # XXX What about devices, sockets etc.?
00132         except (IOError, os.error), why:
00133             errors.append((srcname, dstname, str(why)))
00134         # catch the Error from the recursive copytree so that we can
00135         # continue with other files
00136         except Error, err:
00137             errors.extend(err.args[0])
00138     try:
00139         copystat(src, dst)
00140     except WindowsError:
00141         # can't copy file access times on Windows
00142         pass
00143     except OSError, why:
00144         errors.extend((src, dst, str(why)))
00145     if errors:
00146         raise Error, errors
00147 
00148 ##
00149 # Recursively delete a directory tree.
00150 # 
00151 #     If ignore_errors is set, errors are ignored; otherwise, if onerror
00152 #     is set, it is called to handle the error with arguments (func,
00153 #     path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
00154 #     path is the argument to that function that caused it to fail; and
00155 #     exc_info is a tuple returned by sys.exc_info().  If ignore_errors
00156 #     is false and onerror is None, an exception is raised.
00157 # 
00158 #     
00159 def rmtree(path, ignore_errors=False, onerror=None):
00160     if ignore_errors:
00161         def onerror(*args):
00162             pass
00163     elif onerror is None:
00164         def onerror(*args):
00165             raise
00166     names = []
00167     try:
00168         names = os.listdir(path)
00169     except os.error, err:
00170         onerror(os.listdir, path, sys.exc_info())
00171     for name in names:
00172         fullname = os.path.join(path, name)
00173         try:
00174             mode = os.lstat(fullname).st_mode
00175         except os.error:
00176             mode = 0
00177         if stat.S_ISDIR(mode):
00178             rmtree(fullname, ignore_errors, onerror)
00179         else:
00180             try:
00181                 os.remove(fullname)
00182             except os.error, err:
00183                 onerror(os.remove, fullname, sys.exc_info())
00184     try:
00185         os.rmdir(path)
00186     except os.error:
00187         onerror(os.rmdir, path, sys.exc_info())
00188 
00189 ##
00190 # Recursively move a file or directory to another location.
00191 # 
00192 #     If the destination is on our current filesystem, then simply use
00193 #     rename.  Otherwise, copy src to the dst and then remove src.
00194 #     A lot more could be done here...  A look at a mv.c shows a lot of
00195 #     the issues this implementation glosses over.
00196 # 
00197 #     
00198 def move(src, dst):
00199 
00200     try:
00201         os.rename(src, dst)
00202     except OSError:
00203         if os.path.isdir(src):
00204             if destinsrc(src, dst):
00205                 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
00206             copytree(src, dst, symlinks=True)
00207             rmtree(src)
00208         else:
00209             copy2(src,dst)
00210             os.unlink(src)
00211 
00212 def destinsrc(src, dst):
00213     return abspath(dst).startswith(abspath(src))
00214 
00215 

© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved; If you reference this document or any part of this document you must use the citation verbatim (including the link) "© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved."

Notice: This source code contained in this document is NOT open source and is NOT being distributed as open source.

122,241 lines of code and growing...