Mercurial > cpython-lru_cache-weakref
annotate Lib/shutil.py @ 79691:05c8928362ee
Merge __next__ method link fixes with 3.3.
| author | Ezio Melotti <ezio.melotti@gmail.com> |
|---|---|
| date | Fri, 12 Oct 2012 13:46:37 +0300 |
| parents | e11642068f85 |
| children | c70d964b26fe |
| rev | line source |
|---|---|
|
59060
df56ba1cb0af
Merged revisions 78364 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
59056
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 | 6 |
| 771 | 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 |
|
48499
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
11 import fnmatch |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
12 import collections |
|
59919
1dc18412a7ee
Merged revisions 79301 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
54594
diff
changeset
|
13 import errno |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
14 import tarfile |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
15 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
16 try: |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
17 import bz2 |
|
73345
fa82071bb7e1
Remove redundant imports.
Florent Xicluna <florent.xicluna@gmail.com>
parents:
73166
diff
changeset
|
18 del bz2 |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
19 _BZ2_SUPPORTED = True |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
20 except ImportError: |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
21 _BZ2_SUPPORTED = False |
| 5 | 22 |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
23 try: |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
24 from pwd import getpwnam |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
25 except ImportError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
26 getpwnam = None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
27 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
28 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
29 from grp import getgrnam |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
30 except ImportError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
31 getgrnam = None |
| 5 | 32 |
|
59060
df56ba1cb0af
Merged revisions 78364 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
59056
diff
changeset
|
33 __all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", |
|
df56ba1cb0af
Merged revisions 78364 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
59056
diff
changeset
|
34 "copytree", "move", "rmtree", "Error", "SpecialFileError", |
|
df56ba1cb0af
Merged revisions 78364 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
59056
diff
changeset
|
35 "ExecError", "make_archive", "get_archive_formats", |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
36 "register_archive_format", "unregister_archive_format", |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
37 "get_unpack_formats", "register_unpack_format", |
| 72017 | 38 "unregister_unpack_format", "unpack_archive", |
|
77588
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
39 "ignore_patterns", "chown", "which"] |
|
71781
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
40 # disk_usage is added later, if available on the platform |
|
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
|
41 |
|
35505
26ba3d4f4fc4
No need to import exceptions, they are builtins
Neal Norwitz <nnorwitz@gmail.com>
parents:
35501
diff
changeset
|
42 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
|
43 pass |
| 5 | 44 |
|
79566
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
45 class SameFileError(Error): |
|
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
46 """Raised when source and destination are the same file.""" |
|
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
47 |
|
53653
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
48 class SpecialFileError(EnvironmentError): |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
49 """Raised when trying to do a kind of operation (e.g. copying) which is |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
50 not supported on a special file (e.g. a named pipe)""" |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
51 |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
52 class ExecError(EnvironmentError): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
53 """Raised when a command could not be executed""" |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
54 |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
55 class ReadError(EnvironmentError): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
56 """Raised when an archive cannot be read""" |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
57 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
58 class RegistryError(Exception): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
59 """Raised when a registery operation with the archiving |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
60 and unpacking registeries fails""" |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
61 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
62 |
|
48680
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
63 try: |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
64 WindowsError |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
65 except NameError: |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
66 WindowsError = None |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
67 |
|
13571
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
68 def copyfileobj(fsrc, fdst, length=16*1024): |
|
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
69 """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
|
70 while 1: |
|
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
71 buf = fsrc.read(length) |
|
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
72 if not buf: |
|
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
73 break |
|
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
74 fdst.write(buf) |
|
3a8c670309a2
apply patch #100868 from Moshe Zadka:
Greg Stein <gstein@lyra.org>
parents:
12285
diff
changeset
|
75 |
|
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
|
76 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
|
77 # Macintosh, Unix. |
|
60726
71860cdb4886
Merged revisions 80218 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
59918
diff
changeset
|
78 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
|
79 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
|
80 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
|
81 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
|
82 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
|
83 |
|
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
|
84 # 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
|
85 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
|
86 os.path.normcase(os.path.abspath(dst))) |
|
15872
3685ef2a55a4
Whitespace normalization.
Tim Peters <tim.peters@gmail.com>
parents:
13571
diff
changeset
|
87 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
88 def copyfile(src, dst, *, follow_symlinks=True): |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
89 """Copy data from src to dst. |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
90 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
91 If follow_symlinks is not set and src is a symbolic link, a new |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
92 symlink will be created instead of copying the file it points to. |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
93 |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
94 """ |
|
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
|
95 if _samefile(src, dst): |
|
79566
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
96 raise SameFileError("{!r} and {!r} are the same file".format(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
|
97 |
|
53653
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
98 for fn in [src, dst]: |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
99 try: |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
100 st = os.stat(fn) |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
101 except OSError: |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
102 # File most likely does not exist |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
103 pass |
|
54594
da33bed5d8c4
Merged revisions 73250 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
53653
diff
changeset
|
104 else: |
|
da33bed5d8c4
Merged revisions 73250 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
53653
diff
changeset
|
105 # XXX What about other special files? (sockets, devices...) |
|
da33bed5d8c4
Merged revisions 73250 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
53653
diff
changeset
|
106 if stat.S_ISFIFO(st.st_mode): |
|
da33bed5d8c4
Merged revisions 73250 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
53653
diff
changeset
|
107 raise SpecialFileError("`%s` is a named pipe" % fn) |
|
61289
78e7fc01c51a
Merged revisions 80833 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
59919
diff
changeset
|
108 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
109 if not follow_symlinks and os.path.islink(src): |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
110 os.symlink(os.readlink(src), dst) |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
111 else: |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
112 with open(src, 'rb') as fsrc: |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
113 with open(dst, 'wb') as fdst: |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
114 copyfileobj(fsrc, fdst) |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
115 return dst |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
116 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
117 def copymode(src, dst, *, follow_symlinks=True): |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
118 """Copy mode bits from src to dst. |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
119 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
120 If follow_symlinks is not set, symlinks aren't followed if and only |
|
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
121 if both `src` and `dst` are symlinks. If `lchmod` isn't available |
|
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
122 (e.g. Linux) this method does nothing. |
| 5 | 123 |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
124 """ |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
125 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst): |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
126 if hasattr(os, 'lchmod'): |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
127 stat_func, chmod_func = os.lstat, os.lchmod |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
128 else: |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
129 return |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
130 elif hasattr(os, 'chmod'): |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
131 stat_func, chmod_func = os.stat, os.chmod |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
132 else: |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
133 return |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
134 |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
135 st = stat_func(src) |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
136 chmod_func(dst, stat.S_IMODE(st.st_mode)) |
| 5 | 137 |
|
78101
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
138 if hasattr(os, 'listxattr'): |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
139 def _copyxattr(src, dst, *, follow_symlinks=True): |
|
78101
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
140 """Copy extended filesystem attributes from `src` to `dst`. |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
141 |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
142 Overwrite existing attributes. |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
143 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
144 If `follow_symlinks` is false, symlinks won't be followed. |
|
78101
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
145 |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
146 """ |
| 5 | 147 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
148 for name in os.listxattr(src, follow_symlinks=follow_symlinks): |
|
78101
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
149 try: |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
150 value = os.getxattr(src, name, follow_symlinks=follow_symlinks) |
|
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
151 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks) |
|
78101
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
152 except OSError as e: |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
153 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA): |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
154 raise |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
155 else: |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
156 def _copyxattr(*args, **kwargs): |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
157 pass |
|
5f62c317c202
- Issue #15238: shutil.copystat now copies Linux "extended attributes".
Larry Hastings <larry@hastings.org>
parents:
77846
diff
changeset
|
158 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
159 def copystat(src, dst, *, follow_symlinks=True): |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
160 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst. |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
161 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
162 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
163 only if both `src` and `dst` are symlinks. |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
164 |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
165 """ |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
166 def _nop(*args, ns=None, follow_symlinks=None): |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
167 pass |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
168 |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
169 # follow symlinks (aka don't not follow symlinks) |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
170 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst)) |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
171 if follow: |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
172 # use the real function if it exists |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
173 def lookup(name): |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
174 return getattr(os, name, _nop) |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
175 else: |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
176 # use the real function only if it exists |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
177 # *and* it supports follow_symlinks |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
178 def lookup(name): |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
179 fn = getattr(os, name, _nop) |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
180 if fn in os.supports_follow_symlinks: |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
181 return fn |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
182 return _nop |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
183 |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
184 st = lookup("stat")(src, follow_symlinks=follow) |
|
23697
c0e8c07ae1d6
Replace obsolete stat module constants with
Walter Dörwald <walter@livinglogic.de>
parents:
23627
diff
changeset
|
185 mode = stat.S_IMODE(st.st_mode) |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
186 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns), |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
187 follow_symlinks=follow) |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
188 try: |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
189 lookup("chmod")(dst, mode, follow_symlinks=follow) |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
190 except NotImplementedError: |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
191 # if we got a NotImplementedError, it's because |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
192 # * follow_symlinks=False, |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
193 # * lchown() is unavailable, and |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
194 # * either |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
195 # * fchownat() is unvailable or |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
196 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW. |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
197 # (it returned ENOSUP.) |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
198 # therefore we're out of options--we simply cannot chown the |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
199 # symlink. give up, suppress the error. |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
200 # (which is what shutil always did in this circumstance.) |
|
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
201 pass |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
202 if hasattr(st, 'st_flags'): |
|
59919
1dc18412a7ee
Merged revisions 79301 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
54594
diff
changeset
|
203 try: |
|
77597
27f9c26fdd8b
Issue #14626: Large refactoring of functions / parameters in the os module.
Larry Hastings <larry@hastings.org>
parents:
77590
diff
changeset
|
204 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow) |
|
59919
1dc18412a7ee
Merged revisions 79301 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
54594
diff
changeset
|
205 except OSError as why: |
|
76870
ae141eebcf96
Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents:
74791
diff
changeset
|
206 for err in 'EOPNOTSUPP', 'ENOTSUP': |
|
ae141eebcf96
Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents:
74791
diff
changeset
|
207 if hasattr(errno, err) and why.errno == getattr(errno, err): |
|
ae141eebcf96
Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents:
74791
diff
changeset
|
208 break |
|
ae141eebcf96
Issue #14662: Prevent shutil failures on OS X when destination does not
Ned Deily <nad@acm.org>
parents:
74791
diff
changeset
|
209 else: |
|
59919
1dc18412a7ee
Merged revisions 79301 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
54594
diff
changeset
|
210 raise |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
211 _copyxattr(src, dst, follow_symlinks=follow) |
| 5 | 212 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
213 def copy(src, dst, *, follow_symlinks=True): |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
214 """Copy data and mode bits ("cp src dst"). Return the file's destination. |
|
15872
3685ef2a55a4
Whitespace normalization.
Tim Peters <tim.peters@gmail.com>
parents:
13571
diff
changeset
|
215 |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
216 The destination may be a directory. |
|
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
217 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
218 If follow_symlinks is false, symlinks won't be followed. This |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
219 resembles GNU's "cp -P src dst". |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
220 |
|
79566
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
221 If source and destination are the same file, a SameFileError will be |
|
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
222 raised. |
|
e11642068f85
Closes #1492704: Make shutil.copyfile() raise a distinct SameFileError
Hynek Schlawack <hs@ox.cx>
parents:
78762
diff
changeset
|
223 |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
224 """ |
|
5348
ae02ed2aac3f
Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents:
5347
diff
changeset
|
225 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
|
226 dst = os.path.join(dst, os.path.basename(src)) |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
227 copyfile(src, dst, follow_symlinks=follow_symlinks) |
|
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
228 copymode(src, dst, follow_symlinks=follow_symlinks) |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
229 return dst |
| 5 | 230 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
231 def copy2(src, dst, *, follow_symlinks=True): |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
232 """Copy data and all stat info ("cp -p src dst"). Return the file's |
|
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
233 destination." |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
234 |
|
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
235 The destination may be a directory. |
|
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
236 |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
237 If follow_symlinks is false, symlinks won't be followed. This |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
238 resembles GNU's "cp -P src dst". |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
239 |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
240 """ |
|
5348
ae02ed2aac3f
Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents:
5347
diff
changeset
|
241 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
|
242 dst = os.path.join(dst, os.path.basename(src)) |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
243 copyfile(src, dst, follow_symlinks=follow_symlinks) |
|
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
244 copystat(src, dst, follow_symlinks=follow_symlinks) |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
245 return dst |
| 5 | 246 |
|
48499
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
247 def ignore_patterns(*patterns): |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
248 """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
|
249 |
|
48499
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
250 Patterns is a sequence of glob-style patterns |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
251 that are used to exclude files""" |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
252 def _ignore_patterns(path, names): |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
253 ignored_names = [] |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
254 for pattern in patterns: |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
255 ignored_names.extend(fnmatch.filter(names, pattern)) |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
256 return set(ignored_names) |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
257 return _ignore_patterns |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
258 |
|
60751
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
259 def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
260 ignore_dangling_symlinks=False): |
|
60737
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
261 """Recursively copy a directory tree. |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
262 |
|
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
263 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
|
264 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
|
265 |
|
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
266 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
|
267 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
|
268 it is false, the contents of the files pointed to by symbolic |
|
60751
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
269 links are copied. If the file pointed by the symlink doesn't |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
270 exist, an exception will be added in the list of errors raised in |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
271 an Error exception at the end of the copy process. |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
272 |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
273 You can set the optional ignore_dangling_symlinks flag to true if you |
|
60892
d426bbfd5bd7
added a note about the ignore_dangling_symlinks option
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60810
diff
changeset
|
274 want to silence this exception. Notice that this has no effect on |
|
d426bbfd5bd7
added a note about the ignore_dangling_symlinks option
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60810
diff
changeset
|
275 platforms that don't support os.symlink. |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
276 |
|
48499
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
277 The optional ignore argument is a callable. If given, it |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
278 is called with the `src` parameter, which is the directory |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
279 being visited by copytree(), and `names` which is the list of |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
280 `src` contents, as returned by os.listdir(): |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
281 |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
282 callable(src, names) -> ignored_names |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
283 |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
284 Since copytree() is called recursively, the callable will be |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
285 called once for each directory that is copied. It returns a |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
286 list of names relative to the `src` directory that should |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
287 not be copied. |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
288 |
|
60737
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
289 The optional copy_function argument is a callable that will be used |
|
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
290 to copy each file. It will be called with the source path and the |
|
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
291 destination path as arguments. By default, copy2() is used, but any |
|
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
292 function that supports the same signature (like copy()) can be used. |
|
5349
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
293 |
|
6ab392d7a52f
Transformed comments to doc strings.
Guido van Rossum <guido@python.org>
parents:
5348
diff
changeset
|
294 """ |
|
5348
ae02ed2aac3f
Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents:
5347
diff
changeset
|
295 names = os.listdir(src) |
|
48499
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
296 if ignore is not None: |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
297 ignored_names = ignore(src, names) |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
298 else: |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
299 ignored_names = set() |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
300 |
| 34364 | 301 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
|
302 errors = [] |
|
5348
ae02ed2aac3f
Reindented at 4 spaces.
Guido van Rossum <guido@python.org>
parents:
5347
diff
changeset
|
303 for name in names: |
|
48499
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
304 if name in ignored_names: |
|
de0bf60f1245
Merged revisions 64722,64729,64753,64845-64846,64849,64871,64880-64882,64885,64888,64897,64900-64901,64915,64926-64929,64938-64941,64944,64961,64966,64973 via svnmerge from
Georg Brandl <georg@python.org>
parents:
45865
diff
changeset
|
305 continue |
|
7755
fb4b4d069cc7
Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents:
7203
diff
changeset
|
306 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
|
307 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
|
308 try: |
|
60751
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
309 if os.path.islink(srcname): |
|
7755
fb4b4d069cc7
Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents:
7203
diff
changeset
|
310 linkto = os.readlink(srcname) |
|
60751
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
311 if symlinks: |
|
74194
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
312 # We can't just leave it to `copy_function` because legacy |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
313 # code with a custom `copy_function` may rely on copytree |
|
cf57ef65bcd0
Issue #12715: Add an optional symlinks argument to shutil functions (copyfile, copymode, copystat, copy, copy2).
Antoine Pitrou <solipsis@pitrou.net>
parents:
73345
diff
changeset
|
314 # doing the right thing. |
|
60751
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
315 os.symlink(linkto, dstname) |
|
78121
758a9023d836
Issue #15202: Consistently use the name "follow_symlinks" for
Larry Hastings <larry@hastings.org>
parents:
78101
diff
changeset
|
316 copystat(srcname, dstname, follow_symlinks=not symlinks) |
|
60751
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
317 else: |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
318 # ignore dangling symlink if the flag is on |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
319 if not os.path.exists(linkto) and ignore_dangling_symlinks: |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
320 continue |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
321 # otherwise let the copy occurs. copy2 will raise an error |
|
82de0b488f2d
Fixed #6547: Added the ignore_dangling_symlinks option to shutil.copytree
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60737
diff
changeset
|
322 copy_function(srcname, dstname) |
|
7755
fb4b4d069cc7
Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents:
7203
diff
changeset
|
323 elif os.path.isdir(srcname): |
|
60737
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
324 copytree(srcname, dstname, symlinks, ignore, copy_function) |
|
7755
fb4b4d069cc7
Mass check-in after untabifying all files that need it.
Guido van Rossum <guido@python.org>
parents:
7203
diff
changeset
|
325 else: |
|
53653
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
326 # Will raise a SpecialFileError for unsupported file types |
|
60737
be17bda5a658
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60731
diff
changeset
|
327 copy_function(srcname, dstname) |
|
35501
ed65e0ad2215
patch [ 1242454 ] shutil.copytree() quits too soon after an error.
Georg Brandl <georg@python.org>
parents:
34485
diff
changeset
|
328 # 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
|
329 # continue with other files |
|
40587
6b18a095c2e7
SF patch 1631942 by Collin Winter:
Guido van Rossum <guido@python.org>
parents:
39442
diff
changeset
|
330 except Error as err: |
|
35501
ed65e0ad2215
patch [ 1242454 ] shutil.copytree() quits too soon after an error.
Georg Brandl <georg@python.org>
parents:
34485
diff
changeset
|
331 errors.extend(err.args[0]) |
|
53653
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
332 except EnvironmentError as why: |
|
960ef00d5214
Merged revisions 72178 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
51750
diff
changeset
|
333 errors.append((srcname, dstname, str(why))) |
|
39442
654c380cf8b9
Merged revisions 46753-51188 via svnmerge from
Thomas Wouters <thomas@python.org>
parents:
38453
diff
changeset
|
334 try: |
|
654c380cf8b9
Merged revisions 46753-51188 via svnmerge from
Thomas Wouters <thomas@python.org>
parents:
38453
diff
changeset
|
335 copystat(src, dst) |
|
40587
6b18a095c2e7
SF patch 1631942 by Collin Winter:
Guido van Rossum <guido@python.org>
parents:
39442
diff
changeset
|
336 except OSError as why: |
|
48680
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
337 if WindowsError is not None and isinstance(why, WindowsError): |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
338 # Copying file access times may fail on Windows |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
339 pass |
|
7779af388aec
Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from
Georg Brandl <georg@python.org>
parents:
48499
diff
changeset
|
340 else: |
|
78761
a2bf95458eed
Fix wrong way of adding Error information in shutil.copytree.
Georg Brandl <georg@python.org>
parents:
76870
diff
changeset
|
341 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
|
342 if errors: |
|
43020
907a45df1295
Raise statement normalization in Lib/.
Collin Winter <collinw@gmail.com>
parents:
40893
diff
changeset
|
343 raise Error(errors) |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
344 return dst |
|
7203
8c129a567867
Added rmtree(), to recursively remove a directory tree.
Guido van Rossum <guido@python.org>
parents:
5349
diff
changeset
|
345 |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
346 # version vulnerable to race conditions |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
347 def _rmtree_unsafe(path, onerror): |
|
44828
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
348 try: |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
349 if os.path.islink(path): |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
350 # symlinks to directories are forbidden, see bug #1669 |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
351 raise OSError("Cannot call rmtree on a symbolic link") |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
352 except OSError: |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
353 onerror(os.path.islink, path, sys.exc_info()) |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
354 # can't continue even if onerror hook returns |
|
ef7d72d98485
Merged revisions 60124-60142 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
43020
diff
changeset
|
355 return |
|
33865
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
356 names = [] |
|
27361
891ec4d266d1
rmtree(): Make implementation agree with documentation (both latex and
Barry Warsaw <barry@python.org>
parents:
27096
diff
changeset
|
357 try: |
|
33865
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
358 names = os.listdir(path) |
|
71828
552efc3eb45c
Remove unused names in except clauses
Éric Araujo <merwok@netwok.org>
parents:
71781
diff
changeset
|
359 except os.error: |
|
33865
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
360 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
|
361 for name in names: |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
362 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
|
363 try: |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
364 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
|
365 except os.error: |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
366 mode = 0 |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
367 if stat.S_ISDIR(mode): |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
368 _rmtree_unsafe(fullname, onerror) |
|
27361
891ec4d266d1
rmtree(): Make implementation agree with documentation (both latex and
Barry Warsaw <barry@python.org>
parents:
27096
diff
changeset
|
369 else: |
|
33865
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
370 try: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
371 os.unlink(fullname) |
|
71828
552efc3eb45c
Remove unused names in except clauses
Éric Araujo <merwok@netwok.org>
parents:
71781
diff
changeset
|
372 except os.error: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
373 onerror(os.unlink, fullname, sys.exc_info()) |
|
33865
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
374 try: |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
375 os.rmdir(path) |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
376 except os.error: |
|
f196716ea0db
Bug #1048941: shutil.rmtree error handling was always broken
Johannes Gijsbers <jlg@dds.nl>
parents:
33687
diff
changeset
|
377 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
|
378 |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
379 # Version using fd-based APIs to protect against races |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
380 def _rmtree_safe_fd(topfd, path, onerror): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
381 names = [] |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
382 try: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
383 names = os.listdir(topfd) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
384 except os.error: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
385 onerror(os.listdir, path, sys.exc_info()) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
386 for name in names: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
387 fullname = os.path.join(path, name) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
388 try: |
|
77829
f9f798f1421e
#4489: Don't follow ever symlinks in rmtree
Hynek Schlawack <hs@ox.cx>
parents:
77767
diff
changeset
|
389 orig_st = os.stat(name, dir_fd=topfd, follow_symlinks=False) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
390 mode = orig_st.st_mode |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
391 except os.error: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
392 mode = 0 |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
393 if stat.S_ISDIR(mode): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
394 try: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
395 dirfd = os.open(name, os.O_RDONLY, dir_fd=topfd) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
396 except os.error: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
397 onerror(os.open, fullname, sys.exc_info()) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
398 else: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
399 try: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
400 if os.path.samestat(orig_st, os.fstat(dirfd)): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
401 _rmtree_safe_fd(dirfd, fullname, onerror) |
|
77835
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
402 try: |
|
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
403 os.rmdir(name, dir_fd=topfd) |
|
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
404 except os.error: |
|
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
405 onerror(os.rmdir, fullname, sys.exc_info()) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
406 finally: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
407 os.close(dirfd) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
408 else: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
409 try: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
410 os.unlink(name, dir_fd=topfd) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
411 except os.error: |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
412 onerror(os.unlink, fullname, sys.exc_info()) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
413 |
|
77846
992be49127e1
Check for all used fd-based functions in shutil.rmdir, closes #15218
Hynek Schlawack <hs@ox.cx>
parents:
77835
diff
changeset
|
414 _use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <= |
|
992be49127e1
Check for all used fd-based functions in shutil.rmdir, closes #15218
Hynek Schlawack <hs@ox.cx>
parents:
77835
diff
changeset
|
415 os.supports_dir_fd and |
|
992be49127e1
Check for all used fd-based functions in shutil.rmdir, closes #15218
Hynek Schlawack <hs@ox.cx>
parents:
77835
diff
changeset
|
416 os.listdir in os.supports_fd and |
|
992be49127e1
Check for all used fd-based functions in shutil.rmdir, closes #15218
Hynek Schlawack <hs@ox.cx>
parents:
77835
diff
changeset
|
417 os.stat in os.supports_follow_symlinks) |
|
77668
c2be81151994
Issue #4489: Rename the feature marker for the symlink resistant rmtree and store it as a function attribute
Nick Coghlan <ncoghlan@gmail.com>
parents:
77660
diff
changeset
|
418 |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
419 def rmtree(path, ignore_errors=False, onerror=None): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
420 """Recursively delete a directory tree. |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
421 |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
422 If ignore_errors is set, errors are ignored; otherwise, if onerror |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
423 is set, it is called to handle the error with arguments (func, |
|
77642
53fc7f59c7bb
#4489: Fix usage of fd-based functions to new api introduced earlier today
Hynek Schlawack <hs@ox.cx>
parents:
77635
diff
changeset
|
424 path, exc_info) where func is platform and implementation dependent; |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
425 path is the argument to that function that caused it to fail; and |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
426 exc_info is a tuple returned by sys.exc_info(). If ignore_errors |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
427 is false and onerror is None, an exception is raised. |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
428 |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
429 """ |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
430 if ignore_errors: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
431 def onerror(*args): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
432 pass |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
433 elif onerror is None: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
434 def onerror(*args): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
435 raise |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
436 if _use_fd_functions: |
|
77767
2e2329aeb5c1
#4489 Make fd based rmtree work on bytes
Hynek Schlawack <hs@ox.cx>
parents:
77668
diff
changeset
|
437 # While the unsafe rmtree works fine on bytes, the fd based does not. |
|
2e2329aeb5c1
#4489 Make fd based rmtree work on bytes
Hynek Schlawack <hs@ox.cx>
parents:
77668
diff
changeset
|
438 if isinstance(path, bytes): |
|
2e2329aeb5c1
#4489 Make fd based rmtree work on bytes
Hynek Schlawack <hs@ox.cx>
parents:
77668
diff
changeset
|
439 path = os.fsdecode(path) |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
440 # Note: To guard against symlink races, we use the standard |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
441 # lstat()/open()/fstat() trick. |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
442 try: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
443 orig_st = os.lstat(path) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
444 except Exception: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
445 onerror(os.lstat, path, sys.exc_info()) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
446 return |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
447 try: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
448 fd = os.open(path, os.O_RDONLY) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
449 except Exception: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
450 onerror(os.lstat, path, sys.exc_info()) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
451 return |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
452 try: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
453 if (stat.S_ISDIR(orig_st.st_mode) and |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
454 os.path.samestat(orig_st, os.fstat(fd))): |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
455 _rmtree_safe_fd(fd, path, onerror) |
|
77835
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
456 try: |
|
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
457 os.rmdir(path) |
|
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
458 except os.error: |
|
9134bb4d0578
#4489: Use dir_fd in rmdir in _rmtree_safe_fd()
Hynek Schlawack <hs@ox.cx>
parents:
77829
diff
changeset
|
459 onerror(os.rmdir, path, sys.exc_info()) |
|
77829
f9f798f1421e
#4489: Don't follow ever symlinks in rmtree
Hynek Schlawack <hs@ox.cx>
parents:
77767
diff
changeset
|
460 else: |
|
77635
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
461 raise NotADirectoryError(20, |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
462 "Not a directory: '{}'".format(path)) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
463 finally: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
464 os.close(fd) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
465 else: |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
466 return _rmtree_unsafe(path, onerror) |
|
c910af2e3c98
#4489: Add a shutil.rmtree that isn't suspectible to symlink attacks
Hynek Schlawack <hs@ox.cx>
parents:
77610
diff
changeset
|
467 |
|
77668
c2be81151994
Issue #4489: Rename the feature marker for the symlink resistant rmtree and store it as a function attribute
Nick Coghlan <ncoghlan@gmail.com>
parents:
77660
diff
changeset
|
468 # Allow introspection of whether or not the hardening against symlink |
|
c2be81151994
Issue #4489: Rename the feature marker for the symlink resistant rmtree and store it as a function attribute
Nick Coghlan <ncoghlan@gmail.com>
parents:
77660
diff
changeset
|
469 # attacks is supported on the current platform |
|
c2be81151994
Issue #4489: Rename the feature marker for the symlink resistant rmtree and store it as a function attribute
Nick Coghlan <ncoghlan@gmail.com>
parents:
77660
diff
changeset
|
470 rmtree.avoids_symlink_attacks = _use_fd_functions |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
471 |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
472 def _basename(path): |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
473 # A basename() variant which first strips the trailing slash, if present. |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
474 # Thus we always get the last component of the path, even for directories. |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
475 return os.path.basename(path.rstrip(os.path.sep)) |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
476 |
|
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
|
477 def move(src, dst): |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
478 """Recursively move a file or directory to another location. This is |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
479 similar to the Unix "mv" command. Return the file or directory's |
|
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
480 destination. |
|
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
|
481 |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
482 If the destination is a directory or a symlink to a directory, the source |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
483 is moved inside the directory. The destination path must not already |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
484 exist. |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
485 |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
486 If the destination already exists but is not a directory, it may be |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
487 overwritten depending on os.rename() semantics. |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
488 |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
489 If the destination is on our current filesystem, then rename() is used. |
|
74288
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
490 Otherwise, src is copied to the destination and then removed. Symlinks are |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
491 recreated under the new name if os.rename() fails because of cross |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
492 filesystem renames. |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
493 |
|
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
|
494 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
|
495 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
|
496 |
|
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
|
497 """ |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
498 real_dst = dst |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
499 if os.path.isdir(dst): |
|
69869
26da299ca88e
Fix for issue 10684: Folders get deleted when trying to change case with shutil.move (case insensitive file systems only)
Ronald Oussoren <ronaldoussoren@mac.com>
parents:
61295
diff
changeset
|
500 if _samefile(src, dst): |
|
26da299ca88e
Fix for issue 10684: Folders get deleted when trying to change case with shutil.move (case insensitive file systems only)
Ronald Oussoren <ronaldoussoren@mac.com>
parents:
61295
diff
changeset
|
501 # We might be on a case insensitive filesystem, |
|
26da299ca88e
Fix for issue 10684: Folders get deleted when trying to change case with shutil.move (case insensitive file systems only)
Ronald Oussoren <ronaldoussoren@mac.com>
parents:
61295
diff
changeset
|
502 # perform the rename anyway. |
|
26da299ca88e
Fix for issue 10684: Folders get deleted when trying to change case with shutil.move (case insensitive file systems only)
Ronald Oussoren <ronaldoussoren@mac.com>
parents:
61295
diff
changeset
|
503 os.rename(src, dst) |
|
26da299ca88e
Fix for issue 10684: Folders get deleted when trying to change case with shutil.move (case insensitive file systems only)
Ronald Oussoren <ronaldoussoren@mac.com>
parents:
61295
diff
changeset
|
504 return |
|
26da299ca88e
Fix for issue 10684: Folders get deleted when trying to change case with shutil.move (case insensitive file systems only)
Ronald Oussoren <ronaldoussoren@mac.com>
parents:
61295
diff
changeset
|
505 |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
506 real_dst = os.path.join(dst, _basename(src)) |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
507 if os.path.exists(real_dst): |
|
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
508 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
|
509 try: |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
510 os.rename(src, real_dst) |
|
71828
552efc3eb45c
Remove unused names in except clauses
Éric Araujo <merwok@netwok.org>
parents:
71781
diff
changeset
|
511 except OSError: |
|
74288
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
512 if os.path.islink(src): |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
513 linkto = os.readlink(src) |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
514 os.symlink(linkto, real_dst) |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
515 os.unlink(src) |
|
1ea8b7233fd7
Issue #9993: When the source and destination are on different filesystems,
Antoine Pitrou <solipsis@pitrou.net>
parents:
74194
diff
changeset
|
516 elif os.path.isdir(src): |
|
51750
db8db31fdb4c
Merged revisions 69415,69591,69593 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
51180
diff
changeset
|
517 if _destinsrc(src, dst): |
|
43020
907a45df1295
Raise statement normalization in Lib/.
Collin Winter <collinw@gmail.com>
parents:
40893
diff
changeset
|
518 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
519 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
|
520 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
|
521 else: |
|
45865
e0e8bef0d5ec
Merged revisions 61520,61523-61528,61532 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44828
diff
changeset
|
522 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
|
523 os.unlink(src) |
|
77514
8281233ec648
Fix #14772: Return the destination from some shutil functions.
Brian Curtin <brian@python.org>
parents:
76883
diff
changeset
|
524 return real_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
|
525 |
|
51750
db8db31fdb4c
Merged revisions 69415,69591,69593 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
51180
diff
changeset
|
526 def _destinsrc(src, dst): |
|
51180
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
527 src = abspath(src) |
|
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
528 dst = abspath(dst) |
|
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
529 if not src.endswith(os.path.sep): |
|
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
530 src += os.path.sep |
|
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
531 if not dst.endswith(os.path.sep): |
|
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
532 dst += os.path.sep |
|
5d0eaeb4134d
Merged revisions 69101 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
48680
diff
changeset
|
533 return dst.startswith(src) |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
534 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
535 def _get_gid(name): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
536 """Returns a gid, given a group name.""" |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
537 if getgrnam is None or name is None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
538 return None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
539 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
540 result = getgrnam(name) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
541 except KeyError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
542 result = None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
543 if result is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
544 return result[2] |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
545 return None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
546 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
547 def _get_uid(name): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
548 """Returns an uid, given a user name.""" |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
549 if getpwnam is None or name is None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
550 return None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
551 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
552 result = getpwnam(name) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
553 except KeyError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
554 result = None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
555 if result is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
556 return result[2] |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
557 return None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
558 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
559 def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
560 owner=None, group=None, logger=None): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
561 """Create a (possibly compressed) tar file from all the files under |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
562 'base_dir'. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
563 |
|
60789
bd45e0110990
Merged revisions 80282 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60770
diff
changeset
|
564 'compress' must be "gzip" (the default), "bzip2", or None. |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
565 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
566 'owner' and 'group' can be used to define an owner and a group for the |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
567 archive that is being built. If not provided, the current owner and group |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
568 will be used. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
569 |
|
66932
2d2997f19e90
Fix wrong name in docstring and doc (#10693). Original patch by Eli Bendersky.
Éric Araujo <merwok@netwok.org>
parents:
61294
diff
changeset
|
570 The output tar file will be named 'base_name' + ".tar", possibly plus |
|
60789
bd45e0110990
Merged revisions 80282 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60770
diff
changeset
|
571 the appropriate compression extension (".gz", or ".bz2"). |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
572 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
573 Returns the output filename. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
574 """ |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
575 tar_compression = {'gzip': 'gz', None: ''} |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
576 compress_ext = {'gzip': '.gz'} |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
577 |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
578 if _BZ2_SUPPORTED: |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
579 tar_compression['bzip2'] = 'bz2' |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
580 compress_ext['bzip2'] = '.bz2' |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
581 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
582 # flags for compression program, each element of list will be an argument |
|
72408
cc5e3a65e452
A few style changes originally done in the distutils2 repo
Éric Araujo <merwok@netwok.org>
parents:
72267
diff
changeset
|
583 if compress is not None and compress not in compress_ext: |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
584 raise ValueError("bad value for 'compress', or compression format not " |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
585 "supported : {0}".format(compress)) |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
586 |
|
60789
bd45e0110990
Merged revisions 80282 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60770
diff
changeset
|
587 archive_name = base_name + '.tar' + compress_ext.get(compress, '') |
|
bd45e0110990
Merged revisions 80282 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60770
diff
changeset
|
588 archive_dir = os.path.dirname(archive_name) |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
589 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
590 if not os.path.exists(archive_dir): |
|
67804
5f1ad65a1b84
Protect logging call against None argument (fixes #11045).
Éric Araujo <merwok@netwok.org>
parents:
66932
diff
changeset
|
591 if logger is not None: |
| 71934 | 592 logger.info("creating %s", archive_dir) |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
593 if not dry_run: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
594 os.makedirs(archive_dir) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
595 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
596 # creating the tarball |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
597 if logger is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
598 logger.info('Creating tar archive') |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
599 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
600 uid = _get_uid(owner) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
601 gid = _get_gid(group) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
602 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
603 def _set_uid_gid(tarinfo): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
604 if gid is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
605 tarinfo.gid = gid |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
606 tarinfo.gname = group |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
607 if uid is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
608 tarinfo.uid = uid |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
609 tarinfo.uname = owner |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
610 return tarinfo |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
611 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
612 if not dry_run: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
613 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
614 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
615 tar.add(base_dir, filter=_set_uid_gid) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
616 finally: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
617 tar.close() |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
618 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
619 return archive_name |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
620 |
|
60810
c2905b0ef1d2
Merged revisions 80306 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60789
diff
changeset
|
621 def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
622 # XXX see if we want to keep an external call here |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
623 if verbose: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
624 zipoptions = "-r" |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
625 else: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
626 zipoptions = "-rq" |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
627 from distutils.errors import DistutilsExecError |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
628 from distutils.spawn import spawn |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
629 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
630 spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
631 except DistutilsExecError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
632 # XXX really should distinguish between "couldn't find |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
633 # external 'zip' command" and "zip failed". |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
634 raise ExecError("unable to create zip file '%s': " |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
635 "could neither import the 'zipfile' module nor " |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
636 "find a standalone zip utility") % zip_filename |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
637 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
638 def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
639 """Create a zip file from all the files under 'base_dir'. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
640 |
|
66932
2d2997f19e90
Fix wrong name in docstring and doc (#10693). Original patch by Eli Bendersky.
Éric Araujo <merwok@netwok.org>
parents:
61294
diff
changeset
|
641 The output zip file will be named 'base_name' + ".zip". Uses either the |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
642 "zipfile" Python module (if available) or the InfoZIP "zip" utility |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
643 (if installed and found on the default search path). If neither tool is |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
644 available, raises ExecError. Returns the name of the output zip |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
645 file. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
646 """ |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
647 zip_filename = base_name + ".zip" |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
648 archive_dir = os.path.dirname(base_name) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
649 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
650 if not os.path.exists(archive_dir): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
651 if logger is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
652 logger.info("creating %s", archive_dir) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
653 if not dry_run: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
654 os.makedirs(archive_dir) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
655 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
656 # If zipfile module is not available, try spawning an external 'zip' |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
657 # command. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
658 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
659 import zipfile |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
660 except ImportError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
661 zipfile = None |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
662 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
663 if zipfile is None: |
|
60810
c2905b0ef1d2
Merged revisions 80306 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60789
diff
changeset
|
664 _call_external_zip(base_dir, zip_filename, verbose, dry_run) |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
665 else: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
666 if logger is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
667 logger.info("creating '%s' and adding '%s' to it", |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
668 zip_filename, base_dir) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
669 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
670 if not dry_run: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
671 zip = zipfile.ZipFile(zip_filename, "w", |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
672 compression=zipfile.ZIP_DEFLATED) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
673 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
674 for dirpath, dirnames, filenames in os.walk(base_dir): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
675 for name in filenames: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
676 path = os.path.normpath(os.path.join(dirpath, name)) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
677 if os.path.isfile(path): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
678 zip.write(path, path) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
679 if logger is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
680 logger.info("adding '%s'", path) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
681 zip.close() |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
682 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
683 return zip_filename |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
684 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
685 _ARCHIVE_FORMATS = { |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
686 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
687 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), |
|
72408
cc5e3a65e452
A few style changes originally done in the distutils2 repo
Éric Araujo <merwok@netwok.org>
parents:
72267
diff
changeset
|
688 'zip': (_make_zipfile, [], "ZIP file") |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
689 } |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
690 |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
691 if _BZ2_SUPPORTED: |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
692 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
693 "bzip2'ed tar-file") |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
694 |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
695 def get_archive_formats(): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
696 """Returns a list of supported formats for archiving and unarchiving. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
697 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
698 Each element of the returned sequence is a tuple (name, description) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
699 """ |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
700 formats = [(name, registry[2]) for name, registry in |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
701 _ARCHIVE_FORMATS.items()] |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
702 formats.sort() |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
703 return formats |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
704 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
705 def register_archive_format(name, function, extra_args=None, description=''): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
706 """Registers an archive format. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
707 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
708 name is the name of the format. function is the callable that will be |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
709 used to create archives. If provided, extra_args is a sequence of |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
710 (name, value) tuples that will be passed as arguments to the callable. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
711 description can be provided to describe the format, and will be returned |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
712 by the get_archive_formats() function. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
713 """ |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
714 if extra_args is None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
715 extra_args = [] |
|
73165
8e57b5d8f58f
Closes #13258: Use callable() built-in in the standard library.
Florent Xicluna <florent.xicluna@gmail.com>
parents:
72265
diff
changeset
|
716 if not callable(function): |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
717 raise TypeError('The %s object is not callable' % function) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
718 if not isinstance(extra_args, (tuple, list)): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
719 raise TypeError('extra_args needs to be a sequence') |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
720 for element in extra_args: |
|
72408
cc5e3a65e452
A few style changes originally done in the distutils2 repo
Éric Araujo <merwok@netwok.org>
parents:
72267
diff
changeset
|
721 if not isinstance(element, (tuple, list)) or len(element) !=2: |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
722 raise TypeError('extra_args elements are : (arg_name, value)') |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
723 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
724 _ARCHIVE_FORMATS[name] = (function, extra_args, description) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
725 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
726 def unregister_archive_format(name): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
727 del _ARCHIVE_FORMATS[name] |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
728 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
729 def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
730 dry_run=0, owner=None, group=None, logger=None): |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
731 """Create an archive file (eg. zip or tar). |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
732 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
733 'base_name' is the name of the file to create, minus any format-specific |
|
60789
bd45e0110990
Merged revisions 80282 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60770
diff
changeset
|
734 extension; 'format' is the archive format: one of "zip", "tar", "bztar" |
|
bd45e0110990
Merged revisions 80282 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60770
diff
changeset
|
735 or "gztar". |
|
59056
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
736 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
737 'root_dir' is a directory that will be the root directory of the |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
738 archive; ie. we typically chdir into 'root_dir' before creating the |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
739 archive. 'base_dir' is the directory where we start archiving from; |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
740 ie. 'base_dir' will be the common prefix of all files and |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
741 directories in the archive. 'root_dir' and 'base_dir' both default |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
742 to the current directory. Returns the name of the archive file. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
743 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
744 'owner' and 'group' are used when creating a tar archive. By default, |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
745 uses the current owner and group. |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
746 """ |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
747 save_cwd = os.getcwd() |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
748 if root_dir is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
749 if logger is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
750 logger.debug("changing into '%s'", root_dir) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
751 base_name = os.path.abspath(base_name) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
752 if not dry_run: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
753 os.chdir(root_dir) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
754 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
755 if base_dir is None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
756 base_dir = os.curdir |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
757 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
758 kwargs = {'dry_run': dry_run, 'logger': logger} |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
759 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
760 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
761 format_info = _ARCHIVE_FORMATS[format] |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
762 except KeyError: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
763 raise ValueError("unknown archive format '%s'" % format) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
764 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
765 func = format_info[0] |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
766 for arg, val in format_info[1]: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
767 kwargs[arg] = val |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
768 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
769 if format != 'zip': |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
770 kwargs['owner'] = owner |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
771 kwargs['group'] = group |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
772 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
773 try: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
774 filename = func(base_name, base_dir, **kwargs) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
775 finally: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
776 if root_dir is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
777 if logger is not None: |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
778 logger.debug("changing back to '%s'", save_cwd) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
779 os.chdir(save_cwd) |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
780 |
|
a1d078b88247
Merged revisions 78359-78360 via svnmerge from
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
54594
diff
changeset
|
781 return filename |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
782 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
783 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
784 def get_unpack_formats(): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
785 """Returns a list of supported formats for unpacking. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
786 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
787 Each element of the returned sequence is a tuple |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
788 (name, extensions, description) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
789 """ |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
790 formats = [(name, info[0], info[3]) for name, info in |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
791 _UNPACK_FORMATS.items()] |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
792 formats.sort() |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
793 return formats |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
794 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
795 def _check_unpack_options(extensions, function, extra_args): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
796 """Checks what gets registered as an unpacker.""" |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
797 # first make sure no other unpacker is registered for this extension |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
798 existing_extensions = {} |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
799 for name, info in _UNPACK_FORMATS.items(): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
800 for ext in info[0]: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
801 existing_extensions[ext] = name |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
802 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
803 for extension in extensions: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
804 if extension in existing_extensions: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
805 msg = '%s is already registered for "%s"' |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
806 raise RegistryError(msg % (extension, |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
807 existing_extensions[extension])) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
808 |
|
73165
8e57b5d8f58f
Closes #13258: Use callable() built-in in the standard library.
Florent Xicluna <florent.xicluna@gmail.com>
parents:
72265
diff
changeset
|
809 if not callable(function): |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
810 raise TypeError('The registered function must be a callable') |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
811 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
812 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
813 def register_unpack_format(name, extensions, function, extra_args=None, |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
814 description=''): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
815 """Registers an unpack format. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
816 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
817 `name` is the name of the format. `extensions` is a list of extensions |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
818 corresponding to the format. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
819 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
820 `function` is the callable that will be |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
821 used to unpack archives. The callable will receive archives to unpack. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
822 If it's unable to handle an archive, it needs to raise a ReadError |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
823 exception. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
824 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
825 If provided, `extra_args` is a sequence of |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
826 (name, value) tuples that will be passed as arguments to the callable. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
827 description can be provided to describe the format, and will be returned |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
828 by the get_unpack_formats() function. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
829 """ |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
830 if extra_args is None: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
831 extra_args = [] |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
832 _check_unpack_options(extensions, function, extra_args) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
833 _UNPACK_FORMATS[name] = extensions, function, extra_args, description |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
834 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
835 def unregister_unpack_format(name): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
836 """Removes the pack format from the registery.""" |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
837 del _UNPACK_FORMATS[name] |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
838 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
839 def _ensure_directory(path): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
840 """Ensure that the parent directory of `path` exists""" |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
841 dirname = os.path.dirname(path) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
842 if not os.path.isdir(dirname): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
843 os.makedirs(dirname) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
844 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
845 def _unpack_zipfile(filename, extract_dir): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
846 """Unpack zip `filename` to `extract_dir` |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
847 """ |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
848 try: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
849 import zipfile |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
850 except ImportError: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
851 raise ReadError('zlib not supported, cannot unpack this archive.') |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
852 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
853 if not zipfile.is_zipfile(filename): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
854 raise ReadError("%s is not a zip file" % filename) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
855 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
856 zip = zipfile.ZipFile(filename) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
857 try: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
858 for info in zip.infolist(): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
859 name = info.filename |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
860 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
861 # don't extract absolute paths or ones with .. in them |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
862 if name.startswith('/') or '..' in name: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
863 continue |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
864 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
865 target = os.path.join(extract_dir, *name.split('/')) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
866 if not target: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
867 continue |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
868 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
869 _ensure_directory(target) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
870 if not name.endswith('/'): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
871 # file |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
872 data = zip.read(info.filename) |
|
72408
cc5e3a65e452
A few style changes originally done in the distutils2 repo
Éric Araujo <merwok@netwok.org>
parents:
72267
diff
changeset
|
873 f = open(target, 'wb') |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
874 try: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
875 f.write(data) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
876 finally: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
877 f.close() |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
878 del data |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
879 finally: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
880 zip.close() |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
881 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
882 def _unpack_tarfile(filename, extract_dir): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
883 """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
884 """ |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
885 try: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
886 tarobj = tarfile.open(filename) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
887 except tarfile.TarError: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
888 raise ReadError( |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
889 "%s is not a compressed or uncompressed tar file" % filename) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
890 try: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
891 tarobj.extractall(extract_dir) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
892 finally: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
893 tarobj.close() |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
894 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
895 _UNPACK_FORMATS = { |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
896 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
897 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
898 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
899 } |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
900 |
|
61087
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
901 if _BZ2_SUPPORTED: |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
902 _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
903 "bzip2'ed tar-file") |
|
4b57019150a8
make sure shutil checks for bz2 availability before it uses it.
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
61062
diff
changeset
|
904 |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
905 def _find_unpack_format(filename): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
906 for name, info in _UNPACK_FORMATS.items(): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
907 for extension in info[0]: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
908 if filename.endswith(extension): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
909 return name |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
910 return None |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
911 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
912 def unpack_archive(filename, extract_dir=None, format=None): |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
913 """Unpack an archive. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
914 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
915 `filename` is the name of the archive. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
916 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
917 `extract_dir` is the name of the target directory, where the archive |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
918 is unpacked. If not provided, the current working directory is used. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
919 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
920 `format` is the archive format: one of "zip", "tar", or "gztar". Or any |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
921 other registered format. If not provided, unpack_archive will use the |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
922 filename extension and see if an unpacker was registered for that |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
923 extension. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
924 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
925 In case none is found, a ValueError is raised. |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
926 """ |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
927 if extract_dir is None: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
928 extract_dir = os.getcwd() |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
929 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
930 if format is not None: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
931 try: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
932 format_info = _UNPACK_FORMATS[format] |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
933 except KeyError: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
934 raise ValueError("Unknown unpack format '{0}'".format(format)) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
935 |
|
68601
d1619747c17d
Close #11548: Correctly handle format argument in shutil.unpack_archive
Nick Coghlan <ncoghlan@gmail.com>
parents:
68257
diff
changeset
|
936 func = format_info[1] |
|
d1619747c17d
Close #11548: Correctly handle format argument in shutil.unpack_archive
Nick Coghlan <ncoghlan@gmail.com>
parents:
68257
diff
changeset
|
937 func(filename, extract_dir, **dict(format_info[2])) |
|
61062
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
938 else: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
939 # we need to look at the registered unpackers supported extensions |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
940 format = _find_unpack_format(filename) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
941 if format is None: |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
942 raise ReadError("Unknown archive format '{0}'".format(filename)) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
943 |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
944 func = _UNPACK_FORMATS[format][1] |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
945 kwargs = dict(_UNPACK_FORMATS[format][2]) |
|
a43776553ab5
#8295 : Added shutil.unpack_archive and related APIs
Tarek Ziadé <ziade.tarek@gmail.com>
parents:
60892
diff
changeset
|
946 func(filename, extract_dir, **kwargs) |
|
71110
2fc102ebaf73
Issue #12442: add shutil.disk_usage()
Giampaolo Rodola' <g.rodola@gmail.com>
parents:
69870
diff
changeset
|
947 |
|
71781
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
948 |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
949 if hasattr(os, 'statvfs'): |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
950 |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
951 __all__.append('disk_usage') |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
952 _ntuple_diskusage = collections.namedtuple('usage', 'total used free') |
|
71110
2fc102ebaf73
Issue #12442: add shutil.disk_usage()
Giampaolo Rodola' <g.rodola@gmail.com>
parents:
69870
diff
changeset
|
953 |
|
2fc102ebaf73
Issue #12442: add shutil.disk_usage()
Giampaolo Rodola' <g.rodola@gmail.com>
parents:
69870
diff
changeset
|
954 def disk_usage(path): |
|
71781
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
955 """Return disk usage statistics about the given path. |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
956 |
|
76505
629d4c2faa87
Issue #14650: fix typo in shutil.disk_usage() docstring; patch by Hobson Lane
Sandro Tosi <sandro.tosi@gmail.com>
parents:
74835
diff
changeset
|
957 Returned value is a named tuple with attributes 'total', 'used' and |
|
71781
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
958 'free', which are the amount of total, used and free space, in bytes. |
|
71110
2fc102ebaf73
Issue #12442: add shutil.disk_usage()
Giampaolo Rodola' <g.rodola@gmail.com>
parents:
69870
diff
changeset
|
959 """ |
|
71781
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
960 st = os.statvfs(path) |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
961 free = st.f_bavail * st.f_frsize |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
962 total = st.f_blocks * st.f_frsize |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
963 used = (st.f_blocks - st.f_bfree) * st.f_frsize |
|
71110
2fc102ebaf73
Issue #12442: add shutil.disk_usage()
Giampaolo Rodola' <g.rodola@gmail.com>
parents:
69870
diff
changeset
|
964 return _ntuple_diskusage(total, used, free) |
|
71781
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
965 |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
966 elif os.name == 'nt': |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
967 |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
968 import nt |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
969 __all__.append('disk_usage') |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
970 _ntuple_diskusage = collections.namedtuple('usage', 'total used free') |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
971 |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
972 def disk_usage(path): |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
973 """Return disk usage statistics about the given path. |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
974 |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
975 Returned valus is a named tuple with attributes 'total', 'used' and |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
976 'free', which are the amount of total, used and free space, in bytes. |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
977 """ |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
978 total, free = nt._getdiskusage(path) |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
979 used = total - free |
|
f1e761dea2ee
Clean up shutil.disk_usage.
Éric Araujo <merwok@netwok.org>
parents:
71110
diff
changeset
|
980 return _ntuple_diskusage(total, used, free) |
|
72039
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
981 |
|
72182
b166dc85f604
Add missing name in shutil.__all__
Éric Araujo <merwok@netwok.org>
parents:
72039
diff
changeset
|
982 |
|
72039
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
983 def chown(path, user=None, group=None): |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
984 """Change owner user and group of the given path. |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
985 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
986 user and group can be the uid/gid or the user/group names, and in that case, |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
987 they are converted to their respective uid/gid. |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
988 """ |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
989 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
990 if user is None and group is None: |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
991 raise ValueError("user and/or group must be set") |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
992 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
993 _user = user |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
994 _group = group |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
995 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
996 # -1 means don't change it |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
997 if user is None: |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
998 _user = -1 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
999 # user can either be an int (the uid) or a string (the system username) |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1000 elif isinstance(user, str): |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1001 _user = _get_uid(user) |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1002 if _user is None: |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1003 raise LookupError("no such user: {!r}".format(user)) |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1004 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1005 if group is None: |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1006 _group = -1 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1007 elif not isinstance(group, int): |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1008 _group = _get_gid(group) |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1009 if _group is None: |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1010 raise LookupError("no such group: {!r}".format(group)) |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1011 |
|
d1fd0f0f8e68
#12191: add shutil.chown() to change user and/or group owner of a given path also specifying their names.
Sandro Tosi <sandro.tosi@gmail.com>
parents:
72017
diff
changeset
|
1012 os.chown(path, _user, _group) |
|
74835
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1013 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1014 def get_terminal_size(fallback=(80, 24)): |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1015 """Get the size of the terminal window. |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1016 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1017 For each of the two dimensions, the environment variable, COLUMNS |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1018 and LINES respectively, is checked. If the variable is defined and |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1019 the value is a positive integer, it is used. |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1020 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1021 When COLUMNS or LINES is not defined, which is the common case, |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1022 the terminal connected to sys.__stdout__ is queried |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1023 by invoking os.get_terminal_size. |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1024 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1025 If the terminal size cannot be successfully queried, either because |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1026 the system doesn't support querying, or because we are not |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1027 connected to a terminal, the value given in fallback parameter |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1028 is used. Fallback defaults to (80, 24) which is the default |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1029 size used by many terminal emulators. |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1030 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1031 The value returned is a named tuple of type os.terminal_size. |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1032 """ |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1033 # columns, lines are the working values |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1034 try: |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1035 columns = int(os.environ['COLUMNS']) |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1036 except (KeyError, ValueError): |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1037 columns = 0 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1038 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1039 try: |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1040 lines = int(os.environ['LINES']) |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1041 except (KeyError, ValueError): |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1042 lines = 0 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1043 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1044 # only query if necessary |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1045 if columns <= 0 or lines <= 0: |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1046 try: |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1047 size = os.get_terminal_size(sys.__stdout__.fileno()) |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1048 except (NameError, OSError): |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1049 size = os.terminal_size(fallback) |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1050 if columns <= 0: |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1051 columns = size.columns |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1052 if lines <= 0: |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1053 lines = size.lines |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1054 |
|
c92f8de398ed
Issue #13609: Add two functions to query the terminal size:
Antoine Pitrou <solipsis@pitrou.net>
parents:
74793
diff
changeset
|
1055 return os.terminal_size((columns, lines)) |
|
77588
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1056 |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1057 def which(cmd, mode=os.F_OK | os.X_OK, path=None): |
|
77610
aa153b827d17
Fix #15148. Capitalize PATH, hopefully leading to less confusion
Brian Curtin <brian@python.org>
parents:
77609
diff
changeset
|
1058 """Given a command, mode, and a PATH string, return the path which |
|
77660
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1059 conforms to the given mode on the PATH, or None if there is no such |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1060 file. |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1061 |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1062 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1063 of os.environ.get("PATH"), or can be overridden with a custom search |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1064 path. |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1065 |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1066 """ |
|
77588
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1067 # Check that a given file can be accessed with the correct mode. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1068 # Additionally check that `file` is not a directory, as on Windows |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1069 # directories pass the os.access check. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1070 def _access_check(fn, mode): |
|
77660
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1071 return (os.path.exists(fn) and os.access(fn, mode) |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1072 and not os.path.isdir(fn)) |
|
77588
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1073 |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1074 # Short circuit. If we're given a full path which matches the mode |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1075 # and it exists, we're done here. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1076 if _access_check(cmd, mode): |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1077 return cmd |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1078 |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1079 path = (path or os.environ.get("PATH", os.defpath)).split(os.pathsep) |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1080 |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1081 if sys.platform == "win32": |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1082 # The current directory takes precedence on Windows. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1083 if not os.curdir in path: |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1084 path.insert(0, os.curdir) |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1085 |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1086 # PATHEXT is necessary to check on Windows. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1087 pathext = os.environ.get("PATHEXT", "").split(os.pathsep) |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1088 # See if the given file matches any of the expected path extensions. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1089 # This will allow us to short circuit when given "python.exe". |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1090 matches = [cmd for ext in pathext if cmd.lower().endswith(ext.lower())] |
|
77660
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1091 # If it does match, only test that one, otherwise we have to try |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1092 # others. |
|
48623d846f80
small refactor and PEP8 line width/docstring
Philip Jenvey <pjenvey@underboss.org>
parents:
77642
diff
changeset
|
1093 files = [cmd] if matches else [cmd + ext.lower() for ext in pathext] |
|
77588
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1094 else: |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1095 # On other platforms you don't have things like PATHEXT to tell you |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1096 # what file suffixes are executable, so just pass on cmd as-is. |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1097 files = [cmd] |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1098 |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1099 seen = set() |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1100 for dir in path: |
|
77590
9d2fe615a400
Issue #444582: shutil.which() respects relative paths.
Antoine Pitrou <solipsis@pitrou.net>
parents:
77589
diff
changeset
|
1101 dir = os.path.normcase(dir) |
|
77588
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1102 if not dir in seen: |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1103 seen.add(dir) |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1104 for thefile in files: |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1105 name = os.path.join(dir, thefile) |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1106 if _access_check(name, mode): |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1107 return name |
|
0fe7439e470c
Fix #444582. Add shutil.which function for finding programs on the system path.
Brian Curtin <brian@python.org>
parents:
77514
diff
changeset
|
1108 return None |
