diff options
Diffstat (limited to 'Lib/shutil.py')
| -rw-r--r-- | Lib/shutil.py | 114 | 
1 files changed, 57 insertions, 57 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py index d767a0c..3f4b6bf 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -7,7 +7,6 @@ XXX The functions here don't copy the resource fork or other metadata on Mac.  import os  import sys  import stat -from os.path import abspath  import fnmatch  import collections  import errno @@ -21,6 +20,13 @@ except ImportError:      _BZ2_SUPPORTED = False  try: +    import lzma +    del lzma +    _LZMA_SUPPORTED = True +except ImportError: +    _LZMA_SUPPORTED = False + +try:      from pwd import getpwnam  except ImportError:      getpwnam = None @@ -491,7 +497,7 @@ def _basename(path):      sep = os.path.sep + (os.path.altsep or '')      return os.path.basename(path.rstrip(sep)) -def move(src, dst): +def move(src, dst, copy_function=copy2):      """Recursively move a file or directory to another location. This is      similar to the Unix "mv" command. Return the file or directory's      destination. @@ -508,6 +514,11 @@ def move(src, dst):      recreated under the new name if os.rename() fails because of cross      filesystem renames. +    The optional `copy_function` argument is a callable that will be used +    to copy the source or it will be delegated to `copytree`. +    By default, copy2() is used, but any function that supports the same +    signature (like copy()) can be used. +      A lot more could be done here...  A look at a mv.c shows a lot of      the issues this implementation glosses over. @@ -532,17 +543,19 @@ def move(src, dst):              os.unlink(src)          elif os.path.isdir(src):              if _destinsrc(src, dst): -                raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) -            copytree(src, real_dst, symlinks=True) +                raise Error("Cannot move a directory '%s' into itself" +                            " '%s'." % (src, dst)) +            copytree(src, real_dst, copy_function=copy_function, +                     symlinks=True)              rmtree(src)          else: -            copy2(src, real_dst) +            copy_function(src, real_dst)              os.unlink(src)      return real_dst  def _destinsrc(src, dst): -    src = abspath(src) -    dst = abspath(dst) +    src = os.path.abspath(src) +    dst = os.path.abspath(dst)      if not src.endswith(os.path.sep):          src += os.path.sep      if not dst.endswith(os.path.sep): @@ -578,14 +591,14 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,      """Create a (possibly compressed) tar file from all the files under      'base_dir'. -    'compress' must be "gzip" (the default), "bzip2", or None. +    'compress' must be "gzip" (the default), "bzip2", "xz", or None.      'owner' and 'group' can be used to define an owner and a group for the      archive that is being built. If not provided, the current owner and group      will be used.      The output tar file will be named 'base_name' +  ".tar", possibly plus -    the appropriate compression extension (".gz", or ".bz2"). +    the appropriate compression extension (".gz", ".bz2", or ".xz").      Returns the output filename.      """ @@ -596,6 +609,10 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,          tar_compression['bzip2'] = 'bz2'          compress_ext['bzip2'] = '.bz2' +    if _LZMA_SUPPORTED: +        tar_compression['xz'] = 'xz' +        compress_ext['xz'] = '.xz' +      # flags for compression program, each element of list will be an argument      if compress is not None and compress not in compress_ext:          raise ValueError("bad value for 'compress', or compression format not " @@ -635,23 +652,6 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,      return archive_name -def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): -    # XXX see if we want to keep an external call here -    if verbose: -        zipoptions = "-r" -    else: -        zipoptions = "-rq" -    from distutils.errors import DistutilsExecError -    from distutils.spawn import spawn -    try: -        spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) -    except DistutilsExecError: -        # XXX really should distinguish between "couldn't find -        # external 'zip' command" and "zip failed". -        raise ExecError("unable to create zip file '%s': " -            "could neither import the 'zipfile' module nor " -            "find a standalone zip utility") % zip_filename -  def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):      """Create a zip file from all the files under 'base_dir'. @@ -661,6 +661,8 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):      available, raises ExecError.  Returns the name of the output zip      file.      """ +    import zipfile +      zip_filename = base_name + ".zip"      archive_dir = os.path.dirname(base_name) @@ -670,39 +672,29 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):          if not dry_run:              os.makedirs(archive_dir) -    # If zipfile module is not available, try spawning an external 'zip' -    # command. -    try: -        import zipfile -    except ImportError: -        zipfile = None - -    if zipfile is None: -        _call_external_zip(base_dir, zip_filename, verbose, dry_run) -    else: -        if logger is not None: -            logger.info("creating '%s' and adding '%s' to it", -                        zip_filename, base_dir) +    if logger is not None: +        logger.info("creating '%s' and adding '%s' to it", +                    zip_filename, base_dir) -        if not dry_run: -            with zipfile.ZipFile(zip_filename, "w", -                                 compression=zipfile.ZIP_DEFLATED) as zf: -                path = os.path.normpath(base_dir) -                zf.write(path, path) -                if logger is not None: -                    logger.info("adding '%s'", path) -                for dirpath, dirnames, filenames in os.walk(base_dir): -                    for name in sorted(dirnames): -                        path = os.path.normpath(os.path.join(dirpath, name)) +    if not dry_run: +        with zipfile.ZipFile(zip_filename, "w", +                             compression=zipfile.ZIP_DEFLATED) as zf: +            path = os.path.normpath(base_dir) +            zf.write(path, path) +            if logger is not None: +                logger.info("adding '%s'", path) +            for dirpath, dirnames, filenames in os.walk(base_dir): +                for name in sorted(dirnames): +                    path = os.path.normpath(os.path.join(dirpath, name)) +                    zf.write(path, path) +                    if logger is not None: +                        logger.info("adding '%s'", path) +                for name in filenames: +                    path = os.path.normpath(os.path.join(dirpath, name)) +                    if os.path.isfile(path):                          zf.write(path, path)                          if logger is not None:                              logger.info("adding '%s'", path) -                    for name in filenames: -                        path = os.path.normpath(os.path.join(dirpath, name)) -                        if os.path.isfile(path): -                            zf.write(path, path) -                            if logger is not None: -                                logger.info("adding '%s'", path)      return zip_filename @@ -716,6 +708,10 @@ if _BZ2_SUPPORTED:      _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],                                  "bzip2'ed tar-file") +if _LZMA_SUPPORTED: +    _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')], +                                "xz'ed tar-file") +  def get_archive_formats():      """Returns a list of supported formats for archiving and unarchiving. @@ -904,7 +900,7 @@ def _unpack_zipfile(filename, extract_dir):          zip.close()  def _unpack_tarfile(filename, extract_dir): -    """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` +    """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`      """      try:          tarobj = tarfile.open(filename) @@ -923,9 +919,13 @@ _UNPACK_FORMATS = {      }  if _BZ2_SUPPORTED: -    _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], +    _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],                                  "bzip2'ed tar-file") +if _LZMA_SUPPORTED: +    _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [], +                                "xz'ed tar-file") +  def _find_unpack_format(filename):      for name, info in _UNPACK_FORMATS.items():          for extension in info[0]:  | 
