blob: 5c1255a6713de61ba8180eb6e298cdbe862e18e2 [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
Georg Brandl2ee470f2008-07-16 12:55:28 +000010import fnmatch
Tarek Ziadé396fad72010-02-23 05:30:31 +000011import collections
Antoine Pitrou910bd512010-03-22 20:11:09 +000012import errno
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +020013
14try:
15 import zlib
16 del zlib
17 _ZLIB_SUPPORTED = True
18except ImportError:
19 _ZLIB_SUPPORTED = False
Tarek Ziadé396fad72010-02-23 05:30:31 +000020
21try:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000022 import bz2
Florent Xicluna54540ec2011-11-04 08:29:17 +010023 del bz2
Tarek Ziadéffa155a2010-04-29 13:34:35 +000024 _BZ2_SUPPORTED = True
Brett Cannoncd171c82013-07-04 17:43:24 -040025except ImportError:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000026 _BZ2_SUPPORTED = False
27
28try:
Serhiy Storchaka11213772014-08-06 18:50:19 +030029 import lzma
30 del lzma
31 _LZMA_SUPPORTED = True
32except ImportError:
33 _LZMA_SUPPORTED = False
34
35try:
Tarek Ziadé396fad72010-02-23 05:30:31 +000036 from pwd import getpwnam
Brett Cannoncd171c82013-07-04 17:43:24 -040037except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +000038 getpwnam = None
39
40try:
41 from grp import getgrnam
Brett Cannoncd171c82013-07-04 17:43:24 -040042except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +000043 getgrnam = None
Guido van Rossumc6360141990-10-13 19:23:40 +000044
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070045_WINDOWS = os.name == 'nt'
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020046posix = nt = None
47if os.name == 'posix':
48 import posix
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070049elif _WINDOWS:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020050 import nt
51
Inada Naoki4f190302019-03-02 13:31:01 +090052COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
Giampaolo Rodola413d9552019-05-30 14:05:41 +080053_USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070054_HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile") # macOS
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020055
Tarek Ziadéc3399782010-02-23 05:39:18 +000056__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
57 "copytree", "move", "rmtree", "Error", "SpecialFileError",
58 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000059 "register_archive_format", "unregister_archive_format",
60 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020061 "unregister_unpack_format", "unpack_archive",
Berker Peksag8083cd62014-11-01 11:04:06 +020062 "ignore_patterns", "chown", "which", "get_terminal_size",
63 "SameFileError"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020064 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000065
Andrew Svetlov3438fa42012-12-17 23:35:18 +020066class Error(OSError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000067 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000068
Hynek Schlawack48653762012-10-07 12:49:58 +020069class SameFileError(Error):
70 """Raised when source and destination are the same file."""
71
Andrew Svetlov3438fa42012-12-17 23:35:18 +020072class SpecialFileError(OSError):
Antoine Pitrou7fff0962009-05-01 21:09:44 +000073 """Raised when trying to do a kind of operation (e.g. copying) which is
74 not supported on a special file (e.g. a named pipe)"""
75
Andrew Svetlov3438fa42012-12-17 23:35:18 +020076class ExecError(OSError):
Tarek Ziadé396fad72010-02-23 05:30:31 +000077 """Raised when a command could not be executed"""
78
Andrew Svetlov3438fa42012-12-17 23:35:18 +020079class ReadError(OSError):
Tarek Ziadé6ac91722010-04-28 17:51:36 +000080 """Raised when an archive cannot be read"""
81
82class RegistryError(Exception):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +030083 """Raised when a registry operation with the archiving
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070084 and unpacking registries fails"""
Tarek Ziadé6ac91722010-04-28 17:51:36 +000085
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020086class _GiveupOnFastCopy(Exception):
87 """Raised as a signal to fallback on using raw read()/write()
88 file copy when fast-copy functions fail to do so.
89 """
Tarek Ziadé6ac91722010-04-28 17:51:36 +000090
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070091def _fastcopy_fcopyfile(fsrc, fdst, flags):
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020092 """Copy a regular file content or metadata by using high-performance
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070093 fcopyfile(3) syscall (macOS).
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020094 """
95 try:
96 infd = fsrc.fileno()
97 outfd = fdst.fileno()
98 except Exception as err:
99 raise _GiveupOnFastCopy(err) # not a regular file
100
101 try:
102 posix._fcopyfile(infd, outfd, flags)
103 except OSError as err:
104 err.filename = fsrc.name
105 err.filename2 = fdst.name
106 if err.errno in {errno.EINVAL, errno.ENOTSUP}:
107 raise _GiveupOnFastCopy(err)
108 else:
109 raise err from None
110
111def _fastcopy_sendfile(fsrc, fdst):
112 """Copy data from one regular mmap-like fd to another by using
113 high-performance sendfile(2) syscall.
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800114 This should work on Linux >= 2.6.33 only.
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200115 """
116 # Note: copyfileobj() is left alone in order to not introduce any
117 # unexpected breakage. Possible risks by using zero-copy calls
118 # in copyfileobj() are:
119 # - fdst cannot be open in "a"(ppend) mode
120 # - fsrc and fdst may be open in "t"(ext) mode
121 # - fsrc may be a BufferedReader (which hides unread data in a buffer),
122 # GzipFile (which decompresses data), HTTPResponse (which decodes
123 # chunks).
124 # - possibly others (e.g. encrypted fs/partition?)
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800125 global _USE_CP_SENDFILE
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200126 try:
127 infd = fsrc.fileno()
128 outfd = fdst.fileno()
129 except Exception as err:
130 raise _GiveupOnFastCopy(err) # not a regular file
131
132 # Hopefully the whole file will be copied in a single call.
133 # sendfile() is called in a loop 'till EOF is reached (0 return)
134 # so a bufsize smaller or bigger than the actual file size
135 # should not make any difference, also in case the file content
136 # changes while being copied.
137 try:
138 blocksize = max(os.fstat(infd).st_size, 2 ** 23) # min 8MB
139 except Exception:
140 blocksize = 2 ** 27 # 128MB
141
142 offset = 0
143 while True:
144 try:
145 sent = os.sendfile(outfd, infd, offset, blocksize)
146 except OSError as err:
147 # ...in oder to have a more informative exception.
148 err.filename = fsrc.name
149 err.filename2 = fdst.name
150
151 if err.errno == errno.ENOTSOCK:
152 # sendfile() on this platform (probably Linux < 2.6.33)
153 # does not support copies between regular files (only
154 # sockets).
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800155 _USE_CP_SENDFILE = False
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200156 raise _GiveupOnFastCopy(err)
157
158 if err.errno == errno.ENOSPC: # filesystem is full
159 raise err from None
160
161 # Give up on first call and if no data was copied.
162 if offset == 0 and os.lseek(outfd, 0, os.SEEK_CUR) == 0:
163 raise _GiveupOnFastCopy(err)
164
165 raise err
166 else:
167 if sent == 0:
168 break # EOF
169 offset += sent
170
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700171def _copyfileobj_readinto(fsrc, fdst, length=COPY_BUFSIZE):
172 """readinto()/memoryview() based variant of copyfileobj().
173 *fsrc* must support readinto() method and both files must be
174 open in binary mode.
175 """
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200176 # Localize variable access to minimize overhead.
177 fsrc_readinto = fsrc.readinto
178 fdst_write = fdst.write
179 with memoryview(bytearray(length)) as mv:
180 while True:
181 n = fsrc_readinto(mv)
182 if not n:
183 break
184 elif n < length:
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700185 with mv[:n] as smv:
186 fdst.write(smv)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200187 else:
188 fdst_write(mv)
189
Giampaolo Rodola3b0abb02019-02-24 15:46:40 -0800190def copyfileobj(fsrc, fdst, length=0):
Greg Stein42bb8b32000-07-12 09:55:30 +0000191 """copy data from file-like object fsrc to file-like object fdst"""
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700192 # Localize variable access to minimize overhead.
Giampaolo Rodola3b0abb02019-02-24 15:46:40 -0800193 if not length:
194 length = COPY_BUFSIZE
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700195 fsrc_read = fsrc.read
196 fdst_write = fdst.write
197 while True:
198 buf = fsrc_read(length)
199 if not buf:
200 break
201 fdst_write(buf)
Greg Stein42bb8b32000-07-12 09:55:30 +0000202
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000203def _samefile(src, dst):
204 # Macintosh, Unix.
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800205 if isinstance(src, os.DirEntry) and hasattr(os.path, 'samestat'):
206 try:
207 return os.path.samestat(src.stat(), os.stat(dst))
208 except OSError:
209 return False
210
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +0000211 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +0000212 try:
213 return os.path.samefile(src, dst)
214 except OSError:
215 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000216
217 # All other platforms: check for same pathname.
218 return (os.path.normcase(os.path.abspath(src)) ==
219 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +0000220
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800221def _stat(fn):
222 return fn.stat() if isinstance(fn, os.DirEntry) else os.stat(fn)
223
224def _islink(fn):
225 return fn.is_symlink() if isinstance(fn, os.DirEntry) else os.path.islink(fn)
226
Larry Hastingsb4038062012-07-15 10:57:38 -0700227def copyfile(src, dst, *, follow_symlinks=True):
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700228 """Copy data from src to dst in the most efficient way possible.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100229
Larry Hastingsb4038062012-07-15 10:57:38 -0700230 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +0100231 symlink will be created instead of copying the file it points to.
232
233 """
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000234 if _samefile(src, dst):
Hynek Schlawack48653762012-10-07 12:49:58 +0200235 raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000236
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700237 file_size = 0
238 for i, fn in enumerate([src, dst]):
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000239 try:
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800240 st = _stat(fn)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000241 except OSError:
242 # File most likely does not exist
243 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000244 else:
245 # XXX What about other special files? (sockets, devices...)
246 if stat.S_ISFIFO(st.st_mode):
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800247 fn = fn.path if isinstance(fn, os.DirEntry) else fn
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000248 raise SpecialFileError("`%s` is a named pipe" % fn)
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700249 if _WINDOWS and i == 0:
250 file_size = st.st_size
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000251
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800252 if not follow_symlinks and _islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100253 os.symlink(os.readlink(src), dst)
254 else:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200255 with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700256 # macOS
257 if _HAS_FCOPYFILE:
258 try:
259 _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA)
260 return dst
261 except _GiveupOnFastCopy:
262 pass
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800263 # Linux
264 elif _USE_CP_SENDFILE:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200265 try:
266 _fastcopy_sendfile(fsrc, fdst)
267 return dst
268 except _GiveupOnFastCopy:
269 pass
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700270 # Windows, see:
271 # https://github.com/python/cpython/pull/7160#discussion_r195405230
272 elif _WINDOWS and file_size > 0:
273 _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE))
274 return dst
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200275
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700276 copyfileobj(fsrc, fdst)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200277
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500278 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000279
Larry Hastingsb4038062012-07-15 10:57:38 -0700280def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100281 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000282
Larry Hastingsb4038062012-07-15 10:57:38 -0700283 If follow_symlinks is not set, symlinks aren't followed if and only
284 if both `src` and `dst` are symlinks. If `lchmod` isn't available
285 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100286
287 """
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800288 if not follow_symlinks and _islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100289 if hasattr(os, 'lchmod'):
290 stat_func, chmod_func = os.lstat, os.lchmod
291 else:
292 return
Antoine Pitrou78091e62011-12-29 18:54:15 +0100293 else:
Anthony Sottile8377cd42019-02-25 14:32:27 -0800294 stat_func, chmod_func = _stat, os.chmod
Antoine Pitrou78091e62011-12-29 18:54:15 +0100295
296 st = stat_func(src)
297 chmod_func(dst, stat.S_IMODE(st.st_mode))
298
Larry Hastingsad5ae042012-07-14 17:55:11 -0700299if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700300 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700301 """Copy extended filesystem attributes from `src` to `dst`.
302
303 Overwrite existing attributes.
304
Larry Hastingsb4038062012-07-15 10:57:38 -0700305 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700306
307 """
308
Hynek Schlawack0beab052013-02-05 08:22:44 +0100309 try:
310 names = os.listxattr(src, follow_symlinks=follow_symlinks)
311 except OSError as e:
Ying Wanga16387a2019-05-29 23:25:31 -0400312 if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL):
Hynek Schlawack0beab052013-02-05 08:22:44 +0100313 raise
314 return
315 for name in names:
Larry Hastingsad5ae042012-07-14 17:55:11 -0700316 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700317 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
318 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700319 except OSError as e:
Ying Wanga16387a2019-05-29 23:25:31 -0400320 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA,
321 errno.EINVAL):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700322 raise
323else:
324 def _copyxattr(*args, **kwargs):
325 pass
326
Larry Hastingsb4038062012-07-15 10:57:38 -0700327def copystat(src, dst, *, follow_symlinks=True):
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200328 """Copy file metadata
Antoine Pitrou78091e62011-12-29 18:54:15 +0100329
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200330 Copy the permission bits, last access time, last modification time, and
331 flags from `src` to `dst`. On Linux, copystat() also copies the "extended
332 attributes" where possible. The file contents, owner, and group are
Boris Verhovsky9488a522019-09-09 09:51:56 -0600333 unaffected. `src` and `dst` are path-like objects or path names given as
334 strings.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100335
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200336 If the optional flag `follow_symlinks` is not set, symlinks aren't
337 followed if and only if both `src` and `dst` are symlinks.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100338 """
Larry Hastings9cf065c2012-06-22 16:30:09 -0700339 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100340 pass
341
Larry Hastings9cf065c2012-06-22 16:30:09 -0700342 # follow symlinks (aka don't not follow symlinks)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800343 follow = follow_symlinks or not (_islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700344 if follow:
345 # use the real function if it exists
346 def lookup(name):
347 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100348 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700349 # use the real function only if it exists
350 # *and* it supports follow_symlinks
351 def lookup(name):
352 fn = getattr(os, name, _nop)
353 if fn in os.supports_follow_symlinks:
354 return fn
355 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100356
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800357 if isinstance(src, os.DirEntry):
358 st = src.stat(follow_symlinks=follow)
359 else:
360 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000361 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700362 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
363 follow_symlinks=follow)
Olexa Bilaniuk79efbb72019-05-09 22:22:06 -0500364 # We must copy extended attributes before the file is (potentially)
365 # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
366 _copyxattr(src, dst, follow_symlinks=follow)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700367 try:
368 lookup("chmod")(dst, mode, follow_symlinks=follow)
369 except NotImplementedError:
370 # if we got a NotImplementedError, it's because
371 # * follow_symlinks=False,
372 # * lchown() is unavailable, and
373 # * either
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300374 # * fchownat() is unavailable or
Larry Hastings9cf065c2012-06-22 16:30:09 -0700375 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
376 # (it returned ENOSUP.)
377 # therefore we're out of options--we simply cannot chown the
378 # symlink. give up, suppress the error.
379 # (which is what shutil always did in this circumstance.)
380 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100381 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000382 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700383 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000384 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700385 for err in 'EOPNOTSUPP', 'ENOTSUP':
386 if hasattr(errno, err) and why.errno == getattr(errno, err):
387 break
388 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000389 raise
Antoine Pitrou424246f2012-05-12 19:02:01 +0200390
Larry Hastingsb4038062012-07-15 10:57:38 -0700391def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500392 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000393
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000394 The destination may be a directory.
395
Larry Hastingsb4038062012-07-15 10:57:38 -0700396 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100397 resembles GNU's "cp -P src dst".
398
Hynek Schlawack48653762012-10-07 12:49:58 +0200399 If source and destination are the same file, a SameFileError will be
400 raised.
401
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000402 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000403 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000404 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700405 copyfile(src, dst, follow_symlinks=follow_symlinks)
406 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500407 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000408
Larry Hastingsb4038062012-07-15 10:57:38 -0700409def copy2(src, dst, *, follow_symlinks=True):
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200410 """Copy data and metadata. Return the file's destination.
411
412 Metadata is copied with copystat(). Please see the copystat function
413 for more information.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000414
415 The destination may be a directory.
416
Larry Hastingsb4038062012-07-15 10:57:38 -0700417 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100418 resembles GNU's "cp -P src dst".
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000419 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000420 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000421 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700422 copyfile(src, dst, follow_symlinks=follow_symlinks)
423 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500424 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000425
Georg Brandl2ee470f2008-07-16 12:55:28 +0000426def ignore_patterns(*patterns):
427 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000428
Georg Brandl2ee470f2008-07-16 12:55:28 +0000429 Patterns is a sequence of glob-style patterns
430 that are used to exclude files"""
431 def _ignore_patterns(path, names):
432 ignored_names = []
433 for pattern in patterns:
434 ignored_names.extend(fnmatch.filter(names, pattern))
435 return set(ignored_names)
436 return _ignore_patterns
437
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800438def _copytree(entries, src, dst, symlinks, ignore, copy_function,
jab9e00d9e2018-12-28 13:03:40 -0500439 ignore_dangling_symlinks, dirs_exist_ok=False):
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800440 if ignore is not None:
441 ignored_names = ignore(src, set(os.listdir(src)))
442 else:
443 ignored_names = set()
444
jab9e00d9e2018-12-28 13:03:40 -0500445 os.makedirs(dst, exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800446 errors = []
447 use_srcentry = copy_function is copy2 or copy_function is copy
448
449 for srcentry in entries:
450 if srcentry.name in ignored_names:
451 continue
452 srcname = os.path.join(src, srcentry.name)
453 dstname = os.path.join(dst, srcentry.name)
454 srcobj = srcentry if use_srcentry else srcname
455 try:
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700456 is_symlink = srcentry.is_symlink()
457 if is_symlink and os.name == 'nt':
458 # Special check for directory junctions, which appear as
459 # symlinks but we want to recurse.
460 lstat = srcentry.stat(follow_symlinks=False)
461 if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
462 is_symlink = False
463 if is_symlink:
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800464 linkto = os.readlink(srcname)
465 if symlinks:
466 # We can't just leave it to `copy_function` because legacy
467 # code with a custom `copy_function` may rely on copytree
468 # doing the right thing.
469 os.symlink(linkto, dstname)
470 copystat(srcobj, dstname, follow_symlinks=not symlinks)
471 else:
472 # ignore dangling symlink if the flag is on
473 if not os.path.exists(linkto) and ignore_dangling_symlinks:
474 continue
jab9e00d9e2018-12-28 13:03:40 -0500475 # otherwise let the copy occur. copy2 will raise an error
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800476 if srcentry.is_dir():
477 copytree(srcobj, dstname, symlinks, ignore,
jab9e00d9e2018-12-28 13:03:40 -0500478 copy_function, dirs_exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800479 else:
480 copy_function(srcobj, dstname)
481 elif srcentry.is_dir():
jab9e00d9e2018-12-28 13:03:40 -0500482 copytree(srcobj, dstname, symlinks, ignore, copy_function,
483 dirs_exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800484 else:
485 # Will raise a SpecialFileError for unsupported file types
Giampaolo Rodolac606a9c2019-02-26 12:04:41 +0100486 copy_function(srcobj, dstname)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800487 # catch the Error from the recursive copytree so that we can
488 # continue with other files
489 except Error as err:
490 errors.extend(err.args[0])
491 except OSError as why:
492 errors.append((srcname, dstname, str(why)))
493 try:
494 copystat(src, dst)
495 except OSError as why:
496 # Copying file access times may fail on Windows
497 if getattr(why, 'winerror', None) is None:
498 errors.append((src, dst, str(why)))
499 if errors:
500 raise Error(errors)
501 return dst
502
Tarek Ziadéfb437512010-04-20 08:57:33 +0000503def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
jab9e00d9e2018-12-28 13:03:40 -0500504 ignore_dangling_symlinks=False, dirs_exist_ok=False):
505 """Recursively copy a directory tree and return the destination directory.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000506
jab9e00d9e2018-12-28 13:03:40 -0500507 dirs_exist_ok dictates whether to raise an exception in case dst or any
508 missing parent directory already exists.
509
Neal Norwitza4c93b62003-02-23 21:36:32 +0000510 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000511
512 If the optional symlinks flag is true, symbolic links in the
513 source tree result in symbolic links in the destination tree; if
514 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000515 links are copied. If the file pointed by the symlink doesn't
516 exist, an exception will be added in the list of errors raised in
517 an Error exception at the end of the copy process.
518
519 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000520 want to silence this exception. Notice that this has no effect on
521 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000522
Georg Brandl2ee470f2008-07-16 12:55:28 +0000523 The optional ignore argument is a callable. If given, it
524 is called with the `src` parameter, which is the directory
525 being visited by copytree(), and `names` which is the list of
526 `src` contents, as returned by os.listdir():
527
528 callable(src, names) -> ignored_names
529
530 Since copytree() is called recursively, the callable will be
531 called once for each directory that is copied. It returns a
532 list of names relative to the `src` directory that should
533 not be copied.
534
Tarek Ziadé5340db32010-04-19 22:30:51 +0000535 The optional copy_function argument is a callable that will be used
536 to copy each file. It will be called with the source path and the
537 destination path as arguments. By default, copy2() is used, but any
538 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000539
540 """
Steve Dower60419a72019-06-24 08:42:54 -0700541 sys.audit("shutil.copytree", src, dst)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800542 with os.scandir(src) as entries:
543 return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
544 ignore=ignore, copy_function=copy_function,
jab9e00d9e2018-12-28 13:03:40 -0500545 ignore_dangling_symlinks=ignore_dangling_symlinks,
546 dirs_exist_ok=dirs_exist_ok)
Guido van Rossumd7673291998-02-06 21:38:09 +0000547
Ned Deily7fcc2082019-08-29 17:20:03 -0400548if hasattr(os.stat_result, 'st_file_attributes'):
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700549 # Special handling for directory junctions to make them behave like
550 # symlinks for shutil.rmtree, since in general they do not appear as
551 # regular links.
552 def _rmtree_isdir(entry):
553 try:
554 st = entry.stat(follow_symlinks=False)
555 return (stat.S_ISDIR(st.st_mode) and not
556 (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
557 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
558 except OSError:
559 return False
560
561 def _rmtree_islink(path):
562 try:
563 st = os.lstat(path)
564 return (stat.S_ISLNK(st.st_mode) or
565 (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
566 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
567 except OSError:
568 return False
569else:
570 def _rmtree_isdir(entry):
571 try:
572 return entry.is_dir(follow_symlinks=False)
573 except OSError:
574 return False
575
576 def _rmtree_islink(path):
577 return os.path.islink(path)
578
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200579# version vulnerable to race conditions
580def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000581 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200582 with os.scandir(path) as scandir_it:
583 entries = list(scandir_it)
Christian Heimes9bd667a2008-01-20 15:14:11 +0000584 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200585 onerror(os.scandir, path, sys.exc_info())
586 entries = []
587 for entry in entries:
588 fullname = entry.path
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700589 if _rmtree_isdir(entry):
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200590 try:
591 if entry.is_symlink():
592 # This can only happen if someone replaces
593 # a directory with a symlink after the call to
594 # os.scandir or entry.is_dir above.
595 raise OSError("Cannot call rmtree on a symbolic link")
596 except OSError:
597 onerror(os.path.islink, fullname, sys.exc_info())
598 continue
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200599 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000600 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000601 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200602 os.unlink(fullname)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200603 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200604 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000605 try:
606 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200607 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000608 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000609
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200610# Version using fd-based APIs to protect against races
611def _rmtree_safe_fd(topfd, path, onerror):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200612 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200613 with os.scandir(topfd) as scandir_it:
614 entries = list(scandir_it)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100615 except OSError as err:
616 err.filename = path
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200617 onerror(os.scandir, path, sys.exc_info())
618 return
619 for entry in entries:
620 fullname = os.path.join(path, entry.name)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200621 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200622 is_dir = entry.is_dir(follow_symlinks=False)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100623 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200624 is_dir = False
Serhiy Storchakae9b51c02019-05-31 11:30:37 +0300625 else:
626 if is_dir:
627 try:
628 orig_st = entry.stat(follow_symlinks=False)
629 is_dir = stat.S_ISDIR(orig_st.st_mode)
630 except OSError:
631 onerror(os.lstat, fullname, sys.exc_info())
632 continue
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200633 if is_dir:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200634 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200635 dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100636 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200637 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200638 else:
639 try:
640 if os.path.samestat(orig_st, os.fstat(dirfd)):
641 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200642 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200643 os.rmdir(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100644 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200645 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100646 else:
647 try:
648 # This can only happen if someone replaces
649 # a directory with a symlink after the call to
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200650 # os.scandir or stat.S_ISDIR above.
Hynek Schlawackb5501102012-12-10 09:11:25 +0100651 raise OSError("Cannot call rmtree on a symbolic "
652 "link")
653 except OSError:
654 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200655 finally:
656 os.close(dirfd)
657 else:
658 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200659 os.unlink(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100660 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200661 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200662
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200663_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
664 os.supports_dir_fd and
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200665 os.scandir in os.supports_fd and
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200666 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000667
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200668def rmtree(path, ignore_errors=False, onerror=None):
669 """Recursively delete a directory tree.
670
671 If ignore_errors is set, errors are ignored; otherwise, if onerror
672 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200673 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200674 path is the argument to that function that caused it to fail; and
675 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
676 is false and onerror is None, an exception is raised.
677
678 """
Steve Dower60419a72019-06-24 08:42:54 -0700679 sys.audit("shutil.rmtree", path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200680 if ignore_errors:
681 def onerror(*args):
682 pass
683 elif onerror is None:
684 def onerror(*args):
685 raise
686 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200687 # While the unsafe rmtree works fine on bytes, the fd based does not.
688 if isinstance(path, bytes):
689 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200690 # Note: To guard against symlink races, we use the standard
691 # lstat()/open()/fstat() trick.
692 try:
693 orig_st = os.lstat(path)
694 except Exception:
695 onerror(os.lstat, path, sys.exc_info())
696 return
697 try:
698 fd = os.open(path, os.O_RDONLY)
699 except Exception:
700 onerror(os.lstat, path, sys.exc_info())
701 return
702 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100703 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200704 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200705 try:
706 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200707 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200708 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200709 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100710 try:
711 # symlinks to directories are forbidden, see bug #1669
712 raise OSError("Cannot call rmtree on a symbolic link")
713 except OSError:
714 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200715 finally:
716 os.close(fd)
717 else:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200718 try:
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700719 if _rmtree_islink(path):
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200720 # symlinks to directories are forbidden, see bug #1669
721 raise OSError("Cannot call rmtree on a symbolic link")
722 except OSError:
723 onerror(os.path.islink, path, sys.exc_info())
724 # can't continue even if onerror hook returns
725 return
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200726 return _rmtree_unsafe(path, onerror)
727
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000728# Allow introspection of whether or not the hardening against symlink
729# attacks is supported on the current platform
730rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000731
Christian Heimesada8c3b2008-03-18 18:26:33 +0000732def _basename(path):
733 # A basename() variant which first strips the trailing slash, if present.
734 # Thus we always get the last component of the path, even for directories.
Serhiy Storchaka3a308b92014-02-11 10:30:59 +0200735 sep = os.path.sep + (os.path.altsep or '')
736 return os.path.basename(path.rstrip(sep))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000737
R David Murray6ffface2014-06-11 14:40:13 -0400738def move(src, dst, copy_function=copy2):
Christian Heimesada8c3b2008-03-18 18:26:33 +0000739 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500740 similar to the Unix "mv" command. Return the file or directory's
741 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000742
743 If the destination is a directory or a symlink to a directory, the source
744 is moved inside the directory. The destination path must not already
745 exist.
746
747 If the destination already exists but is not a directory, it may be
748 overwritten depending on os.rename() semantics.
749
750 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100751 Otherwise, src is copied to the destination and then removed. Symlinks are
752 recreated under the new name if os.rename() fails because of cross
753 filesystem renames.
754
R David Murray6ffface2014-06-11 14:40:13 -0400755 The optional `copy_function` argument is a callable that will be used
756 to copy the source or it will be delegated to `copytree`.
757 By default, copy2() is used, but any function that supports the same
758 signature (like copy()) can be used.
759
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000760 A lot more could be done here... A look at a mv.c shows a lot of
761 the issues this implementation glosses over.
762
763 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000764 real_dst = dst
765 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200766 if _samefile(src, dst):
767 # We might be on a case insensitive filesystem,
768 # perform the rename anyway.
769 os.rename(src, dst)
770 return
771
Christian Heimesada8c3b2008-03-18 18:26:33 +0000772 real_dst = os.path.join(dst, _basename(src))
773 if os.path.exists(real_dst):
774 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000775 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000776 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200777 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100778 if os.path.islink(src):
779 linkto = os.readlink(src)
780 os.symlink(linkto, real_dst)
781 os.unlink(src)
782 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000783 if _destinsrc(src, dst):
R David Murray6ffface2014-06-11 14:40:13 -0400784 raise Error("Cannot move a directory '%s' into itself"
785 " '%s'." % (src, dst))
786 copytree(src, real_dst, copy_function=copy_function,
787 symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000788 rmtree(src)
789 else:
R David Murray6ffface2014-06-11 14:40:13 -0400790 copy_function(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000791 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500792 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000793
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000794def _destinsrc(src, dst):
Berker Peksag3715da52014-09-18 05:11:15 +0300795 src = os.path.abspath(src)
796 dst = os.path.abspath(dst)
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000797 if not src.endswith(os.path.sep):
798 src += os.path.sep
799 if not dst.endswith(os.path.sep):
800 dst += os.path.sep
801 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000802
803def _get_gid(name):
804 """Returns a gid, given a group name."""
805 if getgrnam is None or name is None:
806 return None
807 try:
808 result = getgrnam(name)
809 except KeyError:
810 result = None
811 if result is not None:
812 return result[2]
813 return None
814
815def _get_uid(name):
816 """Returns an uid, given a user name."""
817 if getpwnam is None or name is None:
818 return None
819 try:
820 result = getpwnam(name)
821 except KeyError:
822 result = None
823 if result is not None:
824 return result[2]
825 return None
826
827def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
828 owner=None, group=None, logger=None):
829 """Create a (possibly compressed) tar file from all the files under
830 'base_dir'.
831
Serhiy Storchaka11213772014-08-06 18:50:19 +0300832 'compress' must be "gzip" (the default), "bzip2", "xz", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000833
834 'owner' and 'group' can be used to define an owner and a group for the
835 archive that is being built. If not provided, the current owner and group
836 will be used.
837
Éric Araujo4433a5f2010-12-15 20:26:30 +0000838 The output tar file will be named 'base_name' + ".tar", possibly plus
Serhiy Storchaka11213772014-08-06 18:50:19 +0300839 the appropriate compression extension (".gz", ".bz2", or ".xz").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000840
841 Returns the output filename.
842 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200843 if compress is None:
844 tar_compression = ''
845 elif _ZLIB_SUPPORTED and compress == 'gzip':
846 tar_compression = 'gz'
847 elif _BZ2_SUPPORTED and compress == 'bzip2':
848 tar_compression = 'bz2'
849 elif _LZMA_SUPPORTED and compress == 'xz':
850 tar_compression = 'xz'
851 else:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000852 raise ValueError("bad value for 'compress', or compression format not "
853 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000854
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200855 import tarfile # late import for breaking circular dependency
856
857 compress_ext = '.' + tar_compression if compress else ''
858 archive_name = base_name + '.tar' + compress_ext
Tarek Ziadé396fad72010-02-23 05:30:31 +0000859 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000860
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200861 if archive_dir and not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000862 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200863 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000864 if not dry_run:
865 os.makedirs(archive_dir)
866
Tarek Ziadé396fad72010-02-23 05:30:31 +0000867 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000868 if logger is not None:
869 logger.info('Creating tar archive')
870
871 uid = _get_uid(owner)
872 gid = _get_gid(group)
873
874 def _set_uid_gid(tarinfo):
875 if gid is not None:
876 tarinfo.gid = gid
877 tarinfo.gname = group
878 if uid is not None:
879 tarinfo.uid = uid
880 tarinfo.uname = owner
881 return tarinfo
882
883 if not dry_run:
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200884 tar = tarfile.open(archive_name, 'w|%s' % tar_compression)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000885 try:
886 tar.add(base_dir, filter=_set_uid_gid)
887 finally:
888 tar.close()
889
Tarek Ziadé396fad72010-02-23 05:30:31 +0000890 return archive_name
891
Tarek Ziadé396fad72010-02-23 05:30:31 +0000892def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
893 """Create a zip file from all the files under 'base_dir'.
894
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200895 The output zip file will be named 'base_name' + ".zip". Returns the
896 name of the output zip file.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000897 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200898 import zipfile # late import for breaking circular dependency
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400899
Tarek Ziadé396fad72010-02-23 05:30:31 +0000900 zip_filename = base_name + ".zip"
901 archive_dir = os.path.dirname(base_name)
902
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200903 if archive_dir and not os.path.exists(archive_dir):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000904 if logger is not None:
905 logger.info("creating %s", archive_dir)
906 if not dry_run:
907 os.makedirs(archive_dir)
908
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400909 if logger is not None:
910 logger.info("creating '%s' and adding '%s' to it",
911 zip_filename, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000912
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400913 if not dry_run:
914 with zipfile.ZipFile(zip_filename, "w",
915 compression=zipfile.ZIP_DEFLATED) as zf:
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300916 path = os.path.normpath(base_dir)
Serhiy Storchaka666de772016-10-23 15:55:09 +0300917 if path != os.curdir:
918 zf.write(path, path)
919 if logger is not None:
920 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400921 for dirpath, dirnames, filenames in os.walk(base_dir):
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300922 for name in sorted(dirnames):
923 path = os.path.normpath(os.path.join(dirpath, name))
924 zf.write(path, path)
925 if logger is not None:
926 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400927 for name in filenames:
928 path = os.path.normpath(os.path.join(dirpath, name))
929 if os.path.isfile(path):
930 zf.write(path, path)
931 if logger is not None:
932 logger.info("adding '%s'", path)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000933
934 return zip_filename
935
936_ARCHIVE_FORMATS = {
Tarek Ziadé396fad72010-02-23 05:30:31 +0000937 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200938}
939
940if _ZLIB_SUPPORTED:
941 _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')],
942 "gzip'ed tar-file")
943 _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000944
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000945if _BZ2_SUPPORTED:
946 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
947 "bzip2'ed tar-file")
948
Serhiy Storchaka11213772014-08-06 18:50:19 +0300949if _LZMA_SUPPORTED:
950 _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')],
951 "xz'ed tar-file")
952
Tarek Ziadé396fad72010-02-23 05:30:31 +0000953def get_archive_formats():
954 """Returns a list of supported formats for archiving and unarchiving.
955
956 Each element of the returned sequence is a tuple (name, description)
957 """
958 formats = [(name, registry[2]) for name, registry in
959 _ARCHIVE_FORMATS.items()]
960 formats.sort()
961 return formats
962
963def register_archive_format(name, function, extra_args=None, description=''):
964 """Registers an archive format.
965
966 name is the name of the format. function is the callable that will be
967 used to create archives. If provided, extra_args is a sequence of
968 (name, value) tuples that will be passed as arguments to the callable.
969 description can be provided to describe the format, and will be returned
970 by the get_archive_formats() function.
971 """
972 if extra_args is None:
973 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200974 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000975 raise TypeError('The %s object is not callable' % function)
976 if not isinstance(extra_args, (tuple, list)):
977 raise TypeError('extra_args needs to be a sequence')
978 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200979 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000980 raise TypeError('extra_args elements are : (arg_name, value)')
981
982 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
983
984def unregister_archive_format(name):
985 del _ARCHIVE_FORMATS[name]
986
987def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
988 dry_run=0, owner=None, group=None, logger=None):
989 """Create an archive file (eg. zip or tar).
990
991 'base_name' is the name of the file to create, minus any format-specific
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200992 extension; 'format' is the archive format: one of "zip", "tar", "gztar",
993 "bztar", or "xztar". Or any other registered format.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000994
995 'root_dir' is a directory that will be the root directory of the
996 archive; ie. we typically chdir into 'root_dir' before creating the
997 archive. 'base_dir' is the directory where we start archiving from;
998 ie. 'base_dir' will be the common prefix of all files and
999 directories in the archive. 'root_dir' and 'base_dir' both default
1000 to the current directory. Returns the name of the archive file.
1001
1002 'owner' and 'group' are used when creating a tar archive. By default,
1003 uses the current owner and group.
1004 """
Steve Dower60419a72019-06-24 08:42:54 -07001005 sys.audit("shutil.make_archive", base_name, format, root_dir, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +00001006 save_cwd = os.getcwd()
1007 if root_dir is not None:
1008 if logger is not None:
1009 logger.debug("changing into '%s'", root_dir)
1010 base_name = os.path.abspath(base_name)
1011 if not dry_run:
1012 os.chdir(root_dir)
1013
1014 if base_dir is None:
1015 base_dir = os.curdir
1016
1017 kwargs = {'dry_run': dry_run, 'logger': logger}
1018
1019 try:
1020 format_info = _ARCHIVE_FORMATS[format]
1021 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +03001022 raise ValueError("unknown archive format '%s'" % format) from None
Tarek Ziadé396fad72010-02-23 05:30:31 +00001023
1024 func = format_info[0]
1025 for arg, val in format_info[1]:
1026 kwargs[arg] = val
1027
1028 if format != 'zip':
1029 kwargs['owner'] = owner
1030 kwargs['group'] = group
1031
1032 try:
1033 filename = func(base_name, base_dir, **kwargs)
1034 finally:
1035 if root_dir is not None:
1036 if logger is not None:
1037 logger.debug("changing back to '%s'", save_cwd)
1038 os.chdir(save_cwd)
1039
1040 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001041
1042
1043def get_unpack_formats():
1044 """Returns a list of supported formats for unpacking.
1045
1046 Each element of the returned sequence is a tuple
1047 (name, extensions, description)
1048 """
1049 formats = [(name, info[0], info[3]) for name, info in
1050 _UNPACK_FORMATS.items()]
1051 formats.sort()
1052 return formats
1053
1054def _check_unpack_options(extensions, function, extra_args):
1055 """Checks what gets registered as an unpacker."""
1056 # first make sure no other unpacker is registered for this extension
1057 existing_extensions = {}
1058 for name, info in _UNPACK_FORMATS.items():
1059 for ext in info[0]:
1060 existing_extensions[ext] = name
1061
1062 for extension in extensions:
1063 if extension in existing_extensions:
1064 msg = '%s is already registered for "%s"'
1065 raise RegistryError(msg % (extension,
1066 existing_extensions[extension]))
1067
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001068 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001069 raise TypeError('The registered function must be a callable')
1070
1071
1072def register_unpack_format(name, extensions, function, extra_args=None,
1073 description=''):
1074 """Registers an unpack format.
1075
1076 `name` is the name of the format. `extensions` is a list of extensions
1077 corresponding to the format.
1078
1079 `function` is the callable that will be
1080 used to unpack archives. The callable will receive archives to unpack.
1081 If it's unable to handle an archive, it needs to raise a ReadError
1082 exception.
1083
1084 If provided, `extra_args` is a sequence of
1085 (name, value) tuples that will be passed as arguments to the callable.
1086 description can be provided to describe the format, and will be returned
1087 by the get_unpack_formats() function.
1088 """
1089 if extra_args is None:
1090 extra_args = []
1091 _check_unpack_options(extensions, function, extra_args)
1092 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
1093
1094def unregister_unpack_format(name):
Martin Pantereb995702016-07-28 01:11:04 +00001095 """Removes the pack format from the registry."""
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001096 del _UNPACK_FORMATS[name]
1097
1098def _ensure_directory(path):
1099 """Ensure that the parent directory of `path` exists"""
1100 dirname = os.path.dirname(path)
1101 if not os.path.isdir(dirname):
1102 os.makedirs(dirname)
1103
1104def _unpack_zipfile(filename, extract_dir):
1105 """Unpack zip `filename` to `extract_dir`
1106 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001107 import zipfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001108
1109 if not zipfile.is_zipfile(filename):
1110 raise ReadError("%s is not a zip file" % filename)
1111
1112 zip = zipfile.ZipFile(filename)
1113 try:
1114 for info in zip.infolist():
1115 name = info.filename
1116
1117 # don't extract absolute paths or ones with .. in them
1118 if name.startswith('/') or '..' in name:
1119 continue
1120
1121 target = os.path.join(extract_dir, *name.split('/'))
1122 if not target:
1123 continue
1124
1125 _ensure_directory(target)
1126 if not name.endswith('/'):
1127 # file
1128 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +02001129 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001130 try:
1131 f.write(data)
1132 finally:
1133 f.close()
1134 del data
1135 finally:
1136 zip.close()
1137
1138def _unpack_tarfile(filename, extract_dir):
Serhiy Storchaka11213772014-08-06 18:50:19 +03001139 """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001140 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001141 import tarfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001142 try:
1143 tarobj = tarfile.open(filename)
1144 except tarfile.TarError:
1145 raise ReadError(
1146 "%s is not a compressed or uncompressed tar file" % filename)
1147 try:
1148 tarobj.extractall(extract_dir)
1149 finally:
1150 tarobj.close()
1151
1152_UNPACK_FORMATS = {
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001153 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001154 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"),
1155}
1156
1157if _ZLIB_SUPPORTED:
1158 _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [],
1159 "gzip'ed tar-file")
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001160
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001161if _BZ2_SUPPORTED:
Serhiy Storchaka11213772014-08-06 18:50:19 +03001162 _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001163 "bzip2'ed tar-file")
1164
Serhiy Storchaka11213772014-08-06 18:50:19 +03001165if _LZMA_SUPPORTED:
1166 _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [],
1167 "xz'ed tar-file")
1168
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001169def _find_unpack_format(filename):
1170 for name, info in _UNPACK_FORMATS.items():
1171 for extension in info[0]:
1172 if filename.endswith(extension):
1173 return name
1174 return None
1175
1176def unpack_archive(filename, extract_dir=None, format=None):
1177 """Unpack an archive.
1178
1179 `filename` is the name of the archive.
1180
1181 `extract_dir` is the name of the target directory, where the archive
1182 is unpacked. If not provided, the current working directory is used.
1183
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001184 `format` is the archive format: one of "zip", "tar", "gztar", "bztar",
1185 or "xztar". Or any other registered format. If not provided,
1186 unpack_archive will use the filename extension and see if an unpacker
1187 was registered for that extension.
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001188
1189 In case none is found, a ValueError is raised.
1190 """
1191 if extract_dir is None:
1192 extract_dir = os.getcwd()
1193
Jelle Zijlstraa12df7b2017-05-05 14:27:12 -07001194 extract_dir = os.fspath(extract_dir)
1195 filename = os.fspath(filename)
1196
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001197 if format is not None:
1198 try:
1199 format_info = _UNPACK_FORMATS[format]
1200 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +03001201 raise ValueError("Unknown unpack format '{0}'".format(format)) from None
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001202
Nick Coghlanabf202d2011-03-16 13:52:20 -04001203 func = format_info[1]
1204 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001205 else:
1206 # we need to look at the registered unpackers supported extensions
1207 format = _find_unpack_format(filename)
1208 if format is None:
1209 raise ReadError("Unknown archive format '{0}'".format(filename))
1210
1211 func = _UNPACK_FORMATS[format][1]
1212 kwargs = dict(_UNPACK_FORMATS[format][2])
1213 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001214
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001215
1216if hasattr(os, 'statvfs'):
1217
1218 __all__.append('disk_usage')
1219 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Raymond Hettinger5b798ab2015-08-17 22:04:45 -07001220 _ntuple_diskusage.total.__doc__ = 'Total space in bytes'
1221 _ntuple_diskusage.used.__doc__ = 'Used space in bytes'
1222 _ntuple_diskusage.free.__doc__ = 'Free space in bytes'
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001223
1224 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001225 """Return disk usage statistics about the given path.
1226
Sandro Tosif8ae4fa2012-04-23 20:07:15 +02001227 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001228 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001229 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001230 st = os.statvfs(path)
1231 free = st.f_bavail * st.f_frsize
1232 total = st.f_blocks * st.f_frsize
1233 used = (st.f_blocks - st.f_bfree) * st.f_frsize
1234 return _ntuple_diskusage(total, used, free)
1235
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -07001236elif _WINDOWS:
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001237
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001238 __all__.append('disk_usage')
1239 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1240
1241 def disk_usage(path):
1242 """Return disk usage statistics about the given path.
1243
Ezio Melotti30b9d5d2013-08-17 15:50:46 +03001244 Returned values is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001245 'free', which are the amount of total, used and free space, in bytes.
1246 """
1247 total, free = nt._getdiskusage(path)
1248 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001249 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +02001250
Éric Araujo0ac4a5d2011-09-01 08:31:51 +02001251
Sandro Tosid902a142011-08-22 23:28:27 +02001252def chown(path, user=None, group=None):
1253 """Change owner user and group of the given path.
1254
1255 user and group can be the uid/gid or the user/group names, and in that case,
1256 they are converted to their respective uid/gid.
1257 """
1258
1259 if user is None and group is None:
1260 raise ValueError("user and/or group must be set")
1261
1262 _user = user
1263 _group = group
1264
1265 # -1 means don't change it
1266 if user is None:
1267 _user = -1
1268 # user can either be an int (the uid) or a string (the system username)
1269 elif isinstance(user, str):
1270 _user = _get_uid(user)
1271 if _user is None:
1272 raise LookupError("no such user: {!r}".format(user))
1273
1274 if group is None:
1275 _group = -1
1276 elif not isinstance(group, int):
1277 _group = _get_gid(group)
1278 if _group is None:
1279 raise LookupError("no such group: {!r}".format(group))
1280
1281 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001282
1283def get_terminal_size(fallback=(80, 24)):
1284 """Get the size of the terminal window.
1285
1286 For each of the two dimensions, the environment variable, COLUMNS
1287 and LINES respectively, is checked. If the variable is defined and
1288 the value is a positive integer, it is used.
1289
1290 When COLUMNS or LINES is not defined, which is the common case,
1291 the terminal connected to sys.__stdout__ is queried
1292 by invoking os.get_terminal_size.
1293
1294 If the terminal size cannot be successfully queried, either because
1295 the system doesn't support querying, or because we are not
1296 connected to a terminal, the value given in fallback parameter
1297 is used. Fallback defaults to (80, 24) which is the default
1298 size used by many terminal emulators.
1299
1300 The value returned is a named tuple of type os.terminal_size.
1301 """
1302 # columns, lines are the working values
1303 try:
1304 columns = int(os.environ['COLUMNS'])
1305 except (KeyError, ValueError):
1306 columns = 0
1307
1308 try:
1309 lines = int(os.environ['LINES'])
1310 except (KeyError, ValueError):
1311 lines = 0
1312
1313 # only query if necessary
1314 if columns <= 0 or lines <= 0:
1315 try:
1316 size = os.get_terminal_size(sys.__stdout__.fileno())
Serhiy Storchakad30829d2016-04-24 09:58:43 +03001317 except (AttributeError, ValueError, OSError):
1318 # stdout is None, closed, detached, or not a terminal, or
1319 # os.get_terminal_size() is unsupported
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001320 size = os.terminal_size(fallback)
1321 if columns <= 0:
1322 columns = size.columns
1323 if lines <= 0:
1324 lines = size.lines
1325
1326 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001327
Cheryl Sabella5680f652019-02-13 06:25:10 -05001328
1329# Check that a given file can be accessed with the correct mode.
1330# Additionally check that `file` is not a directory, as on Windows
1331# directories pass the os.access check.
1332def _access_check(fn, mode):
1333 return (os.path.exists(fn) and os.access(fn, mode)
1334 and not os.path.isdir(fn))
1335
1336
Brian Curtinc57a3452012-06-22 16:00:30 -05001337def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001338 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001339 conforms to the given mode on the PATH, or None if there is no such
1340 file.
1341
1342 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1343 of os.environ.get("PATH"), or can be overridden with a custom search
1344 path.
1345
1346 """
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001347 # If we're given a path with a directory part, look it up directly rather
1348 # than referring to PATH directories. This includes checking relative to the
1349 # current directory, e.g. ./script
1350 if os.path.dirname(cmd):
1351 if _access_check(cmd, mode):
1352 return cmd
1353 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001354
Cheryl Sabella5680f652019-02-13 06:25:10 -05001355 use_bytes = isinstance(cmd, bytes)
1356
Barry Warsaw618738b2013-04-16 11:05:03 -04001357 if path is None:
Victor Stinner228a3c92019-04-17 16:26:36 +02001358 path = os.environ.get("PATH", None)
1359 if path is None:
1360 try:
1361 path = os.confstr("CS_PATH")
1362 except (AttributeError, ValueError):
1363 # os.confstr() or CS_PATH is not available
1364 path = os.defpath
1365 # bpo-35755: Don't use os.defpath if the PATH environment variable is
Victor Stinner197f0442019-04-17 17:44:06 +02001366 # set to an empty string
Victor Stinner228a3c92019-04-17 16:26:36 +02001367
1368 # PATH='' doesn't match, whereas PATH=':' looks in the current directory
Barry Warsaw618738b2013-04-16 11:05:03 -04001369 if not path:
1370 return None
Victor Stinner228a3c92019-04-17 16:26:36 +02001371
Cheryl Sabella5680f652019-02-13 06:25:10 -05001372 if use_bytes:
1373 path = os.fsencode(path)
1374 path = path.split(os.fsencode(os.pathsep))
1375 else:
1376 path = os.fsdecode(path)
1377 path = path.split(os.pathsep)
Brian Curtinc57a3452012-06-22 16:00:30 -05001378
1379 if sys.platform == "win32":
1380 # The current directory takes precedence on Windows.
Cheryl Sabella5680f652019-02-13 06:25:10 -05001381 curdir = os.curdir
1382 if use_bytes:
1383 curdir = os.fsencode(curdir)
1384 if curdir not in path:
1385 path.insert(0, curdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001386
1387 # PATHEXT is necessary to check on Windows.
1388 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
Cheryl Sabella5680f652019-02-13 06:25:10 -05001389 if use_bytes:
1390 pathext = [os.fsencode(ext) for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001391 # See if the given file matches any of the expected path extensions.
1392 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001393 # If it does match, only test that one, otherwise we have to try
1394 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001395 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1396 files = [cmd]
1397 else:
1398 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001399 else:
1400 # On other platforms you don't have things like PATHEXT to tell you
1401 # what file suffixes are executable, so just pass on cmd as-is.
1402 files = [cmd]
1403
1404 seen = set()
1405 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001406 normdir = os.path.normcase(dir)
1407 if not normdir in seen:
1408 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001409 for thefile in files:
1410 name = os.path.join(dir, thefile)
1411 if _access_check(name, mode):
1412 return name
1413 return None