def test_islink(self): fn = os.path.join(TESTDATA, 'symlink') os.symlink('test.txt', fn) try: self.assertTrue(zipio.islink(fn)) finally: os.unlink(fn) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'test.txt'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'subdir'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'zipped.egg'))) self.assertFalse( zipio.islink(os.path.join(TESTDATA, 'zipped.egg/subdir'))) self.assertFalse( zipio.islink(os.path.join(TESTDATA, 'zipped.egg/subdir4'))) self.assertFalse( zipio.islink(os.path.join(TESTDATA, 'zipped.egg/test.txt'))) self.assertFalse( zipio.islink(os.path.join(TESTDATA, 'zipped.egg/subdir/file1.txt'))) self.assertRaises(IOError, zipio.islink, os.path.join(TESTDATA, 'no-such-file')) self.assertRaises(IOError, zipio.islink, os.path.join(TESTDATA, 'zipped.egg', 'no-such-file'))
def test_islink(self): fn = os.path.join(TESTDATA, 'symlink') os.symlink('test.txt', fn) try: self.assertTrue(zipio.islink(fn)) finally: os.unlink(fn) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'test.txt'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'subdir'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'zipped.egg'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'zipped.egg/subdir'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'zipped.egg/subdir4'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'zipped.egg/test.txt'))) self.assertFalse(zipio.islink(os.path.join(TESTDATA, 'zipped.egg/subdir/file1.txt'))) self.assertRaises(IOError, zipio.islink, os.path.join(TESTDATA, 'no-such-file')) self.assertRaises(IOError, zipio.islink, os.path.join(TESTDATA, 'zipped.egg', 'no-such-file'))
def copy_tree(src, dst, preserve_mode=1, preserve_times=1, preserve_symlinks=0, update=0, verbose=0, dry_run=0, condition=None): """ Copy an entire directory tree 'src' to a new location 'dst'. Both 'src' and 'dst' must be directory names. If 'src' is not a directory, raise DistutilsFileError. If 'dst' does not exist, it is created with 'mkpath()'. The end result of the copy is that every file in 'src' is copied to 'dst', and directories under 'src' are recursively copied to 'dst'. Return the list of files that were copied or might have been copied, using their output name. The return value is unaffected by 'update' or 'dry_run': it is simply the list of all files under 'src', with the names changed to be under 'dst'. 'preserve_mode' and 'preserve_times' are the same as for 'copy_file'; note that they only apply to regular files, not to directories. If 'preserve_symlinks' is true, symlinks will be copied as symlinks (on platforms that support them!); otherwise (the default), the destination of the symlink will be copied. 'update' and 'verbose' are the same as for 'copy_file'. """ assert isinstance(src, (str, unicode)), repr(src) assert isinstance(dst, (str, unicode)), repr(dst) from distutils.dir_util import mkpath from distutils.dep_util import newer from distutils.errors import DistutilsFileError from distutils import log src = fsencoding(src) dst = fsencoding(dst) if condition is None: condition = skipscm if not dry_run and not zipio.isdir(src): raise DistutilsFileError("cannot copy tree '%s': not a directory" % src) try: names = zipio.listdir(src) except os.error as exc: (errno, errstr) = exc.args if dry_run: names = [] else: raise DistutilsFileError("error listing files in '%s': %s" % (src, errstr)) if not dry_run: mkpath(dst) outputs = [] for n in names: src_name = os.path.join(src, n) dst_name = os.path.join(dst, n) if (condition is not None) and (not condition(src_name)): continue if preserve_symlinks and zipio.islink(src_name): link_dest = zipio.readlink(src_name) log.info("linking %s -> %s", dst_name, link_dest) if not dry_run: if update and not newer(src, dst_name): pass else: if os.path.islink(dst_name): os.remove(dst_name) os.symlink(link_dest, dst_name) outputs.append(dst_name) elif zipio.isdir(src_name) and not os.path.isfile(src_name): # ^^^ this odd tests ensures that resource files that # happen to be a zipfile won't get extracted. # XXX: need API in zipio to clean up this code outputs.extend( copy_tree(src_name, dst_name, preserve_mode, preserve_times, preserve_symlinks, update, dry_run=dry_run, condition=condition)) else: copy_file(src_name, dst_name, preserve_mode, preserve_times, update, dry_run=dry_run) outputs.append(dst_name) return outputs
def os_readlink(path): warnings.warn("Use zipio.readlink instead of os_readlink", DeprecationWarning) return zipio.islink(path)
def os_path_isdir(path): warnings.warn("Use zipio.isdir instead of os_path_isdir", DeprecationWarning) return zipio.islink(path)
def copy_tree(src, dst, preserve_mode=1, preserve_times=1, preserve_symlinks=0, update=0, verbose=0, dry_run=0, condition=None): """ Copy an entire directory tree 'src' to a new location 'dst'. Both 'src' and 'dst' must be directory names. If 'src' is not a directory, raise DistutilsFileError. If 'dst' does not exist, it is created with 'mkpath()'. The end result of the copy is that every file in 'src' is copied to 'dst', and directories under 'src' are recursively copied to 'dst'. Return the list of files that were copied or might have been copied, using their output name. The return value is unaffected by 'update' or 'dry_run': it is simply the list of all files under 'src', with the names changed to be under 'dst'. 'preserve_mode' and 'preserve_times' are the same as for 'copy_file'; note that they only apply to regular files, not to directories. If 'preserve_symlinks' is true, symlinks will be copied as symlinks (on platforms that support them!); otherwise (the default), the destination of the symlink will be copied. 'update' and 'verbose' are the same as for 'copy_file'. """ assert isinstance(src, (str, unicode)), repr(src) assert isinstance(dst, (str, unicode)), repr(dst) from distutils.dir_util import mkpath from distutils.dep_util import newer from distutils.errors import DistutilsFileError from distutils import log src = fsencoding(src) dst = fsencoding(dst) if condition is None: condition = skipscm if not dry_run and not zipio.isdir(src): raise DistutilsFileError( "cannot copy tree '%s': not a directory" % src) try: names = zipio.listdir(src) except os.error as exc: (errno, errstr) = exc.args if dry_run: names = [] else: raise DistutilsFileError( "error listing files in '%s': %s" % (src, errstr)) if not dry_run: mkpath(dst) outputs = [] for n in names: src_name = os.path.join(src, n) dst_name = os.path.join(dst, n) if (condition is not None) and (not condition(src_name)): continue if preserve_symlinks and zipio.islink(src_name): link_dest = zipio.readlink(src_name) log.info("linking %s -> %s", dst_name, link_dest) if not dry_run: if update and not newer(src, dst_name): pass else: if os.path.islink(dst_name): os.remove(dst_name) os.symlink(link_dest, dst_name) outputs.append(dst_name) elif zipio.isdir(src_name) and not os.path.isfile(src_name): # ^^^ this odd tests ensures that resource files that # happen to be a zipfile won't get extracted. # XXX: need API in zipio to clean up this code outputs.extend( copy_tree(src_name, dst_name, preserve_mode, preserve_times, preserve_symlinks, update, dry_run=dry_run, condition=condition)) else: copy_file(src_name, dst_name, preserve_mode, preserve_times, update, dry_run=dry_run) outputs.append(dst_name) return outputs
def copy_tree( src, dst, preserve_mode=1, preserve_times=1, preserve_symlinks=0, update=0, verbose=0, dry_run=0, condition=None, progress=None, ): """ Copy an entire directory tree 'src' to a new location 'dst'. Both 'src' and 'dst' must be directory names. If 'src' is not a directory, raise DistutilsFileError. If 'dst' does not exist, it is created with 'mkpath()'. The end result of the copy is that every file in 'src' is copied to 'dst', and directories under 'src' are recursively copied to 'dst'. Return the list of files that were copied or might have been copied, using their output name. The return value is unaffected by 'update' or 'dry_run': it is simply the list of all files under 'src', with the names changed to be under 'dst'. 'preserve_mode' and 'preserve_times' are the same as for 'copy_file'; note that they only apply to regular files, not to directories. If 'preserve_symlinks' is true, symlinks will be copied as symlinks (on platforms that support them!); otherwise (the default), the destination of the symlink will be copied. 'update' and 'verbose' are the same as for 'copy_file'. """ assert isinstance(src, str), repr(src) assert isinstance(dst, str), repr(dst) from distutils.dep_util import newer from distutils.errors import DistutilsFileError if condition is None: condition = skipscm if not dry_run and not zipio.isdir(src): raise DistutilsFileError("cannot copy tree '%s': not a directory" % src) try: names = zipio.listdir(src) except os.error as exc: (errno, errstr) = exc.args if dry_run: names = [] else: raise DistutilsFileError( f"error listing files in '{src}': {errstr}") if not dry_run and not os.path.exists(dst): if progress is not None: progress.trace(f"creating {dst}") os.makedirs(dst, 0o777) outputs = [] for n in names: src_name = os.path.join(src, n) dst_name = os.path.join(dst, n) if (condition is not None) and (not condition(src_name)): continue # Note: using zipio's internal _locate function throws an IOError on # dead symlinks, so handle it here. if os.path.islink(src_name) and not os.path.exists( os.path.join(src, os.readlink(src_name))): continue if preserve_symlinks and zipio.islink(src_name): link_dest = zipio.readlink(src_name) if progress is not None: progress.trace(f"linking {dst_name} -> {link_dest}") if not dry_run: if update and not newer(src, dst_name): pass else: make_symlink(link_dest, dst_name) outputs.append(dst_name) elif zipio.isdir(src_name) and not os.path.isfile(src_name): # ^^^ this odd tests ensures that resource files that # happen to be a zipfile won't get extracted. outputs.extend( copy_tree( src_name, dst_name, preserve_mode, preserve_times, preserve_symlinks, update, dry_run=dry_run, condition=condition, progress=progress, )) else: copy_file( src_name, dst_name, preserve_mode, preserve_times, update, dry_run=dry_run, progress=progress, ) outputs.append(dst_name) return outputs