Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(4868)

Delta Between Two Patch Sets: Lib/shutil.py

Issue 15202: followlinks/follow_symlinks/symlinks flags unification.
Left Patch Set: Created 10 months, 3 weeks ago
Right Patch Set: Created 10 months, 2 weeks ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Doc/library/shutil.rst ('k') | Lib/test/test_shutil.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 """Utility functions for copying and archiving files and directory trees. 1 """Utility functions for copying and archiving files and directory trees.
2 2
3 XXX The functions here don't copy the resource fork or other metadata on Mac. 3 XXX The functions here don't copy the resource fork or other metadata on Mac.
4 4
5 """ 5 """
6 6
7 import os 7 import os
8 import sys 8 import sys
9 import stat 9 import stat
10 from os.path import abspath 10 from os.path import abspath
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 if hasattr(os.path, 'samefile'): 75 if hasattr(os.path, 'samefile'):
76 try: 76 try:
77 return os.path.samefile(src, dst) 77 return os.path.samefile(src, dst)
78 except OSError: 78 except OSError:
79 return False 79 return False
80 80
81 # All other platforms: check for same pathname. 81 # All other platforms: check for same pathname.
82 return (os.path.normcase(os.path.abspath(src)) == 82 return (os.path.normcase(os.path.abspath(src)) ==
83 os.path.normcase(os.path.abspath(dst))) 83 os.path.normcase(os.path.abspath(dst)))
84 84
85 def copyfile(src, dst, follow_symlinks=True): 85 def copyfile(src, dst, *, follow_symlinks=True):
larry 2012/07/01 17:44:36 follow_symlinks should always be keyword-only. Pl
86 """Copy data from src to dst. 86 """Copy data from src to dst.
87 87
88 If optional flag `follow_symlinks` is not set and `src` is a symbolic link, a new 88 If optional flag `follow_symlinks` is not set and `src` is a symbolic link, a new
larry 2012/07/01 17:44:36 Please change this paragraph to: """ If follow_sy
89 symlink will be created instead of copying the file it points to. 89 symlink will be created instead of copying the file it points to.
90 90
91 """ 91 """
92 if _samefile(src, dst): 92 if _samefile(src, dst):
93 raise Error("`%s` and `%s` are the same file" % (src, dst)) 93 raise Error("`%s` and `%s` are the same file" % (src, dst))
94 94
95 for fn in [src, dst]: 95 for fn in [src, dst]:
96 try: 96 try:
97 st = os.stat(fn) 97 st = os.stat(fn)
98 except OSError: 98 except OSError:
99 # File most likely does not exist 99 # File most likely does not exist
100 pass 100 pass
101 else: 101 else:
102 # XXX What about other special files? (sockets, devices...) 102 # XXX What about other special files? (sockets, devices...)
103 if stat.S_ISFIFO(st.st_mode): 103 if stat.S_ISFIFO(st.st_mode):
104 raise SpecialFileError("`%s` is a named pipe" % fn) 104 raise SpecialFileError("`%s` is a named pipe" % fn)
105 105
106 if not follow_symlinks and os.path.islink(src): 106 if not follow_symlinks and os.path.islink(src):
107 os.symlink(os.readlink(src), dst) 107 os.symlink(os.readlink(src), dst)
108 else: 108 else:
109 with open(src, 'rb') as fsrc: 109 with open(src, 'rb') as fsrc:
110 with open(dst, 'wb') as fdst: 110 with open(dst, 'wb') as fdst:
111 copyfileobj(fsrc, fdst) 111 copyfileobj(fsrc, fdst)
112 return dst 112 return dst
113 113
114 def copymode(src, dst, follow_symlinks=True): 114 def copymode(src, dst, *, follow_symlinks=True):
115 """Copy mode bits from src to dst. 115 """Copy mode bits from src to dst.
116 116
117 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and 117 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
larry 2012/07/01 17:44:36 Please change this paragraph to: """ If follow_sy
118 only if both `src` and `dst` are symlinks. If `lchmod` isn't available (eg. 118 only if both `src` and `dst` are symlinks. If `lchmod` isn't available (eg.
119 Linux), in these cases, this method does nothing. 119 Linux), in these cases, this method does nothing.
120 120
121 """ 121 """
122 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst): 122 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
123 if hasattr(os, 'lchmod'): 123 if hasattr(os, 'lchmod'):
124 stat_func, chmod_func = os.lstat, os.lchmod 124 stat_func, chmod_func = os.lstat, os.lchmod
125 else: 125 else:
126 return 126 return
127 elif hasattr(os, 'chmod'): 127 elif hasattr(os, 'chmod'):
128 stat_func, chmod_func = os.stat, os.chmod 128 stat_func, chmod_func = os.stat, os.chmod
129 else: 129 else:
130 return 130 return
131 131
132 st = stat_func(src) 132 st = stat_func(src)
133 chmod_func(dst, stat.S_IMODE(st.st_mode)) 133 chmod_func(dst, stat.S_IMODE(st.st_mode))
134 134
135 def copystat(src, dst, follow_symlinks=True): 135 def copystat(src, dst, *, follow_symlinks=True):
136 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst. 136 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst.
137 137
138 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and 138 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
larry 2012/07/01 17:44:36 Please change to: """ If follow_symlinks is False
139 only if both `src` and `dst` are symlinks. 139 only if both `src` and `dst` are symlinks.
140 140
141 """ 141 """
142 def _nop(*args, ns=None, follow_symlinks=None): 142 def _nop(*args, ns=None, follow_symlinks=None):
143 pass 143 pass
144 144
145 # follow symlinks (aka don't not follow symlinks) 145 # follow symlinks (aka don't not follow symlinks)
146 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst) ) 146 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst) )
147 if follow: 147 if follow:
148 # use the real function if it exists 148 # use the real function if it exists
(...skipping 30 matching lines...) Expand all
179 try: 179 try:
180 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow) 180 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
181 except OSError as why: 181 except OSError as why:
182 for err in 'EOPNOTSUPP', 'ENOTSUP': 182 for err in 'EOPNOTSUPP', 'ENOTSUP':
183 if hasattr(errno, err) and why.errno == getattr(errno, err): 183 if hasattr(errno, err) and why.errno == getattr(errno, err):
184 break 184 break
185 else: 185 else:
186 raise 186 raise
187 187
188 if hasattr(os, 'listxattr'): 188 if hasattr(os, 'listxattr'):
189 def _copyxattr(src, dst, follow_symlinks=True): 189 def _copyxattr(src, dst, *, follow_symlinks=True):
190 """Copy extended filesystem attributes from `src` to `dst`. 190 """Copy extended filesystem attributes from `src` to `dst`.
191 191
192 Overwrite existing attributes. 192 Overwrite existing attributes.
193 193
194 If the optional flag `follow_symlinks` is not set, symlinks won't be fol lowed. 194 If the optional flag `follow_symlinks` is not set, symlinks won't be fol lowed.
195 195
196 """ 196 """
197 197
198 for name in os.listxattr(src, follow_symlinks=follow_symlinks): 198 for name in os.listxattr(src, follow_symlinks=follow_symlinks):
199 try: 199 try:
200 value = os.getxattr(src, name, follow_symlinks=follow_symlinks) 200 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
201 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks) 201 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
202 except OSError as e: 202 except OSError as e:
203 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA): 203 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA):
204 raise 204 raise
205 else: 205 else:
206 def _copyxattr(*args, **kwargs): 206 def _copyxattr(*args, **kwargs):
207 pass 207 pass
208 208
209 def copy(src, dst, follow_symlinks=True): 209 def copy(src, dst, *, follow_symlinks=True):
210 """Copy data and mode bits ("cp src dst"). Return the file's destination. 210 """Copy data and mode bits ("cp src dst"). Return the file's destination.
211 211
212 The destination may be a directory. 212 The destination may be a directory.
213 213
214 If the optional flag `follow_symlinks` is not set, symlinks won't be followe d. This 214 If the optional flag `follow_symlinks` is not set, symlinks won't be followe d. This
215 resembles GNU's "cp -P src dst". 215 resembles GNU's "cp -P src dst".
216 216
217 """ 217 """
218 if os.path.isdir(dst): 218 if os.path.isdir(dst):
219 dst = os.path.join(dst, os.path.basename(src)) 219 dst = os.path.join(dst, os.path.basename(src))
220 copyfile(src, dst, follow_symlinks=follow_symlinks) 220 copyfile(src, dst, follow_symlinks=follow_symlinks)
221 copymode(src, dst, follow_symlinks=follow_symlinks) 221 copymode(src, dst, follow_symlinks=follow_symlinks)
222 return dst 222 return dst
223 223
224 def copy2(src, dst, follow_symlinks=True): 224 def copy2(src, dst, *, follow_symlinks=True):
225 """Copy data and all stat info ("cp -p src dst"). Return the file's 225 """Copy data and all stat info ("cp -p src dst"). Return the file's
226 destination." 226 destination."
227 227
228 The destination may be a directory. 228 The destination may be a directory.
229 229
230 If the optional flag `follow_symlinks` is not set, symlinks won't be followe d. This 230 If the optional flag `follow_symlinks` is not set, symlinks won't be followe d. This
231 resembles GNU's "cp -P src dst". 231 resembles GNU's "cp -P src dst".
232 232
233 """ 233 """
234 if os.path.isdir(dst): 234 if os.path.isdir(dst):
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 seen = set() 1093 seen = set()
1094 for dir in path: 1094 for dir in path:
1095 dir = os.path.normcase(dir) 1095 dir = os.path.normcase(dir)
1096 if not dir in seen: 1096 if not dir in seen:
1097 seen.add(dir) 1097 seen.add(dir)
1098 for thefile in files: 1098 for thefile in files:
1099 name = os.path.join(dir, thefile) 1099 name = os.path.join(dir, thefile)
1100 if _access_check(name, mode): 1100 if _access_check(name, mode):
1101 return name 1101 return name
1102 return None 1102 return None
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7