annotate Lib/shutil.py @ 80661:94de77bd0b4b 2.7

Issue #16194: document imp.load_dynamic problems when read several extension modules from the same binary object file.
author Andrew Svetlov <andrew.svetlov@gmail.com>
date Thu, 29 Nov 2012 19:51:28 +0200
parents fe3d113e139d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
59058
b52e3ff0a4c8 completed the __all__ list and changed the module doctest
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59053
diff changeset
1 """Utility functions for copying and archiving files and directory trees.
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
2
11202
7eeeb0d2b0a4 Typo in comment (on Mac, it's the *resource* fork that's not copied,
Guido van Rossum <guido@python.org>
parents: 10289
diff changeset
3 XXX The functions here don't copy the resource fork or other metadata on Mac.
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
4
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
5 """
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
6
771
2e82dd0f8a9e posix -> os
Guido van Rossum <guido@python.org>
parents: 363
diff changeset
7 import os
10289
1e766de714de Add import sys, needed by reference to sys.exc_info() in rmtree().
Guido van Rossum <guido@python.org>
parents: 9872
diff changeset
8 import sys
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
9 import stat
32386
686e5d38be42 shutil.move() will raise an exception when trying to move a directory into
Brett Cannon <bcannon@gmail.com>
parents: 28025
diff changeset
10 from os.path import abspath
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
11 import fnmatch
59431
e2d41079d059 Fix some py3k warnings in the standard library.
Florent Xicluna <florent.xicluna@gmail.com>
parents: 59058
diff changeset
12 import collections
59917
e3fdfdb1a8ff Merged revisions 79299 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 51179
diff changeset
13 import errno
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
14
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
15 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
16 from pwd import getpwnam
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
17 except ImportError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
18 getpwnam = None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
19
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
20 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
21 from grp import getgrnam
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
22 except ImportError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
23 getgrnam = None
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
24
59058
b52e3ff0a4c8 completed the __all__ list and changed the module doctest
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59053
diff changeset
25 __all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
b52e3ff0a4c8 completed the __all__ list and changed the module doctest
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59053
diff changeset
26 "copytree", "move", "rmtree", "Error", "SpecialFileError",
b52e3ff0a4c8 completed the __all__ list and changed the module doctest
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59053
diff changeset
27 "ExecError", "make_archive", "get_archive_formats",
72087
bb214afa366f Add missing name in shutil.__all__
Éric Araujo <merwok@netwok.org>
parents: 71956
diff changeset
28 "register_archive_format", "unregister_archive_format",
bb214afa366f Add missing name in shutil.__all__
Éric Araujo <merwok@netwok.org>
parents: 71956
diff changeset
29 "ignore_patterns"]
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
30
35505
26ba3d4f4fc4 No need to import exceptions, they are builtins
Neal Norwitz <nnorwitz@gmail.com>
parents: 35501
diff changeset
31 class Error(EnvironmentError):
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
32 pass
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
33
53652
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
34 class SpecialFileError(EnvironmentError):
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
35 """Raised when trying to do a kind of operation (e.g. copying) which is
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
36 not supported on a special file (e.g. a named pipe)"""
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
37
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
38 class ExecError(EnvironmentError):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
39 """Raised when a command could not be executed"""
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
40
48216
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
41 try:
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
42 WindowsError
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
43 except NameError:
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
44 WindowsError = None
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
45
13571
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
46 def copyfileobj(fsrc, fdst, length=16*1024):
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
47 """copy data from file-like object fsrc to file-like object fdst"""
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
48 while 1:
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
49 buf = fsrc.read(length)
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
50 if not buf:
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
51 break
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
52 fdst.write(buf)
3a8c670309a2 apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents: 12285
diff changeset
53
33124
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
54 def _samefile(src, dst):
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
55 # Macintosh, Unix.
60725
bcfb6badff88 few pep8 fixes
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59916
diff changeset
56 if hasattr(os.path, 'samefile'):
33128
c2384601a241 Catch OSError raised when src or dst argument to os.path.samefile doesn't
Johannes Gijsbers <jlg@dds.nl>
parents: 33124
diff changeset
57 try:
c2384601a241 Catch OSError raised when src or dst argument to os.path.samefile doesn't
Johannes Gijsbers <jlg@dds.nl>
parents: 33124
diff changeset
58 return os.path.samefile(src, dst)
c2384601a241 Catch OSError raised when src or dst argument to os.path.samefile doesn't
Johannes Gijsbers <jlg@dds.nl>
parents: 33124
diff changeset
59 except OSError:
c2384601a241 Catch OSError raised when src or dst argument to os.path.samefile doesn't
Johannes Gijsbers <jlg@dds.nl>
parents: 33124
diff changeset
60 return False
33124
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
61
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
62 # All other platforms: check for same pathname.
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
63 return (os.path.normcase(os.path.abspath(src)) ==
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
64 os.path.normcase(os.path.abspath(dst)))
15872
3685ef2a55a4 Whitespace normalization.
Tim Peters <tim.peters@gmail.com>
parents: 13571
diff changeset
65
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
66 def copyfile(src, dst):
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
67 """Copy data from src to dst"""
33124
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
68 if _samefile(src, dst):
61285
f0fa944b15c0 Merged revisions 80830 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59917
diff changeset
69 raise Error("`%s` and `%s` are the same file" % (src, dst))
33124
dc647df53921 Raise an exception when src and dst refer to the same file via a hard link or a
Johannes Gijsbers <jlg@dds.nl>
parents: 32652
diff changeset
70
53652
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
71 for fn in [src, dst]:
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
72 try:
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
73 st = os.stat(fn)
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
74 except OSError:
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
75 # File most likely does not exist
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
76 pass
54593
602559fa5297 only test for named pipe when os.stat doesn't raise #6209
Benjamin Peterson <benjamin@python.org>
parents: 53652
diff changeset
77 else:
602559fa5297 only test for named pipe when os.stat doesn't raise #6209
Benjamin Peterson <benjamin@python.org>
parents: 53652
diff changeset
78 # XXX What about other special files? (sockets, devices...)
602559fa5297 only test for named pipe when os.stat doesn't raise #6209
Benjamin Peterson <benjamin@python.org>
parents: 53652
diff changeset
79 if stat.S_ISFIFO(st.st_mode):
602559fa5297 only test for named pipe when os.stat doesn't raise #6209
Benjamin Peterson <benjamin@python.org>
parents: 53652
diff changeset
80 raise SpecialFileError("`%s` is a named pipe" % fn)
61291
e3e466f53f9e removed non needed lines
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 61284
diff changeset
81
61285
f0fa944b15c0 Merged revisions 80830 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59917
diff changeset
82 with open(src, 'rb') as fsrc:
f0fa944b15c0 Merged revisions 80830 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59917
diff changeset
83 with open(dst, 'wb') as fdst:
f0fa944b15c0 Merged revisions 80830 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 59917
diff changeset
84 copyfileobj(fsrc, fdst)
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
85
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
86 def copymode(src, dst):
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
87 """Copy mode bits from src to dst"""
16084
4c307a12dcb9 Patch #103342: Make shutil.copytree more useful under Jython.
Tim Peters <tim.peters@gmail.com>
parents: 15872
diff changeset
88 if hasattr(os, 'chmod'):
4c307a12dcb9 Patch #103342: Make shutil.copytree more useful under Jython.
Tim Peters <tim.peters@gmail.com>
parents: 15872
diff changeset
89 st = os.stat(src)
23697
c0e8c07ae1d6 Replace obsolete stat module constants with
Walter Dörwald <walter@livinglogic.de>
parents: 23627
diff changeset
90 mode = stat.S_IMODE(st.st_mode)
16084
4c307a12dcb9 Patch #103342: Make shutil.copytree more useful under Jython.
Tim Peters <tim.peters@gmail.com>
parents: 15872
diff changeset
91 os.chmod(dst, mode)
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
92
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
93 def copystat(src, dst):
40872
53fd144a3f1a Patch #1490190: posixmodule now includes os.chflags() and os.lchflags()
Martin v. Löwis <martin@v.loewis.de>
parents: 39307
diff changeset
94 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
95 st = os.stat(src)
23697
c0e8c07ae1d6 Replace obsolete stat module constants with
Walter Dörwald <walter@livinglogic.de>
parents: 23627
diff changeset
96 mode = stat.S_IMODE(st.st_mode)
16084
4c307a12dcb9 Patch #103342: Make shutil.copytree more useful under Jython.
Tim Peters <tim.peters@gmail.com>
parents: 15872
diff changeset
97 if hasattr(os, 'utime'):
23697
c0e8c07ae1d6 Replace obsolete stat module constants with
Walter Dörwald <walter@livinglogic.de>
parents: 23627
diff changeset
98 os.utime(dst, (st.st_atime, st.st_mtime))
16084
4c307a12dcb9 Patch #103342: Make shutil.copytree more useful under Jython.
Tim Peters <tim.peters@gmail.com>
parents: 15872
diff changeset
99 if hasattr(os, 'chmod'):
4c307a12dcb9 Patch #103342: Make shutil.copytree more useful under Jython.
Tim Peters <tim.peters@gmail.com>
parents: 15872
diff changeset
100 os.chmod(dst, mode)
40872
53fd144a3f1a Patch #1490190: posixmodule now includes os.chflags() and os.lchflags()
Martin v. Löwis <martin@v.loewis.de>
parents: 39307
diff changeset
101 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
59917
e3fdfdb1a8ff Merged revisions 79299 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 51179
diff changeset
102 try:
e3fdfdb1a8ff Merged revisions 79299 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 51179
diff changeset
103 os.chflags(dst, st.st_flags)
e3fdfdb1a8ff Merged revisions 79299 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 51179
diff changeset
104 except OSError, why:
76869
e12efebc3ba6 Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents: 72087
diff changeset
105 for err in 'EOPNOTSUPP', 'ENOTSUP':
e12efebc3ba6 Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents: 72087
diff changeset
106 if hasattr(errno, err) and why.errno == getattr(errno, err):
e12efebc3ba6 Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents: 72087
diff changeset
107 break
e12efebc3ba6 Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents: 72087
diff changeset
108 else:
59917
e3fdfdb1a8ff Merged revisions 79299 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 51179
diff changeset
109 raise
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
110
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
111 def copy(src, dst):
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
112 """Copy data and mode bits ("cp src dst").
15872
3685ef2a55a4 Whitespace normalization.
Tim Peters <tim.peters@gmail.com>
parents: 13571
diff changeset
113
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
114 The destination may be a directory.
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
115
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
116 """
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
117 if os.path.isdir(dst):
7755
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
118 dst = os.path.join(dst, os.path.basename(src))
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
119 copyfile(src, dst)
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
120 copymode(src, dst)
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
121
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
122 def copy2(src, dst):
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
123 """Copy data and all stat info ("cp -p src dst").
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
124
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
125 The destination may be a directory.
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
126
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
127 """
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
128 if os.path.isdir(dst):
7755
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
129 dst = os.path.join(dst, os.path.basename(src))
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
130 copyfile(src, dst)
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
131 copystat(src, dst)
5
5570dbb1ce55 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
132
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
133 def ignore_patterns(*patterns):
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
134 """Function that can be used as copytree() ignore parameter.
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
135
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
136 Patterns is a sequence of glob-style patterns
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
137 that are used to exclude files"""
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
138 def _ignore_patterns(path, names):
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
139 ignored_names = []
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
140 for pattern in patterns:
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
141 ignored_names.extend(fnmatch.filter(names, pattern))
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
142 return set(ignored_names)
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
143 return _ignore_patterns
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
144
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
145 def copytree(src, dst, symlinks=False, ignore=None):
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
146 """Recursively copy a directory tree using copy2().
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
147
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
148 The destination directory must not already exist.
28025
e63f1eccd250 Fix SF bug #691276, shutil.copytree documentation bug
Neal Norwitz <nnorwitz@gmail.com>
parents: 27361
diff changeset
149 If exception(s) occur, an Error is raised with a list of reasons.
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
150
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
151 If the optional symlinks flag is true, symbolic links in the
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
152 source tree result in symbolic links in the destination tree; if
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
153 it is false, the contents of the files pointed to by symbolic
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
154 links are copied.
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
155
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
156 The optional ignore argument is a callable. If given, it
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
157 is called with the `src` parameter, which is the directory
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
158 being visited by copytree(), and `names` which is the list of
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
159 `src` contents, as returned by os.listdir():
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
160
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
161 callable(src, names) -> ignored_names
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
162
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
163 Since copytree() is called recursively, the callable will be
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
164 called once for each directory that is copied. It returns a
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
165 list of names relative to the `src` directory that should
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
166 not be copied.
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
167
5349
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
168 XXX Consider this example code rather than the ultimate tool.
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
169
6ab392d7a52f Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents: 5348
diff changeset
170 """
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
171 names = os.listdir(src)
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
172 if ignore is not None:
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
173 ignored_names = ignore(src, names)
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
174 else:
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
175 ignored_names = set()
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
176
34364
19e61a2a5632 Patch #1094015:
Johannes Gijsbers <jlg@dds.nl>
parents: 33865
diff changeset
177 os.makedirs(dst)
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
178 errors = []
5348
ae02ed2aac3f Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents: 5347
diff changeset
179 for name in names:
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
180 if name in ignored_names:
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
181 continue
7755
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
182 srcname = os.path.join(src, name)
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
183 dstname = os.path.join(dst, name)
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
184 try:
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
185 if symlinks and os.path.islink(srcname):
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
186 linkto = os.readlink(srcname)
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
187 os.symlink(linkto, dstname)
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
188 elif os.path.isdir(srcname):
47888
d7526670ff0a #2663: support an *ignore* argument to shutil.copytree(). Patch by Tarek Ziade.
Georg Brandl <georg@python.org>
parents: 45858
diff changeset
189 copytree(srcname, dstname, symlinks, ignore)
7755
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
190 else:
53652
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
191 # Will raise a SpecialFileError for unsupported file types
7755
fb4b4d069cc7 Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents: 7203
diff changeset
192 copy2(srcname, dstname)
35501
ed65e0ad2215 patch [ 1242454 ] shutil.copytree() quits too soon after an error.
Georg Brandl <georg@python.org>
parents: 34485
diff changeset
193 # catch the Error from the recursive copytree so that we can
ed65e0ad2215 patch [ 1242454 ] shutil.copytree() quits too soon after an error.
Georg Brandl <georg@python.org>
parents: 34485
diff changeset
194 # continue with other files
ed65e0ad2215 patch [ 1242454 ] shutil.copytree() quits too soon after an error.
Georg Brandl <georg@python.org>
parents: 34485
diff changeset
195 except Error, err:
ed65e0ad2215 patch [ 1242454 ] shutil.copytree() quits too soon after an error.
Georg Brandl <georg@python.org>
parents: 34485
diff changeset
196 errors.extend(err.args[0])
53652
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
197 except EnvironmentError, why:
409448d455e3 Issue #3002: `shutil.copyfile()` and `shutil.copytree()` now raise an
Antoine Pitrou <solipsis@pitrou.net>
parents: 51446
diff changeset
198 errors.append((srcname, dstname, str(why)))
39307
9377c6604542 Don't copy directory stat times in shutil.copytree on Windows
Martin v. Löwis <martin@v.loewis.de>
parents: 38032
diff changeset
199 try:
9377c6604542 Don't copy directory stat times in shutil.copytree on Windows
Martin v. Löwis <martin@v.loewis.de>
parents: 38032
diff changeset
200 copystat(src, dst)
9377c6604542 Don't copy directory stat times in shutil.copytree on Windows
Martin v. Löwis <martin@v.loewis.de>
parents: 38032
diff changeset
201 except OSError, why:
48216
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
202 if WindowsError is not None and isinstance(why, WindowsError):
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
203 # Copying file access times may fail on Windows
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
204 pass
ef41dae30f35 #3134: shutil referenced undefined WindowsError symbol
Georg Brandl <georg@python.org>
parents: 39307
diff changeset
205 else:
78763
fe3d113e139d Fix wrong way of adding Error information in shutil.copytree.
Georg Brandl <georg@python.org>
parents: 76869
diff changeset
206 errors.append((src, dst, str(why)))
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
207 if errors:
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
208 raise Error, errors
7203
8c129a567867 Added rmtree(), to recursively remove a directory tree.
Guido van Rossum <guido@python.org>
parents: 5349
diff changeset
209
27361
891ec4d266d1 rmtree(): Make implementation agree with documentation (both latex and
Barry Warsaw <barry@python.org>
parents: 27096
diff changeset
210 def rmtree(path, ignore_errors=False, onerror=None):
7203
8c129a567867 Added rmtree(), to recursively remove a directory tree.
Guido van Rossum <guido@python.org>
parents: 5349
diff changeset
211 """Recursively delete a directory tree.
8c129a567867 Added rmtree(), to recursively remove a directory tree.
Guido van Rossum <guido@python.org>
parents: 5349
diff changeset
212
33865
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
213 If ignore_errors is set, errors are ignored; otherwise, if onerror
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
214 is set, it is called to handle the error with arguments (func,
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
215 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
216 path is the argument to that function that caused it to fail; and
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
217 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
218 is false and onerror is None, an exception is raised.
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
219
7203
8c129a567867 Added rmtree(), to recursively remove a directory tree.
Guido van Rossum <guido@python.org>
parents: 5349
diff changeset
220 """
33865
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
221 if ignore_errors:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
222 def onerror(*args):
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
223 pass
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
224 elif onerror is None:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
225 def onerror(*args):
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
226 raise
44823
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
227 try:
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
228 if os.path.islink(path):
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
229 # symlinks to directories are forbidden, see bug #1669
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
230 raise OSError("Cannot call rmtree on a symbolic link")
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
231 except OSError:
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
232 onerror(os.path.islink, path, sys.exc_info())
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
233 # can't continue even if onerror hook returns
eaca2367ecc9 #1669: don't allow shutil.rmtree() to be called on a symlink.
Georg Brandl <georg@python.org>
parents: 40872
diff changeset
234 return
33865
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
235 names = []
27361
891ec4d266d1 rmtree(): Make implementation agree with documentation (both latex and
Barry Warsaw <barry@python.org>
parents: 27096
diff changeset
236 try:
33865
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
237 names = os.listdir(path)
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
238 except os.error, err:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
239 onerror(os.listdir, path, sys.exc_info())
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
240 for name in names:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
241 fullname = os.path.join(path, name)
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
242 try:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
243 mode = os.lstat(fullname).st_mode
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
244 except os.error:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
245 mode = 0
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
246 if stat.S_ISDIR(mode):
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
247 rmtree(fullname, ignore_errors, onerror)
27361
891ec4d266d1 rmtree(): Make implementation agree with documentation (both latex and
Barry Warsaw <barry@python.org>
parents: 27096
diff changeset
248 else:
33865
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
249 try:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
250 os.remove(fullname)
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
251 except os.error, err:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
252 onerror(os.remove, fullname, sys.exc_info())
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
253 try:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
254 os.rmdir(path)
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
255 except os.error:
f196716ea0db Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents: 33687
diff changeset
256 onerror(os.rmdir, path, sys.exc_info())
7203
8c129a567867 Added rmtree(), to recursively remove a directory tree.
Guido van Rossum <guido@python.org>
parents: 5349
diff changeset
257
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
258
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
259 def _basename(path):
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
260 # A basename() variant which first strips the trailing slash, if present.
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
261 # Thus we always get the last component of the path, even for directories.
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
262 return os.path.basename(path.rstrip(os.path.sep))
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
263
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
264 def move(src, dst):
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
265 """Recursively move a file or directory to another location. This is
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
266 similar to the Unix "mv" command.
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
267
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
268 If the destination is a directory or a symlink to a directory, the source
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
269 is moved inside the directory. The destination path must not already
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
270 exist.
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
271
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
272 If the destination already exists but is not a directory, it may be
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
273 overwritten depending on os.rename() semantics.
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
274
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
275 If the destination is on our current filesystem, then rename() is used.
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
276 Otherwise, src is copied to the destination and then removed.
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
277 A lot more could be done here... A look at a mv.c shows a lot of
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
278 the issues this implementation glosses over.
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
279
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
280 """
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
281 real_dst = dst
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
282 if os.path.isdir(dst):
69872
051190230254 Backport fix for issue #10684 from 3.x
Ronald Oussoren <ronaldoussoren@mac.com>
parents: 68256
diff changeset
283 if _samefile(src, dst):
051190230254 Backport fix for issue #10684 from 3.x
Ronald Oussoren <ronaldoussoren@mac.com>
parents: 68256
diff changeset
284 # We might be on a case insensitive filesystem,
051190230254 Backport fix for issue #10684 from 3.x
Ronald Oussoren <ronaldoussoren@mac.com>
parents: 68256
diff changeset
285 # perform the rename anyway.
051190230254 Backport fix for issue #10684 from 3.x
Ronald Oussoren <ronaldoussoren@mac.com>
parents: 68256
diff changeset
286 os.rename(src, dst)
051190230254 Backport fix for issue #10684 from 3.x
Ronald Oussoren <ronaldoussoren@mac.com>
parents: 68256
diff changeset
287 return
051190230254 Backport fix for issue #10684 from 3.x
Ronald Oussoren <ronaldoussoren@mac.com>
parents: 68256
diff changeset
288
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
289 real_dst = os.path.join(dst, _basename(src))
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
290 if os.path.exists(real_dst):
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
291 raise Error, "Destination path '%s' already exists" % real_dst
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
292 try:
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
293 os.rename(src, real_dst)
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
294 except OSError:
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
295 if os.path.isdir(src):
51446
0ab36796dd79 make destinsrc private
Benjamin Peterson <benjamin@python.org>
parents: 51179
diff changeset
296 if _destinsrc(src, dst):
32386
686e5d38be42 shutil.move() will raise an exception when trying to move a directory into
Brett Cannon <bcannon@gmail.com>
parents: 28025
diff changeset
297 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
298 copytree(src, real_dst, symlinks=True)
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
299 rmtree(src)
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
300 else:
45858
923380acd1cd Issue 1577: shutil.move() where destination is a directory was doing a
Sean Reifscheider <jafo@tummy.com>
parents: 44823
diff changeset
301 copy2(src, real_dst)
25641
13438586daa6 Patch #448038: Add move(). Report errors from copytree as in shutil.Error.
Martin v. Löwis <martin@v.loewis.de>
parents: 25170
diff changeset
302 os.unlink(src)
32386
686e5d38be42 shutil.move() will raise an exception when trying to move a directory into
Brett Cannon <bcannon@gmail.com>
parents: 28025
diff changeset
303
51446
0ab36796dd79 make destinsrc private
Benjamin Peterson <benjamin@python.org>
parents: 51179
diff changeset
304 def _destinsrc(src, dst):
51179
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
305 src = abspath(src)
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
306 dst = abspath(dst)
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
307 if not src.endswith(os.path.sep):
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
308 src += os.path.sep
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
309 if not dst.endswith(os.path.sep):
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
310 dst += os.path.sep
e2dcad56e40e Merged revisions 69100 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 48214
diff changeset
311 return dst.startswith(src)
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
312
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
313 def _get_gid(name):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
314 """Returns a gid, given a group name."""
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
315 if getgrnam is None or name is None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
316 return None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
317 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
318 result = getgrnam(name)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
319 except KeyError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
320 result = None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
321 if result is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
322 return result[2]
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
323 return None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
324
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
325 def _get_uid(name):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
326 """Returns an uid, given a user name."""
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
327 if getpwnam is None or name is None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
328 return None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
329 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
330 result = getpwnam(name)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
331 except KeyError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
332 result = None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
333 if result is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
334 return result[2]
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
335 return None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
336
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
337 def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
338 owner=None, group=None, logger=None):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
339 """Create a (possibly compressed) tar file from all the files under
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
340 'base_dir'.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
341
60788
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
342 'compress' must be "gzip" (the default), "bzip2", or None.
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
343
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
344 'owner' and 'group' can be used to define an owner and a group for the
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
345 archive that is being built. If not provided, the current owner and group
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
346 will be used.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
347
66934
5b44059247db Merged revisions 87277 via svnmerge from
Éric Araujo <merwok@netwok.org>
parents: 61291
diff changeset
348 The output tar file will be named 'base_name' + ".tar", possibly plus
60788
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
349 the appropriate compression extension (".gz", or ".bz2").
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
350
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
351 Returns the output filename.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
352 """
60788
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
353 tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: ''}
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
354 compress_ext = {'gzip': '.gz', 'bzip2': '.bz2'}
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
355
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
356 # flags for compression program, each element of list will be an argument
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
357 if compress is not None and compress not in compress_ext.keys():
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
358 raise ValueError, \
60788
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
359 ("bad value for 'compress': must be None, 'gzip' or 'bzip2'")
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
360
60788
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
361 archive_name = base_name + '.tar' + compress_ext.get(compress, '')
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
362 archive_dir = os.path.dirname(archive_name)
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
363
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
364 if not os.path.exists(archive_dir):
71956
615a29295d5f Guard shutil._make_archive against a logger=None argument.
Éric Araujo <merwok@netwok.org>
parents: 69872
diff changeset
365 if logger is not None:
615a29295d5f Guard shutil._make_archive against a logger=None argument.
Éric Araujo <merwok@netwok.org>
parents: 69872
diff changeset
366 logger.info("creating %s", archive_dir)
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
367 if not dry_run:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
368 os.makedirs(archive_dir)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
369
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
370
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
371 # creating the tarball
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
372 import tarfile # late import so Python build itself doesn't break
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
373
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
374 if logger is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
375 logger.info('Creating tar archive')
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
376
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
377 uid = _get_uid(owner)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
378 gid = _get_gid(group)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
379
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
380 def _set_uid_gid(tarinfo):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
381 if gid is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
382 tarinfo.gid = gid
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
383 tarinfo.gname = group
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
384 if uid is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
385 tarinfo.uid = uid
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
386 tarinfo.uname = owner
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
387 return tarinfo
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
388
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
389 if not dry_run:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
390 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
391 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
392 tar.add(base_dir, filter=_set_uid_gid)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
393 finally:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
394 tar.close()
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
395
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
396 return archive_name
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
397
60807
2db06fae8c2e shutil: removed unused import and fixed attributes names in _call_external_zip
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60788
diff changeset
398 def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
399 # XXX see if we want to keep an external call here
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
400 if verbose:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
401 zipoptions = "-r"
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
402 else:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
403 zipoptions = "-rq"
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
404 from distutils.errors import DistutilsExecError
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
405 from distutils.spawn import spawn
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
406 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
407 spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
408 except DistutilsExecError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
409 # XXX really should distinguish between "couldn't find
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
410 # external 'zip' command" and "zip failed".
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
411 raise ExecError, \
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
412 ("unable to create zip file '%s': "
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
413 "could neither import the 'zipfile' module nor "
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
414 "find a standalone zip utility") % zip_filename
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
415
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
416 def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
417 """Create a zip file from all the files under 'base_dir'.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
418
66934
5b44059247db Merged revisions 87277 via svnmerge from
Éric Araujo <merwok@netwok.org>
parents: 61291
diff changeset
419 The output zip file will be named 'base_name' + ".zip". Uses either the
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
420 "zipfile" Python module (if available) or the InfoZIP "zip" utility
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
421 (if installed and found on the default search path). If neither tool is
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
422 available, raises ExecError. Returns the name of the output zip
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
423 file.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
424 """
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
425 zip_filename = base_name + ".zip"
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
426 archive_dir = os.path.dirname(base_name)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
427
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
428 if not os.path.exists(archive_dir):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
429 if logger is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
430 logger.info("creating %s", archive_dir)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
431 if not dry_run:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
432 os.makedirs(archive_dir)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
433
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
434 # If zipfile module is not available, try spawning an external 'zip'
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
435 # command.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
436 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
437 import zipfile
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
438 except ImportError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
439 zipfile = None
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
440
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
441 if zipfile is None:
60807
2db06fae8c2e shutil: removed unused import and fixed attributes names in _call_external_zip
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60788
diff changeset
442 _call_external_zip(base_dir, zip_filename, verbose, dry_run)
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
443 else:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
444 if logger is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
445 logger.info("creating '%s' and adding '%s' to it",
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
446 zip_filename, base_dir)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
447
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
448 if not dry_run:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
449 zip = zipfile.ZipFile(zip_filename, "w",
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
450 compression=zipfile.ZIP_DEFLATED)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
451
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
452 for dirpath, dirnames, filenames in os.walk(base_dir):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
453 for name in filenames:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
454 path = os.path.normpath(os.path.join(dirpath, name))
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
455 if os.path.isfile(path):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
456 zip.write(path, path)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
457 if logger is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
458 logger.info("adding '%s'", path)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
459 zip.close()
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
460
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
461 return zip_filename
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
462
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
463 _ARCHIVE_FORMATS = {
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
464 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
465 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
466 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
467 'zip': (_make_zipfile, [],"ZIP file")
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
468 }
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
469
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
470 def get_archive_formats():
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
471 """Returns a list of supported formats for archiving and unarchiving.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
472
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
473 Each element of the returned sequence is a tuple (name, description)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
474 """
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
475 formats = [(name, registry[2]) for name, registry in
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
476 _ARCHIVE_FORMATS.items()]
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
477 formats.sort()
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
478 return formats
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
479
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
480 def register_archive_format(name, function, extra_args=None, description=''):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
481 """Registers an archive format.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
482
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
483 name is the name of the format. function is the callable that will be
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
484 used to create archives. If provided, extra_args is a sequence of
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
485 (name, value) tuples that will be passed as arguments to the callable.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
486 description can be provided to describe the format, and will be returned
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
487 by the get_archive_formats() function.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
488 """
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
489 if extra_args is None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
490 extra_args = []
59431
e2d41079d059 Fix some py3k warnings in the standard library.
Florent Xicluna <florent.xicluna@gmail.com>
parents: 59058
diff changeset
491 if not isinstance(function, collections.Callable):
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
492 raise TypeError('The %s object is not callable' % function)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
493 if not isinstance(extra_args, (tuple, list)):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
494 raise TypeError('extra_args needs to be a sequence')
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
495 for element in extra_args:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
496 if not isinstance(element, (tuple, list)) or len(element) !=2 :
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
497 raise TypeError('extra_args elements are : (arg_name, value)')
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
498
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
499 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
500
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
501 def unregister_archive_format(name):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
502 del _ARCHIVE_FORMATS[name]
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
503
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
504 def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
505 dry_run=0, owner=None, group=None, logger=None):
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
506 """Create an archive file (eg. zip or tar).
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
507
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
508 'base_name' is the name of the file to create, minus any format-specific
60788
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
509 extension; 'format' is the archive format: one of "zip", "tar", "bztar"
4ddca7fd3639 removed ztar support in shutil.make_archive
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 60728
diff changeset
510 or "gztar".
59053
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
511
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
512 'root_dir' is a directory that will be the root directory of the
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
513 archive; ie. we typically chdir into 'root_dir' before creating the
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
514 archive. 'base_dir' is the directory where we start archiving from;
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
515 ie. 'base_dir' will be the common prefix of all files and
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
516 directories in the archive. 'root_dir' and 'base_dir' both default
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
517 to the current directory. Returns the name of the archive file.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
518
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
519 'owner' and 'group' are used when creating a tar archive. By default,
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
520 uses the current owner and group.
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
521 """
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
522 save_cwd = os.getcwd()
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
523 if root_dir is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
524 if logger is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
525 logger.debug("changing into '%s'", root_dir)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
526 base_name = os.path.abspath(base_name)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
527 if not dry_run:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
528 os.chdir(root_dir)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
529
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
530 if base_dir is None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
531 base_dir = os.curdir
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
532
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
533 kwargs = {'dry_run': dry_run, 'logger': logger}
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
534
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
535 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
536 format_info = _ARCHIVE_FORMATS[format]
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
537 except KeyError:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
538 raise ValueError, "unknown archive format '%s'" % format
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
539
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
540 func = format_info[0]
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
541 for arg, val in format_info[1]:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
542 kwargs[arg] = val
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
543
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
544 if format != 'zip':
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
545 kwargs['owner'] = owner
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
546 kwargs['group'] = group
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
547
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
548 try:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
549 filename = func(base_name, base_dir, **kwargs)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
550 finally:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
551 if root_dir is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
552 if logger is not None:
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
553 logger.debug("changing back to '%s'", save_cwd)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
554 os.chdir(save_cwd)
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
555
ac36ec8bae6c added make_archive (and secondary APIs) to shutil
Tarek Ziadé <ziade.tarek@gmail.com>
parents: 54593
diff changeset
556 return filename