blob: a1884083087073512c1f8f63278798e755cb567e [file] [log] [blame]
Tarek Ziadéc3399782010-02-23 05:39:18 +00001"""Utility functions for copying and archiving files and directory trees.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00002
Guido van Rossum959fa011999-08-18 20:03:17 +00003XXX The functions here don't copy the resource fork or other metadata on Mac.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00004
5"""
Guido van Rossumc6360141990-10-13 19:23:40 +00006
Guido van Rossumc96207a1992-03-31 18:55:40 +00007import os
Guido van Rossum83c03e21999-02-23 23:07:51 +00008import sys
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00009import stat
Brett Cannon1c3fa182004-06-19 21:11:35 +000010from os.path import abspath
Georg Brandl2ee470f2008-07-16 12:55:28 +000011import fnmatch
Tarek Ziadé396fad72010-02-23 05:30:31 +000012import collections
Antoine Pitrou910bd512010-03-22 20:11:09 +000013import errno
Tarek Ziadé6ac91722010-04-28 17:51:36 +000014import tarfile
Tarek Ziadé396fad72010-02-23 05:30:31 +000015
16try:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000017 import bz2
Florent Xicluna54540ec2011-11-04 08:29:17 +010018 del bz2
Tarek Ziadéffa155a2010-04-29 13:34:35 +000019 _BZ2_SUPPORTED = True
20except ImportError:
21 _BZ2_SUPPORTED = False
22
23try:
Tarek Ziadé396fad72010-02-23 05:30:31 +000024 from pwd import getpwnam
25except ImportError:
26 getpwnam = None
27
28try:
29 from grp import getgrnam
30except ImportError:
31 getgrnam = None
Guido van Rossumc6360141990-10-13 19:23:40 +000032
Tarek Ziadéc3399782010-02-23 05:39:18 +000033__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
34 "copytree", "move", "rmtree", "Error", "SpecialFileError",
35 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000036 "register_archive_format", "unregister_archive_format",
37 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020038 "unregister_unpack_format", "unpack_archive",
Brian Curtinc57a3452012-06-22 16:00:30 -050039 "ignore_patterns", "chown", "which"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020040 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000041
Neal Norwitz4ce69a52005-09-01 00:45:28 +000042class Error(EnvironmentError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000043 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000044
Antoine Pitrou7fff0962009-05-01 21:09:44 +000045class SpecialFileError(EnvironmentError):
46 """Raised when trying to do a kind of operation (e.g. copying) which is
47 not supported on a special file (e.g. a named pipe)"""
48
Tarek Ziadé396fad72010-02-23 05:30:31 +000049class ExecError(EnvironmentError):
50 """Raised when a command could not be executed"""
51
Tarek Ziadé6ac91722010-04-28 17:51:36 +000052class ReadError(EnvironmentError):
53 """Raised when an archive cannot be read"""
54
55class RegistryError(Exception):
56 """Raised when a registery operation with the archiving
57 and unpacking registeries fails"""
58
59
Georg Brandl6aa2d1f2008-08-12 08:35:52 +000060try:
61 WindowsError
62except NameError:
63 WindowsError = None
64
Greg Stein42bb8b32000-07-12 09:55:30 +000065def copyfileobj(fsrc, fdst, length=16*1024):
66 """copy data from file-like object fsrc to file-like object fdst"""
67 while 1:
68 buf = fsrc.read(length)
69 if not buf:
70 break
71 fdst.write(buf)
72
Johannes Gijsbers46f14592004-08-14 13:30:02 +000073def _samefile(src, dst):
74 # Macintosh, Unix.
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +000075 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000076 try:
77 return os.path.samefile(src, dst)
78 except OSError:
79 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000080
81 # All other platforms: check for same pathname.
82 return (os.path.normcase(os.path.abspath(src)) ==
83 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000084
Larry Hastingsb4038062012-07-15 10:57:38 -070085def copyfile(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +010086 """Copy data from src to dst.
87
Larry Hastingsb4038062012-07-15 10:57:38 -070088 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +010089 symlink will be created instead of copying the file it points to.
90
91 """
Johannes Gijsbers46f14592004-08-14 13:30:02 +000092 if _samefile(src, dst):
Hynek Schlawack26fe37d2012-07-19 21:41:02 +020093 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000094
Antoine Pitrou7fff0962009-05-01 21:09:44 +000095 for fn in [src, dst]:
96 try:
97 st = os.stat(fn)
98 except OSError:
99 # File most likely does not exist
100 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000101 else:
102 # XXX What about other special files? (sockets, devices...)
103 if stat.S_ISFIFO(st.st_mode):
104 raise SpecialFileError("`%s` is a named pipe" % fn)
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000105
Larry Hastingsb4038062012-07-15 10:57:38 -0700106 if not follow_symlinks and os.path.islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100107 os.symlink(os.readlink(src), dst)
108 else:
109 with open(src, 'rb') as fsrc:
110 with open(dst, 'wb') as fdst:
111 copyfileobj(fsrc, fdst)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500112 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000113
Larry Hastingsb4038062012-07-15 10:57:38 -0700114def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100115 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000116
Larry Hastingsb4038062012-07-15 10:57:38 -0700117 If follow_symlinks is not set, symlinks aren't followed if and only
118 if both `src` and `dst` are symlinks. If `lchmod` isn't available
119 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100120
121 """
Larry Hastingsb4038062012-07-15 10:57:38 -0700122 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100123 if hasattr(os, 'lchmod'):
124 stat_func, chmod_func = os.lstat, os.lchmod
125 else:
126 return
127 elif hasattr(os, 'chmod'):
128 stat_func, chmod_func = os.stat, os.chmod
129 else:
130 return
131
132 st = stat_func(src)
133 chmod_func(dst, stat.S_IMODE(st.st_mode))
134
Larry Hastingsad5ae042012-07-14 17:55:11 -0700135if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700136 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700137 """Copy extended filesystem attributes from `src` to `dst`.
138
139 Overwrite existing attributes.
140
Larry Hastingsb4038062012-07-15 10:57:38 -0700141 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700142
143 """
144
Hynek Schlawack0beab052013-02-05 08:22:44 +0100145 try:
146 names = os.listxattr(src, follow_symlinks=follow_symlinks)
147 except OSError as e:
148 if e.errno not in (errno.ENOTSUP, errno.ENODATA):
149 raise
150 return
151 for name in names:
Larry Hastingsad5ae042012-07-14 17:55:11 -0700152 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700153 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
154 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700155 except OSError as e:
156 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA):
157 raise
158else:
159 def _copyxattr(*args, **kwargs):
160 pass
161
Larry Hastingsb4038062012-07-15 10:57:38 -0700162def copystat(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100163 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst.
164
Larry Hastingsb4038062012-07-15 10:57:38 -0700165 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
Antoine Pitrou78091e62011-12-29 18:54:15 +0100166 only if both `src` and `dst` are symlinks.
167
168 """
Larry Hastings9cf065c2012-06-22 16:30:09 -0700169 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100170 pass
171
Larry Hastings9cf065c2012-06-22 16:30:09 -0700172 # follow symlinks (aka don't not follow symlinks)
Larry Hastingsb4038062012-07-15 10:57:38 -0700173 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700174 if follow:
175 # use the real function if it exists
176 def lookup(name):
177 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100178 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700179 # use the real function only if it exists
180 # *and* it supports follow_symlinks
181 def lookup(name):
182 fn = getattr(os, name, _nop)
183 if fn in os.supports_follow_symlinks:
184 return fn
185 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100186
Larry Hastings9cf065c2012-06-22 16:30:09 -0700187 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000188 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700189 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
190 follow_symlinks=follow)
191 try:
192 lookup("chmod")(dst, mode, follow_symlinks=follow)
193 except NotImplementedError:
194 # if we got a NotImplementedError, it's because
195 # * follow_symlinks=False,
196 # * lchown() is unavailable, and
197 # * either
198 # * fchownat() is unvailable or
199 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
200 # (it returned ENOSUP.)
201 # therefore we're out of options--we simply cannot chown the
202 # symlink. give up, suppress the error.
203 # (which is what shutil always did in this circumstance.)
204 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100205 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000206 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700207 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000208 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700209 for err in 'EOPNOTSUPP', 'ENOTSUP':
210 if hasattr(errno, err) and why.errno == getattr(errno, err):
211 break
212 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000213 raise
Larry Hastingsb4038062012-07-15 10:57:38 -0700214 _copyxattr(src, dst, follow_symlinks=follow)
Antoine Pitrou424246f2012-05-12 19:02:01 +0200215
Larry Hastingsb4038062012-07-15 10:57:38 -0700216def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500217 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000218
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000219 The destination may be a directory.
220
Larry Hastingsb4038062012-07-15 10:57:38 -0700221 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100222 resembles GNU's "cp -P src dst".
223
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000224 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000225 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000226 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700227 copyfile(src, dst, follow_symlinks=follow_symlinks)
228 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500229 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000230
Larry Hastingsb4038062012-07-15 10:57:38 -0700231def copy2(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500232 """Copy data and all stat info ("cp -p src dst"). Return the file's
233 destination."
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000234
235 The destination may be a directory.
236
Larry Hastingsb4038062012-07-15 10:57:38 -0700237 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100238 resembles GNU's "cp -P src dst".
239
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000240 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000241 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000242 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700243 copyfile(src, dst, follow_symlinks=follow_symlinks)
244 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500245 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000246
Georg Brandl2ee470f2008-07-16 12:55:28 +0000247def ignore_patterns(*patterns):
248 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000249
Georg Brandl2ee470f2008-07-16 12:55:28 +0000250 Patterns is a sequence of glob-style patterns
251 that are used to exclude files"""
252 def _ignore_patterns(path, names):
253 ignored_names = []
254 for pattern in patterns:
255 ignored_names.extend(fnmatch.filter(names, pattern))
256 return set(ignored_names)
257 return _ignore_patterns
258
Tarek Ziadéfb437512010-04-20 08:57:33 +0000259def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
260 ignore_dangling_symlinks=False):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000261 """Recursively copy a directory tree.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000262
263 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000264 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000265
266 If the optional symlinks flag is true, symbolic links in the
267 source tree result in symbolic links in the destination tree; if
268 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000269 links are copied. If the file pointed by the symlink doesn't
270 exist, an exception will be added in the list of errors raised in
271 an Error exception at the end of the copy process.
272
273 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000274 want to silence this exception. Notice that this has no effect on
275 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000276
Georg Brandl2ee470f2008-07-16 12:55:28 +0000277 The optional ignore argument is a callable. If given, it
278 is called with the `src` parameter, which is the directory
279 being visited by copytree(), and `names` which is the list of
280 `src` contents, as returned by os.listdir():
281
282 callable(src, names) -> ignored_names
283
284 Since copytree() is called recursively, the callable will be
285 called once for each directory that is copied. It returns a
286 list of names relative to the `src` directory that should
287 not be copied.
288
Tarek Ziadé5340db32010-04-19 22:30:51 +0000289 The optional copy_function argument is a callable that will be used
290 to copy each file. It will be called with the source path and the
291 destination path as arguments. By default, copy2() is used, but any
292 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000293
294 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000295 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000296 if ignore is not None:
297 ignored_names = ignore(src, names)
298 else:
299 ignored_names = set()
300
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000301 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000302 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000303 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000304 if name in ignored_names:
305 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000306 srcname = os.path.join(src, name)
307 dstname = os.path.join(dst, name)
308 try:
Tarek Ziadéfb437512010-04-20 08:57:33 +0000309 if os.path.islink(srcname):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000310 linkto = os.readlink(srcname)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000311 if symlinks:
Antoine Pitrou78091e62011-12-29 18:54:15 +0100312 # We can't just leave it to `copy_function` because legacy
313 # code with a custom `copy_function` may rely on copytree
314 # doing the right thing.
Tarek Ziadéfb437512010-04-20 08:57:33 +0000315 os.symlink(linkto, dstname)
Larry Hastingsb4038062012-07-15 10:57:38 -0700316 copystat(srcname, dstname, follow_symlinks=not symlinks)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000317 else:
318 # ignore dangling symlink if the flag is on
319 if not os.path.exists(linkto) and ignore_dangling_symlinks:
320 continue
321 # otherwise let the copy occurs. copy2 will raise an error
322 copy_function(srcname, dstname)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000323 elif os.path.isdir(srcname):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000324 copytree(srcname, dstname, symlinks, ignore, copy_function)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000325 else:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000326 # Will raise a SpecialFileError for unsupported file types
Tarek Ziadé5340db32010-04-19 22:30:51 +0000327 copy_function(srcname, dstname)
Georg Brandla1be88e2005-08-31 22:48:45 +0000328 # catch the Error from the recursive copytree so that we can
329 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000330 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000331 errors.extend(err.args[0])
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000332 except EnvironmentError as why:
333 errors.append((srcname, dstname, str(why)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000334 try:
335 copystat(src, dst)
Guido van Rossumb940e112007-01-10 16:19:56 +0000336 except OSError as why:
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000337 if WindowsError is not None and isinstance(why, WindowsError):
338 # Copying file access times may fail on Windows
339 pass
340 else:
Georg Brandlc8076df2012-08-25 10:11:57 +0200341 errors.append((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000342 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000343 raise Error(errors)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500344 return dst
Guido van Rossumd7673291998-02-06 21:38:09 +0000345
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200346# version vulnerable to race conditions
347def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000348 try:
349 if os.path.islink(path):
350 # symlinks to directories are forbidden, see bug #1669
351 raise OSError("Cannot call rmtree on a symbolic link")
352 except OSError:
353 onerror(os.path.islink, path, sys.exc_info())
354 # can't continue even if onerror hook returns
355 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000356 names = []
357 try:
358 names = os.listdir(path)
Éric Araujocfcc9772011-08-10 20:54:33 +0200359 except os.error:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000360 onerror(os.listdir, path, sys.exc_info())
361 for name in names:
362 fullname = os.path.join(path, name)
363 try:
364 mode = os.lstat(fullname).st_mode
365 except os.error:
366 mode = 0
367 if stat.S_ISDIR(mode):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200368 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000369 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000370 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200371 os.unlink(fullname)
Éric Araujocfcc9772011-08-10 20:54:33 +0200372 except os.error:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200373 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000374 try:
375 os.rmdir(path)
376 except os.error:
377 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000378
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200379# Version using fd-based APIs to protect against races
380def _rmtree_safe_fd(topfd, path, onerror):
381 names = []
382 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200383 names = os.listdir(topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100384 except OSError as err:
385 err.filename = path
Hynek Schlawack2100b422012-06-23 20:28:32 +0200386 onerror(os.listdir, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200387 for name in names:
388 fullname = os.path.join(path, name)
389 try:
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200390 orig_st = os.stat(name, dir_fd=topfd, follow_symlinks=False)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200391 mode = orig_st.st_mode
Hynek Schlawackb5501102012-12-10 09:11:25 +0100392 except OSError:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200393 mode = 0
394 if stat.S_ISDIR(mode):
395 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200396 dirfd = os.open(name, os.O_RDONLY, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100397 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200398 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200399 else:
400 try:
401 if os.path.samestat(orig_st, os.fstat(dirfd)):
402 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200403 try:
404 os.rmdir(name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100405 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200406 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100407 else:
408 try:
409 # This can only happen if someone replaces
410 # a directory with a symlink after the call to
411 # stat.S_ISDIR above.
412 raise OSError("Cannot call rmtree on a symbolic "
413 "link")
414 except OSError:
415 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200416 finally:
417 os.close(dirfd)
418 else:
419 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200420 os.unlink(name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100421 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200422 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200423
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200424_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
425 os.supports_dir_fd and
426 os.listdir in os.supports_fd and
427 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000428
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200429def rmtree(path, ignore_errors=False, onerror=None):
430 """Recursively delete a directory tree.
431
432 If ignore_errors is set, errors are ignored; otherwise, if onerror
433 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200434 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200435 path is the argument to that function that caused it to fail; and
436 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
437 is false and onerror is None, an exception is raised.
438
439 """
440 if ignore_errors:
441 def onerror(*args):
442 pass
443 elif onerror is None:
444 def onerror(*args):
445 raise
446 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200447 # While the unsafe rmtree works fine on bytes, the fd based does not.
448 if isinstance(path, bytes):
449 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200450 # Note: To guard against symlink races, we use the standard
451 # lstat()/open()/fstat() trick.
452 try:
453 orig_st = os.lstat(path)
454 except Exception:
455 onerror(os.lstat, path, sys.exc_info())
456 return
457 try:
458 fd = os.open(path, os.O_RDONLY)
459 except Exception:
460 onerror(os.lstat, path, sys.exc_info())
461 return
462 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100463 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200464 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200465 try:
466 os.rmdir(path)
467 except os.error:
468 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200469 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100470 try:
471 # symlinks to directories are forbidden, see bug #1669
472 raise OSError("Cannot call rmtree on a symbolic link")
473 except OSError:
474 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200475 finally:
476 os.close(fd)
477 else:
478 return _rmtree_unsafe(path, onerror)
479
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000480# Allow introspection of whether or not the hardening against symlink
481# attacks is supported on the current platform
482rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000483
Christian Heimesada8c3b2008-03-18 18:26:33 +0000484def _basename(path):
485 # A basename() variant which first strips the trailing slash, if present.
486 # Thus we always get the last component of the path, even for directories.
487 return os.path.basename(path.rstrip(os.path.sep))
488
489def move(src, dst):
490 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500491 similar to the Unix "mv" command. Return the file or directory's
492 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000493
494 If the destination is a directory or a symlink to a directory, the source
495 is moved inside the directory. The destination path must not already
496 exist.
497
498 If the destination already exists but is not a directory, it may be
499 overwritten depending on os.rename() semantics.
500
501 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100502 Otherwise, src is copied to the destination and then removed. Symlinks are
503 recreated under the new name if os.rename() fails because of cross
504 filesystem renames.
505
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000506 A lot more could be done here... A look at a mv.c shows a lot of
507 the issues this implementation glosses over.
508
509 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000510 real_dst = dst
511 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200512 if _samefile(src, dst):
513 # We might be on a case insensitive filesystem,
514 # perform the rename anyway.
515 os.rename(src, dst)
516 return
517
Christian Heimesada8c3b2008-03-18 18:26:33 +0000518 real_dst = os.path.join(dst, _basename(src))
519 if os.path.exists(real_dst):
520 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000521 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000522 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200523 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100524 if os.path.islink(src):
525 linkto = os.readlink(src)
526 os.symlink(linkto, real_dst)
527 os.unlink(src)
528 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000529 if _destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000530 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000531 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000532 rmtree(src)
533 else:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000534 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000535 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500536 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000537
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000538def _destinsrc(src, dst):
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000539 src = abspath(src)
540 dst = abspath(dst)
541 if not src.endswith(os.path.sep):
542 src += os.path.sep
543 if not dst.endswith(os.path.sep):
544 dst += os.path.sep
545 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000546
547def _get_gid(name):
548 """Returns a gid, given a group name."""
549 if getgrnam is None or name is None:
550 return None
551 try:
552 result = getgrnam(name)
553 except KeyError:
554 result = None
555 if result is not None:
556 return result[2]
557 return None
558
559def _get_uid(name):
560 """Returns an uid, given a user name."""
561 if getpwnam is None or name is None:
562 return None
563 try:
564 result = getpwnam(name)
565 except KeyError:
566 result = None
567 if result is not None:
568 return result[2]
569 return None
570
571def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
572 owner=None, group=None, logger=None):
573 """Create a (possibly compressed) tar file from all the files under
574 'base_dir'.
575
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000576 'compress' must be "gzip" (the default), "bzip2", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000577
578 'owner' and 'group' can be used to define an owner and a group for the
579 archive that is being built. If not provided, the current owner and group
580 will be used.
581
Éric Araujo4433a5f2010-12-15 20:26:30 +0000582 The output tar file will be named 'base_name' + ".tar", possibly plus
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000583 the appropriate compression extension (".gz", or ".bz2").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000584
585 Returns the output filename.
586 """
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000587 tar_compression = {'gzip': 'gz', None: ''}
588 compress_ext = {'gzip': '.gz'}
589
590 if _BZ2_SUPPORTED:
591 tar_compression['bzip2'] = 'bz2'
592 compress_ext['bzip2'] = '.bz2'
Tarek Ziadé396fad72010-02-23 05:30:31 +0000593
594 # flags for compression program, each element of list will be an argument
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200595 if compress is not None and compress not in compress_ext:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000596 raise ValueError("bad value for 'compress', or compression format not "
597 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000598
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000599 archive_name = base_name + '.tar' + compress_ext.get(compress, '')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000600 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000601
Tarek Ziadé396fad72010-02-23 05:30:31 +0000602 if not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000603 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200604 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000605 if not dry_run:
606 os.makedirs(archive_dir)
607
Tarek Ziadé396fad72010-02-23 05:30:31 +0000608 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000609 if logger is not None:
610 logger.info('Creating tar archive')
611
612 uid = _get_uid(owner)
613 gid = _get_gid(group)
614
615 def _set_uid_gid(tarinfo):
616 if gid is not None:
617 tarinfo.gid = gid
618 tarinfo.gname = group
619 if uid is not None:
620 tarinfo.uid = uid
621 tarinfo.uname = owner
622 return tarinfo
623
624 if not dry_run:
625 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
626 try:
627 tar.add(base_dir, filter=_set_uid_gid)
628 finally:
629 tar.close()
630
Tarek Ziadé396fad72010-02-23 05:30:31 +0000631 return archive_name
632
Tarek Ziadée2124162010-04-21 13:35:21 +0000633def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000634 # XXX see if we want to keep an external call here
635 if verbose:
636 zipoptions = "-r"
637 else:
638 zipoptions = "-rq"
639 from distutils.errors import DistutilsExecError
640 from distutils.spawn import spawn
641 try:
642 spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
643 except DistutilsExecError:
644 # XXX really should distinguish between "couldn't find
645 # external 'zip' command" and "zip failed".
646 raise ExecError("unable to create zip file '%s': "
647 "could neither import the 'zipfile' module nor "
648 "find a standalone zip utility") % zip_filename
649
650def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
651 """Create a zip file from all the files under 'base_dir'.
652
Éric Araujo4433a5f2010-12-15 20:26:30 +0000653 The output zip file will be named 'base_name' + ".zip". Uses either the
Tarek Ziadé396fad72010-02-23 05:30:31 +0000654 "zipfile" Python module (if available) or the InfoZIP "zip" utility
655 (if installed and found on the default search path). If neither tool is
656 available, raises ExecError. Returns the name of the output zip
657 file.
658 """
659 zip_filename = base_name + ".zip"
660 archive_dir = os.path.dirname(base_name)
661
662 if not os.path.exists(archive_dir):
663 if logger is not None:
664 logger.info("creating %s", archive_dir)
665 if not dry_run:
666 os.makedirs(archive_dir)
667
668 # If zipfile module is not available, try spawning an external 'zip'
669 # command.
670 try:
671 import zipfile
672 except ImportError:
673 zipfile = None
674
675 if zipfile is None:
Tarek Ziadée2124162010-04-21 13:35:21 +0000676 _call_external_zip(base_dir, zip_filename, verbose, dry_run)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000677 else:
678 if logger is not None:
679 logger.info("creating '%s' and adding '%s' to it",
680 zip_filename, base_dir)
681
682 if not dry_run:
683 zip = zipfile.ZipFile(zip_filename, "w",
684 compression=zipfile.ZIP_DEFLATED)
685
686 for dirpath, dirnames, filenames in os.walk(base_dir):
687 for name in filenames:
688 path = os.path.normpath(os.path.join(dirpath, name))
689 if os.path.isfile(path):
690 zip.write(path, path)
691 if logger is not None:
692 logger.info("adding '%s'", path)
693 zip.close()
694
695 return zip_filename
696
697_ARCHIVE_FORMATS = {
698 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
Tarek Ziadé396fad72010-02-23 05:30:31 +0000699 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200700 'zip': (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000701 }
702
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000703if _BZ2_SUPPORTED:
704 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
705 "bzip2'ed tar-file")
706
Tarek Ziadé396fad72010-02-23 05:30:31 +0000707def get_archive_formats():
708 """Returns a list of supported formats for archiving and unarchiving.
709
710 Each element of the returned sequence is a tuple (name, description)
711 """
712 formats = [(name, registry[2]) for name, registry in
713 _ARCHIVE_FORMATS.items()]
714 formats.sort()
715 return formats
716
717def register_archive_format(name, function, extra_args=None, description=''):
718 """Registers an archive format.
719
720 name is the name of the format. function is the callable that will be
721 used to create archives. If provided, extra_args is a sequence of
722 (name, value) tuples that will be passed as arguments to the callable.
723 description can be provided to describe the format, and will be returned
724 by the get_archive_formats() function.
725 """
726 if extra_args is None:
727 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200728 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000729 raise TypeError('The %s object is not callable' % function)
730 if not isinstance(extra_args, (tuple, list)):
731 raise TypeError('extra_args needs to be a sequence')
732 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200733 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000734 raise TypeError('extra_args elements are : (arg_name, value)')
735
736 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
737
738def unregister_archive_format(name):
739 del _ARCHIVE_FORMATS[name]
740
741def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
742 dry_run=0, owner=None, group=None, logger=None):
743 """Create an archive file (eg. zip or tar).
744
745 'base_name' is the name of the file to create, minus any format-specific
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000746 extension; 'format' is the archive format: one of "zip", "tar", "bztar"
747 or "gztar".
Tarek Ziadé396fad72010-02-23 05:30:31 +0000748
749 'root_dir' is a directory that will be the root directory of the
750 archive; ie. we typically chdir into 'root_dir' before creating the
751 archive. 'base_dir' is the directory where we start archiving from;
752 ie. 'base_dir' will be the common prefix of all files and
753 directories in the archive. 'root_dir' and 'base_dir' both default
754 to the current directory. Returns the name of the archive file.
755
756 'owner' and 'group' are used when creating a tar archive. By default,
757 uses the current owner and group.
758 """
759 save_cwd = os.getcwd()
760 if root_dir is not None:
761 if logger is not None:
762 logger.debug("changing into '%s'", root_dir)
763 base_name = os.path.abspath(base_name)
764 if not dry_run:
765 os.chdir(root_dir)
766
767 if base_dir is None:
768 base_dir = os.curdir
769
770 kwargs = {'dry_run': dry_run, 'logger': logger}
771
772 try:
773 format_info = _ARCHIVE_FORMATS[format]
774 except KeyError:
775 raise ValueError("unknown archive format '%s'" % format)
776
777 func = format_info[0]
778 for arg, val in format_info[1]:
779 kwargs[arg] = val
780
781 if format != 'zip':
782 kwargs['owner'] = owner
783 kwargs['group'] = group
784
785 try:
786 filename = func(base_name, base_dir, **kwargs)
787 finally:
788 if root_dir is not None:
789 if logger is not None:
790 logger.debug("changing back to '%s'", save_cwd)
791 os.chdir(save_cwd)
792
793 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000794
795
796def get_unpack_formats():
797 """Returns a list of supported formats for unpacking.
798
799 Each element of the returned sequence is a tuple
800 (name, extensions, description)
801 """
802 formats = [(name, info[0], info[3]) for name, info in
803 _UNPACK_FORMATS.items()]
804 formats.sort()
805 return formats
806
807def _check_unpack_options(extensions, function, extra_args):
808 """Checks what gets registered as an unpacker."""
809 # first make sure no other unpacker is registered for this extension
810 existing_extensions = {}
811 for name, info in _UNPACK_FORMATS.items():
812 for ext in info[0]:
813 existing_extensions[ext] = name
814
815 for extension in extensions:
816 if extension in existing_extensions:
817 msg = '%s is already registered for "%s"'
818 raise RegistryError(msg % (extension,
819 existing_extensions[extension]))
820
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200821 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000822 raise TypeError('The registered function must be a callable')
823
824
825def register_unpack_format(name, extensions, function, extra_args=None,
826 description=''):
827 """Registers an unpack format.
828
829 `name` is the name of the format. `extensions` is a list of extensions
830 corresponding to the format.
831
832 `function` is the callable that will be
833 used to unpack archives. The callable will receive archives to unpack.
834 If it's unable to handle an archive, it needs to raise a ReadError
835 exception.
836
837 If provided, `extra_args` is a sequence of
838 (name, value) tuples that will be passed as arguments to the callable.
839 description can be provided to describe the format, and will be returned
840 by the get_unpack_formats() function.
841 """
842 if extra_args is None:
843 extra_args = []
844 _check_unpack_options(extensions, function, extra_args)
845 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
846
847def unregister_unpack_format(name):
848 """Removes the pack format from the registery."""
849 del _UNPACK_FORMATS[name]
850
851def _ensure_directory(path):
852 """Ensure that the parent directory of `path` exists"""
853 dirname = os.path.dirname(path)
854 if not os.path.isdir(dirname):
855 os.makedirs(dirname)
856
857def _unpack_zipfile(filename, extract_dir):
858 """Unpack zip `filename` to `extract_dir`
859 """
860 try:
861 import zipfile
862 except ImportError:
863 raise ReadError('zlib not supported, cannot unpack this archive.')
864
865 if not zipfile.is_zipfile(filename):
866 raise ReadError("%s is not a zip file" % filename)
867
868 zip = zipfile.ZipFile(filename)
869 try:
870 for info in zip.infolist():
871 name = info.filename
872
873 # don't extract absolute paths or ones with .. in them
874 if name.startswith('/') or '..' in name:
875 continue
876
877 target = os.path.join(extract_dir, *name.split('/'))
878 if not target:
879 continue
880
881 _ensure_directory(target)
882 if not name.endswith('/'):
883 # file
884 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200885 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000886 try:
887 f.write(data)
888 finally:
889 f.close()
890 del data
891 finally:
892 zip.close()
893
894def _unpack_tarfile(filename, extract_dir):
895 """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
896 """
897 try:
898 tarobj = tarfile.open(filename)
899 except tarfile.TarError:
900 raise ReadError(
901 "%s is not a compressed or uncompressed tar file" % filename)
902 try:
903 tarobj.extractall(extract_dir)
904 finally:
905 tarobj.close()
906
907_UNPACK_FORMATS = {
908 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"),
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000909 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
910 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file")
911 }
912
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000913if _BZ2_SUPPORTED:
914 _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [],
915 "bzip2'ed tar-file")
916
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000917def _find_unpack_format(filename):
918 for name, info in _UNPACK_FORMATS.items():
919 for extension in info[0]:
920 if filename.endswith(extension):
921 return name
922 return None
923
924def unpack_archive(filename, extract_dir=None, format=None):
925 """Unpack an archive.
926
927 `filename` is the name of the archive.
928
929 `extract_dir` is the name of the target directory, where the archive
930 is unpacked. If not provided, the current working directory is used.
931
932 `format` is the archive format: one of "zip", "tar", or "gztar". Or any
933 other registered format. If not provided, unpack_archive will use the
934 filename extension and see if an unpacker was registered for that
935 extension.
936
937 In case none is found, a ValueError is raised.
938 """
939 if extract_dir is None:
940 extract_dir = os.getcwd()
941
942 if format is not None:
943 try:
944 format_info = _UNPACK_FORMATS[format]
945 except KeyError:
946 raise ValueError("Unknown unpack format '{0}'".format(format))
947
Nick Coghlanabf202d2011-03-16 13:52:20 -0400948 func = format_info[1]
949 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000950 else:
951 # we need to look at the registered unpackers supported extensions
952 format = _find_unpack_format(filename)
953 if format is None:
954 raise ReadError("Unknown archive format '{0}'".format(filename))
955
956 func = _UNPACK_FORMATS[format][1]
957 kwargs = dict(_UNPACK_FORMATS[format][2])
958 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200959
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200960
961if hasattr(os, 'statvfs'):
962
963 __all__.append('disk_usage')
964 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200965
966 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200967 """Return disk usage statistics about the given path.
968
Sandro Tosif8ae4fa2012-04-23 20:07:15 +0200969 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200970 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200971 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200972 st = os.statvfs(path)
973 free = st.f_bavail * st.f_frsize
974 total = st.f_blocks * st.f_frsize
975 used = (st.f_blocks - st.f_bfree) * st.f_frsize
976 return _ntuple_diskusage(total, used, free)
977
978elif os.name == 'nt':
979
980 import nt
981 __all__.append('disk_usage')
982 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
983
984 def disk_usage(path):
985 """Return disk usage statistics about the given path.
986
987 Returned valus is a named tuple with attributes 'total', 'used' and
988 'free', which are the amount of total, used and free space, in bytes.
989 """
990 total, free = nt._getdiskusage(path)
991 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200992 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +0200993
Éric Araujo0ac4a5d2011-09-01 08:31:51 +0200994
Sandro Tosid902a142011-08-22 23:28:27 +0200995def chown(path, user=None, group=None):
996 """Change owner user and group of the given path.
997
998 user and group can be the uid/gid or the user/group names, and in that case,
999 they are converted to their respective uid/gid.
1000 """
1001
1002 if user is None and group is None:
1003 raise ValueError("user and/or group must be set")
1004
1005 _user = user
1006 _group = group
1007
1008 # -1 means don't change it
1009 if user is None:
1010 _user = -1
1011 # user can either be an int (the uid) or a string (the system username)
1012 elif isinstance(user, str):
1013 _user = _get_uid(user)
1014 if _user is None:
1015 raise LookupError("no such user: {!r}".format(user))
1016
1017 if group is None:
1018 _group = -1
1019 elif not isinstance(group, int):
1020 _group = _get_gid(group)
1021 if _group is None:
1022 raise LookupError("no such group: {!r}".format(group))
1023
1024 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001025
1026def get_terminal_size(fallback=(80, 24)):
1027 """Get the size of the terminal window.
1028
1029 For each of the two dimensions, the environment variable, COLUMNS
1030 and LINES respectively, is checked. If the variable is defined and
1031 the value is a positive integer, it is used.
1032
1033 When COLUMNS or LINES is not defined, which is the common case,
1034 the terminal connected to sys.__stdout__ is queried
1035 by invoking os.get_terminal_size.
1036
1037 If the terminal size cannot be successfully queried, either because
1038 the system doesn't support querying, or because we are not
1039 connected to a terminal, the value given in fallback parameter
1040 is used. Fallback defaults to (80, 24) which is the default
1041 size used by many terminal emulators.
1042
1043 The value returned is a named tuple of type os.terminal_size.
1044 """
1045 # columns, lines are the working values
1046 try:
1047 columns = int(os.environ['COLUMNS'])
1048 except (KeyError, ValueError):
1049 columns = 0
1050
1051 try:
1052 lines = int(os.environ['LINES'])
1053 except (KeyError, ValueError):
1054 lines = 0
1055
1056 # only query if necessary
1057 if columns <= 0 or lines <= 0:
1058 try:
1059 size = os.get_terminal_size(sys.__stdout__.fileno())
1060 except (NameError, OSError):
1061 size = os.terminal_size(fallback)
1062 if columns <= 0:
1063 columns = size.columns
1064 if lines <= 0:
1065 lines = size.lines
1066
1067 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001068
1069def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001070 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001071 conforms to the given mode on the PATH, or None if there is no such
1072 file.
1073
1074 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1075 of os.environ.get("PATH"), or can be overridden with a custom search
1076 path.
1077
1078 """
Brian Curtinc57a3452012-06-22 16:00:30 -05001079 # Check that a given file can be accessed with the correct mode.
1080 # Additionally check that `file` is not a directory, as on Windows
1081 # directories pass the os.access check.
1082 def _access_check(fn, mode):
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001083 return (os.path.exists(fn) and os.access(fn, mode)
1084 and not os.path.isdir(fn))
Brian Curtinc57a3452012-06-22 16:00:30 -05001085
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001086 # If we're given a path with a directory part, look it up directly rather
1087 # than referring to PATH directories. This includes checking relative to the
1088 # current directory, e.g. ./script
1089 if os.path.dirname(cmd):
1090 if _access_check(cmd, mode):
1091 return cmd
1092 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001093
1094 path = (path or os.environ.get("PATH", os.defpath)).split(os.pathsep)
1095
1096 if sys.platform == "win32":
1097 # The current directory takes precedence on Windows.
1098 if not os.curdir in path:
1099 path.insert(0, os.curdir)
1100
1101 # PATHEXT is necessary to check on Windows.
1102 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1103 # See if the given file matches any of the expected path extensions.
1104 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001105 # If it does match, only test that one, otherwise we have to try
1106 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001107 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1108 files = [cmd]
1109 else:
1110 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001111 else:
1112 # On other platforms you don't have things like PATHEXT to tell you
1113 # what file suffixes are executable, so just pass on cmd as-is.
1114 files = [cmd]
1115
1116 seen = set()
1117 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001118 normdir = os.path.normcase(dir)
1119 if not normdir in seen:
1120 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001121 for thefile in files:
1122 name = os.path.join(dir, thefile)
1123 if _access_check(name, mode):
1124 return name
1125 return None