symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/shutil.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Utility functions for copying files and directory trees.
       
     2 
       
     3 XXX The functions here don't copy the resource fork or other metadata on Mac.
       
     4 
       
     5 """
       
     6 
       
     7 import os
       
     8 import sys
       
     9 import stat
       
    10 from os.path import abspath
       
    11 import fnmatch
       
    12 
       
    13 __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
       
    14            "copytree","move","rmtree","Error"]
       
    15 
       
    16 class Error(EnvironmentError):
       
    17     pass
       
    18 
       
    19 try:
       
    20     WindowsError
       
    21 except NameError:
       
    22     WindowsError = None
       
    23 
       
    24 def copyfileobj(fsrc, fdst, length=16*1024):
       
    25     """copy data from file-like object fsrc to file-like object fdst"""
       
    26     while 1:
       
    27         buf = fsrc.read(length)
       
    28         if not buf:
       
    29             break
       
    30         fdst.write(buf)
       
    31 
       
    32 def _samefile(src, dst):
       
    33     # Macintosh, Unix.
       
    34     if hasattr(os.path,'samefile'):
       
    35         try:
       
    36             return os.path.samefile(src, dst)
       
    37         except OSError:
       
    38             return False
       
    39 
       
    40     # All other platforms: check for same pathname.
       
    41     return (os.path.normcase(os.path.abspath(src)) ==
       
    42             os.path.normcase(os.path.abspath(dst)))
       
    43 
       
    44 def copyfile(src, dst):
       
    45     """Copy data from src to dst"""
       
    46     if _samefile(src, dst):
       
    47         raise Error, "`%s` and `%s` are the same file" % (src, dst)
       
    48 
       
    49     fsrc = None
       
    50     fdst = None
       
    51     try:
       
    52         fsrc = open(src, 'rb')
       
    53         fdst = open(dst, 'wb')
       
    54         copyfileobj(fsrc, fdst)
       
    55     finally:
       
    56         if fdst:
       
    57             fdst.close()
       
    58         if fsrc:
       
    59             fsrc.close()
       
    60 
       
    61 def copymode(src, dst):
       
    62     """Copy mode bits from src to dst"""
       
    63     if hasattr(os, 'chmod'):
       
    64         st = os.stat(src)
       
    65         mode = stat.S_IMODE(st.st_mode)
       
    66         os.chmod(dst, mode)
       
    67 
       
    68 def copystat(src, dst):
       
    69     """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
       
    70     st = os.stat(src)
       
    71     mode = stat.S_IMODE(st.st_mode)
       
    72     if hasattr(os, 'utime'):
       
    73         os.utime(dst, (st.st_atime, st.st_mtime))
       
    74     if hasattr(os, 'chmod'):
       
    75         os.chmod(dst, mode)
       
    76     if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
       
    77         os.chflags(dst, st.st_flags)
       
    78 
       
    79 
       
    80 def copy(src, dst):
       
    81     """Copy data and mode bits ("cp src dst").
       
    82 
       
    83     The destination may be a directory.
       
    84 
       
    85     """
       
    86     if os.path.isdir(dst):
       
    87         dst = os.path.join(dst, os.path.basename(src))
       
    88     copyfile(src, dst)
       
    89     copymode(src, dst)
       
    90 
       
    91 def copy2(src, dst):
       
    92     """Copy data and all stat info ("cp -p src dst").
       
    93 
       
    94     The destination may be a directory.
       
    95 
       
    96     """
       
    97     if os.path.isdir(dst):
       
    98         dst = os.path.join(dst, os.path.basename(src))
       
    99     copyfile(src, dst)
       
   100     copystat(src, dst)
       
   101 
       
   102 def ignore_patterns(*patterns):
       
   103     """Function that can be used as copytree() ignore parameter.
       
   104 
       
   105     Patterns is a sequence of glob-style patterns
       
   106     that are used to exclude files"""
       
   107     def _ignore_patterns(path, names):
       
   108         ignored_names = []
       
   109         for pattern in patterns:
       
   110             ignored_names.extend(fnmatch.filter(names, pattern))
       
   111         return set(ignored_names)
       
   112     return _ignore_patterns
       
   113 
       
   114 def copytree(src, dst, symlinks=False, ignore=None):
       
   115     """Recursively copy a directory tree using copy2().
       
   116 
       
   117     The destination directory must not already exist.
       
   118     If exception(s) occur, an Error is raised with a list of reasons.
       
   119 
       
   120     If the optional symlinks flag is true, symbolic links in the
       
   121     source tree result in symbolic links in the destination tree; if
       
   122     it is false, the contents of the files pointed to by symbolic
       
   123     links are copied.
       
   124 
       
   125     The optional ignore argument is a callable. If given, it
       
   126     is called with the `src` parameter, which is the directory
       
   127     being visited by copytree(), and `names` which is the list of
       
   128     `src` contents, as returned by os.listdir():
       
   129 
       
   130         callable(src, names) -> ignored_names
       
   131 
       
   132     Since copytree() is called recursively, the callable will be
       
   133     called once for each directory that is copied. It returns a
       
   134     list of names relative to the `src` directory that should
       
   135     not be copied.
       
   136 
       
   137     XXX Consider this example code rather than the ultimate tool.
       
   138 
       
   139     """
       
   140     names = os.listdir(src)
       
   141     if ignore is not None:
       
   142         ignored_names = ignore(src, names)
       
   143     else:
       
   144         ignored_names = set()
       
   145 
       
   146     os.makedirs(dst)
       
   147     errors = []
       
   148     for name in names:
       
   149         if name in ignored_names:
       
   150             continue
       
   151         srcname = os.path.join(src, name)
       
   152         dstname = os.path.join(dst, name)
       
   153         try:
       
   154             if symlinks and os.path.islink(srcname):
       
   155                 linkto = os.readlink(srcname)
       
   156                 os.symlink(linkto, dstname)
       
   157             elif os.path.isdir(srcname):
       
   158                 copytree(srcname, dstname, symlinks, ignore)
       
   159             else:
       
   160                 copy2(srcname, dstname)
       
   161             # XXX What about devices, sockets etc.?
       
   162         except (IOError, os.error), why:
       
   163             errors.append((srcname, dstname, str(why)))
       
   164         # catch the Error from the recursive copytree so that we can
       
   165         # continue with other files
       
   166         except Error, err:
       
   167             errors.extend(err.args[0])
       
   168     try:
       
   169         copystat(src, dst)
       
   170     except OSError, why:
       
   171         if WindowsError is not None and isinstance(why, WindowsError):
       
   172             # Copying file access times may fail on Windows
       
   173             pass
       
   174         else:
       
   175             errors.extend((src, dst, str(why)))
       
   176     if errors:
       
   177         raise Error, errors
       
   178 
       
   179 def rmtree(path, ignore_errors=False, onerror=None):
       
   180     """Recursively delete a directory tree.
       
   181 
       
   182     If ignore_errors is set, errors are ignored; otherwise, if onerror
       
   183     is set, it is called to handle the error with arguments (func,
       
   184     path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
       
   185     path is the argument to that function that caused it to fail; and
       
   186     exc_info is a tuple returned by sys.exc_info().  If ignore_errors
       
   187     is false and onerror is None, an exception is raised.
       
   188 
       
   189     """
       
   190     if ignore_errors:
       
   191         def onerror(*args):
       
   192             pass
       
   193     elif onerror is None:
       
   194         def onerror(*args):
       
   195             raise
       
   196     try:
       
   197         if os.path.islink(path):
       
   198             # symlinks to directories are forbidden, see bug #1669
       
   199             raise OSError("Cannot call rmtree on a symbolic link")
       
   200     except OSError:
       
   201         onerror(os.path.islink, path, sys.exc_info())
       
   202         # can't continue even if onerror hook returns
       
   203         return
       
   204     names = []
       
   205     try:
       
   206         names = os.listdir(path)
       
   207     except os.error, err:
       
   208         onerror(os.listdir, path, sys.exc_info())
       
   209     for name in names:
       
   210         fullname = os.path.join(path, name)
       
   211         try:
       
   212             mode = os.lstat(fullname).st_mode
       
   213         except os.error:
       
   214             mode = 0
       
   215         if stat.S_ISDIR(mode):
       
   216             rmtree(fullname, ignore_errors, onerror)
       
   217         else:
       
   218             try:
       
   219                 os.remove(fullname)
       
   220             except os.error, err:
       
   221                 onerror(os.remove, fullname, sys.exc_info())
       
   222     try:
       
   223         os.rmdir(path)
       
   224     except os.error:
       
   225         onerror(os.rmdir, path, sys.exc_info())
       
   226 
       
   227 
       
   228 def _basename(path):
       
   229     # A basename() variant which first strips the trailing slash, if present.
       
   230     # Thus we always get the last component of the path, even for directories.
       
   231     return os.path.basename(path.rstrip(os.path.sep))
       
   232 
       
   233 def move(src, dst):
       
   234     """Recursively move a file or directory to another location. This is
       
   235     similar to the Unix "mv" command.
       
   236 
       
   237     If the destination is a directory or a symlink to a directory, the source
       
   238     is moved inside the directory. The destination path must not already
       
   239     exist.
       
   240 
       
   241     If the destination already exists but is not a directory, it may be
       
   242     overwritten depending on os.rename() semantics.
       
   243 
       
   244     If the destination is on our current filesystem, then rename() is used.
       
   245     Otherwise, src is copied to the destination and then removed.
       
   246     A lot more could be done here...  A look at a mv.c shows a lot of
       
   247     the issues this implementation glosses over.
       
   248 
       
   249     """
       
   250     real_dst = dst
       
   251     if os.path.isdir(dst):
       
   252         real_dst = os.path.join(dst, _basename(src))
       
   253         if os.path.exists(real_dst):
       
   254             raise Error, "Destination path '%s' already exists" % real_dst
       
   255     try:
       
   256         os.rename(src, real_dst)
       
   257     except OSError:
       
   258         if os.path.isdir(src):
       
   259             if destinsrc(src, dst):
       
   260                 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
       
   261             copytree(src, real_dst, symlinks=True)
       
   262             rmtree(src)
       
   263         else:
       
   264             copy2(src, real_dst)
       
   265             os.unlink(src)
       
   266 
       
   267 def destinsrc(src, dst):
       
   268     return abspath(dst).startswith(abspath(src))