diff -r a1c8302e6b27 Doc/library/shutil.rst --- a/Doc/library/shutil.rst Sun Jul 01 12:24:20 2012 +0200 +++ b/Doc/library/shutil.rst Mon Jul 02 18:43:37 2012 +0300 @@ -47,7 +47,7 @@ be copied. -.. function:: copyfile(src, dst, symlinks=False) +.. function:: copyfile(src, dst, *, follow_symlinks=True) Copy the contents (no metadata) of the file named *src* to a file named *dst* and return *dst*. *dst* must be the complete target file name; look at @@ -59,63 +59,63 @@ such as character or block devices and pipes cannot be copied with this function. *src* and *dst* are path names given as strings. - If *symlinks* is true and *src* is a symbolic link, a new symbolic link will + If *follow_symlinks* is false and *src* is a symbolic link, a new symbolic link will be created instead of copying the file *src* points to. .. versionchanged:: 3.3 :exc:`IOError` used to be raised instead of :exc:`OSError`. - Added *symlinks* argument. + Added *follow_symlinks* argument. .. versionchanged:: 3.3 Added return of the *dst*. -.. function:: copymode(src, dst, symlinks=False) +.. function:: copymode(src, dst, *, follow_symlinks=True) Copy the permission bits from *src* to *dst*. The file contents, owner, and group are unaffected. *src* and *dst* are path names given as strings. If - *symlinks* is true, *src* a symbolic link and the operating system supports + *follow_symlinks* is false, *src* a symbolic link and the operating system supports modes for symbolic links (for example BSD-based ones), the mode of the link will be copied. .. versionchanged:: 3.3 - Added *symlinks* argument. + Added *follow_symlinks* argument. -.. function:: copystat(src, dst, symlinks=False) +.. function:: copystat(src, dst, *, follow_symlinks=True) Copy the permission bits, last access time, last modification time, and flags from *src* to *dst*. The file contents, owner, and group are unaffected. *src* and *dst* are path names given as strings. If *src* and *dst* are both - symbolic links and *symlinks* true, the stats of the link will be copied as + symbolic links and *follow_symlinks* false, the stats of the link will be copied as far as the platform allows. .. versionchanged:: 3.3 - Added *symlinks* argument. + Added *follow_symlinks* argument. -.. function:: copy(src, dst, symlinks=False) +.. function:: copy(src, dst, *, follow_symlinks=True) Copy the file *src* to the file or directory *dst* and return the file's destination. If *dst* is a directory, a file with the same basename as *src* is created (or overwritten) in the directory specified. Permission bits are copied. *src* and *dst* are path - names given as strings. If *symlinks* is true, symbolic links won't be + names given as strings. If *follow_symlinks* is false, symbolic links won't be followed but recreated instead -- this resembles GNU's :program:`cp -P`. .. versionchanged:: 3.3 - Added *symlinks* argument. + Added *follow_symlinks* argument. .. versionchanged:: 3.3 Added return of the *dst*. -.. function:: copy2(src, dst, symlinks=False) +.. function:: copy2(src, dst, *, follow_symlinks=True) Similar to :func:`shutil.copy`, including that the destination is returned, but metadata is copied as well. This is - similar to the Unix command :program:`cp -p`. If *symlinks* is true, + similar to the Unix command :program:`cp -p`. If *follow_symlinks* is false, symbolic links won't be followed but recreated instead -- this resembles GNU's :program:`cp -P`. .. versionchanged:: 3.3 - Added *symlinks* argument, try to copy extended file system attributes + Added *follow_symlinks* argument, try to copy extended file system attributes too (currently Linux only). .. versionchanged:: 3.3 diff -r a1c8302e6b27 Lib/shutil.py --- a/Lib/shutil.py Sun Jul 01 12:24:20 2012 +0200 +++ b/Lib/shutil.py Mon Jul 02 18:43:37 2012 +0300 @@ -82,10 +82,10 @@ return (os.path.normcase(os.path.abspath(src)) == os.path.normcase(os.path.abspath(dst))) -def copyfile(src, dst, symlinks=False): +def copyfile(src, dst, *, follow_symlinks=True): """Copy data from src to dst. - If optional flag `symlinks` is set and `src` is a symbolic link, a new + If optional flag `follow_symlinks` is not set and `src` is a symbolic link, a new symlink will be created instead of copying the file it points to. """ @@ -103,7 +103,7 @@ if stat.S_ISFIFO(st.st_mode): raise SpecialFileError("`%s` is a named pipe" % fn) - if symlinks and os.path.islink(src): + if not follow_symlinks and os.path.islink(src): os.symlink(os.readlink(src), dst) else: with open(src, 'rb') as fsrc: @@ -111,15 +111,15 @@ copyfileobj(fsrc, fdst) return dst -def copymode(src, dst, symlinks=False): +def copymode(src, dst, *, follow_symlinks=True): """Copy mode bits from src to dst. - If the optional flag `symlinks` is set, symlinks aren't followed if and + If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and only if both `src` and `dst` are symlinks. If `lchmod` isn't available (eg. Linux), in these cases, this method does nothing. """ - if symlinks and os.path.islink(src) and os.path.islink(dst): + if not follow_symlinks and os.path.islink(src) and os.path.islink(dst): if hasattr(os, 'lchmod'): stat_func, chmod_func = os.lstat, os.lchmod else: @@ -132,10 +132,10 @@ st = stat_func(src) chmod_func(dst, stat.S_IMODE(st.st_mode)) -def copystat(src, dst, symlinks=False): +def copystat(src, dst, *, follow_symlinks=True): """Copy all stat info (mode bits, atime, mtime, flags) from src to dst. - If the optional flag `symlinks` is set, symlinks aren't followed if and + If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and only if both `src` and `dst` are symlinks. """ @@ -143,7 +143,7 @@ pass # follow symlinks (aka don't not follow symlinks) - follow = not (symlinks and os.path.islink(src) and os.path.islink(dst)) + follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst)) if follow: # use the real function if it exists def lookup(name): @@ -186,19 +186,19 @@ raise if hasattr(os, 'listxattr'): - def _copyxattr(src, dst, symlinks=False): + def _copyxattr(src, dst, *, follow_symlinks=True): """Copy extended filesystem attributes from `src` to `dst`. Overwrite existing attributes. - If the optional flag `symlinks` is set, symlinks won't be followed. + If the optional flag `follow_symlinks` is not set, symlinks won't be followed. """ - for name in os.listxattr(src, follow_symlinks=symlinks): + for name in os.listxattr(src, follow_symlinks=follow_symlinks): try: - value = os.getxattr(src, name, follow_symlinks=symlinks) - os.setxattr(dst, name, value, follow_symlinks=symlinks) + value = os.getxattr(src, name, follow_symlinks=follow_symlinks) + os.setxattr(dst, name, value, follow_symlinks=follow_symlinks) except OSError as e: if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA): raise @@ -206,36 +206,36 @@ def _copyxattr(*args, **kwargs): pass -def copy(src, dst, symlinks=False): +def copy(src, dst, *, follow_symlinks=True): """Copy data and mode bits ("cp src dst"). Return the file's destination. The destination may be a directory. - If the optional flag `symlinks` is set, symlinks won't be followed. This + If the optional flag `follow_symlinks` is not set, symlinks won't be followed. This resembles GNU's "cp -P src dst". """ if os.path.isdir(dst): dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst, symlinks=symlinks) - copymode(src, dst, symlinks=symlinks) + copyfile(src, dst, follow_symlinks=follow_symlinks) + copymode(src, dst, follow_symlinks=follow_symlinks) return dst -def copy2(src, dst, symlinks=False): +def copy2(src, dst, *, follow_symlinks=True): """Copy data and all stat info ("cp -p src dst"). Return the file's destination." The destination may be a directory. - If the optional flag `symlinks` is set, symlinks won't be followed. This + If the optional flag `follow_symlinks` is not set, symlinks won't be followed. This resembles GNU's "cp -P src dst". """ if os.path.isdir(dst): dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst, symlinks=symlinks) - copystat(src, dst, symlinks=symlinks) - _copyxattr(src, dst, symlinks=symlinks) + copyfile(src, dst, follow_symlinks=follow_symlinks) + copystat(src, dst, follow_symlinks=follow_symlinks) + _copyxattr(src, dst, follow_symlinks=follow_symlinks) return dst def ignore_patterns(*patterns): @@ -307,7 +307,7 @@ # code with a custom `copy_function` may rely on copytree # doing the right thing. os.symlink(linkto, dstname) - copystat(srcname, dstname, symlinks=symlinks) + copystat(srcname, dstname, follow_symlinks=not symlinks) else: # ignore dangling symlink if the flag is on if not os.path.exists(linkto) and ignore_dangling_symlinks: diff -r a1c8302e6b27 Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py Sun Jul 01 12:24:20 2012 +0200 +++ b/Lib/test/test_shutil.py Mon Jul 02 18:43:37 2012 +0300 @@ -277,17 +277,17 @@ os.lchmod(src_link, stat.S_IRWXO|stat.S_IRWXG) # link to link os.lchmod(dst_link, stat.S_IRWXO) - shutil.copymode(src_link, dst_link, symlinks=True) + shutil.copymode(src_link, dst_link, follow_symlinks=False) self.assertEqual(os.lstat(src_link).st_mode, os.lstat(dst_link).st_mode) self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode) # src link - use chmod os.lchmod(dst_link, stat.S_IRWXO) - shutil.copymode(src_link, dst, symlinks=True) + shutil.copymode(src_link, dst, follow_symlinks=False) self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) # dst link - use chmod os.lchmod(dst_link, stat.S_IRWXO) - shutil.copymode(src, dst_link, symlinks=True) + shutil.copymode(src, dst_link, follow_symlinks=False) self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) @unittest.skipIf(hasattr(os, 'lchmod'), 'requires os.lchmod to be missing') @@ -302,7 +302,7 @@ write_file(dst, 'foo') os.symlink(src, src_link) os.symlink(dst, dst_link) - shutil.copymode(src_link, dst_link, symlinks=True) # silent fail + shutil.copymode(src_link, dst_link, follow_symlinks=False) # silent fail @support.skip_unless_symlink def test_copystat_symlinks(self): @@ -326,10 +326,10 @@ src_link_stat = os.lstat(src_link) # follow if hasattr(os, 'lchmod'): - shutil.copystat(src_link, dst_link, symlinks=False) + shutil.copystat(src_link, dst_link, follow_symlinks=True) self.assertNotEqual(src_link_stat.st_mode, os.stat(dst).st_mode) # don't follow - shutil.copystat(src_link, dst_link, symlinks=True) + shutil.copystat(src_link, dst_link, follow_symlinks=False) dst_link_stat = os.lstat(dst_link) if os.utime in os.supports_follow_symlinks: for attr in 'st_atime', 'st_mtime': @@ -341,7 +341,7 @@ if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'): self.assertEqual(src_link_stat.st_flags, dst_link_stat.st_flags) # tell to follow but dst is not a link - shutil.copystat(src_link, dst, symlinks=True) + shutil.copystat(src_link, dst, follow_symlinks=False) self.assertTrue(abs(os.stat(src).st_mtime - os.stat(dst).st_mtime) < 00000.1) @@ -429,10 +429,10 @@ dst_link = os.path.join(tmp_dir, 'qux') write_file(dst, 'bar') os.symlink(dst, dst_link) - shutil._copyxattr(src_link, dst_link, symlinks=True) + shutil._copyxattr(src_link, dst_link, follow_symlinks=False) self.assertEqual(os.getxattr(dst_link, 'trusted.foo', follow_symlinks=False), b'43') self.assertRaises(OSError, os.getxattr, dst, 'trusted.foo') - shutil._copyxattr(src_link, dst, symlinks=True) + shutil._copyxattr(src_link, dst, follow_symlinks=False) self.assertEqual(os.getxattr(dst, 'trusted.foo'), b'43') @support.skip_unless_symlink @@ -446,12 +446,12 @@ if hasattr(os, 'lchmod'): os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO) # don't follow - shutil.copy(src_link, dst, symlinks=False) + shutil.copy(src_link, dst, follow_symlinks=True) self.assertFalse(os.path.islink(dst)) self.assertEqual(read_file(src), read_file(dst)) os.remove(dst) # follow - shutil.copy(src_link, dst, symlinks=True) + shutil.copy(src_link, dst, follow_symlinks=False) self.assertTrue(os.path.islink(dst)) self.assertEqual(os.readlink(dst), os.readlink(src_link)) if hasattr(os, 'lchmod'): @@ -473,12 +473,12 @@ src_stat = os.stat(src) src_link_stat = os.lstat(src_link) # follow - shutil.copy2(src_link, dst, symlinks=False) + shutil.copy2(src_link, dst, follow_symlinks=True) self.assertFalse(os.path.islink(dst)) self.assertEqual(read_file(src), read_file(dst)) os.remove(dst) # don't follow - shutil.copy2(src_link, dst, symlinks=True) + shutil.copy2(src_link, dst, follow_symlinks=False) self.assertTrue(os.path.islink(dst)) self.assertEqual(os.readlink(dst), os.readlink(src_link)) dst_stat = os.lstat(dst) @@ -516,7 +516,7 @@ write_file(src, 'foo') os.symlink(src, link) # don't follow - shutil.copyfile(link, dst_link, symlinks=True) + shutil.copyfile(link, dst_link, follow_symlinks=False) self.assertTrue(os.path.islink(dst_link)) self.assertEqual(os.readlink(link), os.readlink(dst_link)) # follow