blob: 1f47b03ee30c4ff488de796b5bf14e8dc8a808ef [file] [log] [blame]
Barry Warsaw7fc2cca2003-01-24 17:34:13 +00001# Copyright (C) 2003 Python Software Foundation
2
3import unittest
4import shutil
5import tempfile
Johannes Gijsbers8e6f2de2004-11-23 09:27:27 +00006import sys
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +00007import stat
Brett Cannon1c3fa182004-06-19 21:11:35 +00008import os
9import os.path
Antoine Pitrouc041ab62012-01-02 19:18:02 +010010import errno
Nick Coghlan8ed3cf32011-03-16 14:05:35 -040011import functools
Antoine Pitroubcf2b592012-02-08 23:28:36 +010012import subprocess
Benjamin Petersonee8712c2008-05-20 21:35:26 +000013from test import support
14from test.support import TESTFN
Tarek Ziadé396fad72010-02-23 05:30:31 +000015from os.path import splitdrive
16from distutils.spawn import find_executable, spawn
17from shutil import (_make_tarball, _make_zipfile, make_archive,
18 register_archive_format, unregister_archive_format,
Tarek Ziadé6ac91722010-04-28 17:51:36 +000019 get_archive_formats, Error, unpack_archive,
20 register_unpack_format, RegistryError,
Hynek Schlawack48653762012-10-07 12:49:58 +020021 unregister_unpack_format, get_unpack_formats,
22 SameFileError)
Tarek Ziadé396fad72010-02-23 05:30:31 +000023import tarfile
24import warnings
25
26from test import support
Ezio Melotti975077a2011-05-19 22:03:22 +030027from test.support import TESTFN, check_warnings, captured_stdout, requires_zlib
Tarek Ziadé396fad72010-02-23 05:30:31 +000028
Tarek Ziadéffa155a2010-04-29 13:34:35 +000029try:
30 import bz2
31 BZ2_SUPPORTED = True
32except ImportError:
33 BZ2_SUPPORTED = False
34
Antoine Pitrou7fff0962009-05-01 21:09:44 +000035TESTFN2 = TESTFN + "2"
Barry Warsaw7fc2cca2003-01-24 17:34:13 +000036
Tarek Ziadé396fad72010-02-23 05:30:31 +000037try:
38 import grp
39 import pwd
40 UID_GID_SUPPORT = True
41except ImportError:
42 UID_GID_SUPPORT = False
43
44try:
Tarek Ziadé396fad72010-02-23 05:30:31 +000045 import zipfile
46 ZIP_SUPPORT = True
47except ImportError:
48 ZIP_SUPPORT = find_executable('zip')
49
Nick Coghlan8ed3cf32011-03-16 14:05:35 -040050def _fake_rename(*args, **kwargs):
51 # Pretend the destination path is on a different filesystem.
Antoine Pitrouc041ab62012-01-02 19:18:02 +010052 raise OSError(getattr(errno, 'EXDEV', 18), "Invalid cross-device link")
Nick Coghlan8ed3cf32011-03-16 14:05:35 -040053
54def mock_rename(func):
55 @functools.wraps(func)
56 def wrap(*args, **kwargs):
57 try:
58 builtin_rename = os.rename
59 os.rename = _fake_rename
60 return func(*args, **kwargs)
61 finally:
62 os.rename = builtin_rename
63 return wrap
64
Éric Araujoa7e33a12011-08-12 19:51:35 +020065def write_file(path, content, binary=False):
66 """Write *content* to a file located at *path*.
67
68 If *path* is a tuple instead of a string, os.path.join will be used to
69 make a path. If *binary* is true, the file will be opened in binary
70 mode.
71 """
72 if isinstance(path, tuple):
73 path = os.path.join(*path)
74 with open(path, 'wb' if binary else 'w') as fp:
75 fp.write(content)
76
77def read_file(path, binary=False):
78 """Return contents from a file located at *path*.
79
80 If *path* is a tuple instead of a string, os.path.join will be used to
81 make a path. If *binary* is true, the file will be opened in binary
82 mode.
83 """
84 if isinstance(path, tuple):
85 path = os.path.join(*path)
86 with open(path, 'rb' if binary else 'r') as fp:
87 return fp.read()
88
89
Barry Warsaw7fc2cca2003-01-24 17:34:13 +000090class TestShutil(unittest.TestCase):
Tarek Ziadé396fad72010-02-23 05:30:31 +000091
92 def setUp(self):
93 super(TestShutil, self).setUp()
94 self.tempdirs = []
95
96 def tearDown(self):
97 super(TestShutil, self).tearDown()
98 while self.tempdirs:
99 d = self.tempdirs.pop()
100 shutil.rmtree(d, os.name in ('nt', 'cygwin'))
101
Tarek Ziadé396fad72010-02-23 05:30:31 +0000102
103 def mkdtemp(self):
104 """Create a temporary directory that will be cleaned up.
105
106 Returns the path of the directory.
107 """
108 d = tempfile.mkdtemp()
109 self.tempdirs.append(d)
110 return d
Tarek Ziadé5340db32010-04-19 22:30:51 +0000111
Hynek Schlawack3b527782012-06-25 13:27:31 +0200112 def test_rmtree_works_on_bytes(self):
113 tmp = self.mkdtemp()
114 victim = os.path.join(tmp, 'killme')
115 os.mkdir(victim)
116 write_file(os.path.join(victim, 'somefile'), 'foo')
117 victim = os.fsencode(victim)
118 self.assertIsInstance(victim, bytes)
119 shutil.rmtree(victim)
120
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200121 @support.skip_unless_symlink
122 def test_rmtree_fails_on_symlink(self):
123 tmp = self.mkdtemp()
124 dir_ = os.path.join(tmp, 'dir')
125 os.mkdir(dir_)
126 link = os.path.join(tmp, 'link')
127 os.symlink(dir_, link)
128 self.assertRaises(OSError, shutil.rmtree, link)
129 self.assertTrue(os.path.exists(dir_))
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100130 self.assertTrue(os.path.lexists(link))
131 errors = []
132 def onerror(*args):
133 errors.append(args)
134 shutil.rmtree(link, onerror=onerror)
135 self.assertEqual(len(errors), 1)
136 self.assertIs(errors[0][0], os.path.islink)
137 self.assertEqual(errors[0][1], link)
138 self.assertIsInstance(errors[0][2][1], OSError)
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200139
140 @support.skip_unless_symlink
141 def test_rmtree_works_on_symlinks(self):
142 tmp = self.mkdtemp()
143 dir1 = os.path.join(tmp, 'dir1')
144 dir2 = os.path.join(dir1, 'dir2')
145 dir3 = os.path.join(tmp, 'dir3')
146 for d in dir1, dir2, dir3:
147 os.mkdir(d)
148 file1 = os.path.join(tmp, 'file1')
149 write_file(file1, 'foo')
150 link1 = os.path.join(dir1, 'link1')
151 os.symlink(dir2, link1)
152 link2 = os.path.join(dir1, 'link2')
153 os.symlink(dir3, link2)
154 link3 = os.path.join(dir1, 'link3')
155 os.symlink(file1, link3)
156 # make sure symlinks are removed but not followed
157 shutil.rmtree(dir1)
158 self.assertFalse(os.path.exists(dir1))
159 self.assertTrue(os.path.exists(dir3))
160 self.assertTrue(os.path.exists(file1))
161
Barry Warsaw7fc2cca2003-01-24 17:34:13 +0000162 def test_rmtree_errors(self):
163 # filename is guaranteed not to exist
164 filename = tempfile.mktemp()
Hynek Schlawackb5501102012-12-10 09:11:25 +0100165 self.assertRaises(FileNotFoundError, shutil.rmtree, filename)
166 # test that ignore_errors option is honored
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100167 shutil.rmtree(filename, ignore_errors=True)
168
169 # existing file
170 tmpdir = self.mkdtemp()
Hynek Schlawackb5501102012-12-10 09:11:25 +0100171 write_file((tmpdir, "tstfile"), "")
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100172 filename = os.path.join(tmpdir, "tstfile")
Hynek Schlawackb5501102012-12-10 09:11:25 +0100173 with self.assertRaises(NotADirectoryError) as cm:
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100174 shutil.rmtree(filename)
Hynek Schlawack87f9b462012-12-10 16:29:57 +0100175 # The reason for this rather odd construct is that Windows sprinkles
176 # a \*.* at the end of file names. But only sometimes on some buildbots
177 possible_args = [filename, os.path.join(filename, '*.*')]
178 self.assertIn(cm.exception.filename, possible_args)
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100179 self.assertTrue(os.path.exists(filename))
Hynek Schlawackb5501102012-12-10 09:11:25 +0100180 # test that ignore_errors option is honored
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100181 shutil.rmtree(filename, ignore_errors=True)
182 self.assertTrue(os.path.exists(filename))
183 errors = []
184 def onerror(*args):
185 errors.append(args)
186 shutil.rmtree(filename, onerror=onerror)
187 self.assertEqual(len(errors), 2)
188 self.assertIs(errors[0][0], os.listdir)
189 self.assertEqual(errors[0][1], filename)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100190 self.assertIsInstance(errors[0][2][1], NotADirectoryError)
Hynek Schlawack87f9b462012-12-10 16:29:57 +0100191 self.assertIn(errors[0][2][1].filename, possible_args)
Hynek Schlawackd16eacb2012-12-10 09:00:09 +0100192 self.assertIs(errors[1][0], os.rmdir)
193 self.assertEqual(errors[1][1], filename)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100194 self.assertIsInstance(errors[1][2][1], NotADirectoryError)
Hynek Schlawack87f9b462012-12-10 16:29:57 +0100195 self.assertIn(errors[1][2][1].filename, possible_args)
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000196
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000197
Serhiy Storchaka43767632013-11-03 21:31:38 +0200198 @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod()')
199 @unittest.skipIf(sys.platform[:6] == 'cygwin',
200 "This test can't be run on Cygwin (issue #1071513).")
201 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
202 "This test can't be run reliably as root (issue #1076467).")
203 def test_on_error(self):
204 self.errorState = 0
205 os.mkdir(TESTFN)
206 self.addCleanup(shutil.rmtree, TESTFN)
Antoine Pitrou2f8a75c2012-06-23 21:28:15 +0200207
Serhiy Storchaka43767632013-11-03 21:31:38 +0200208 self.child_file_path = os.path.join(TESTFN, 'a')
209 self.child_dir_path = os.path.join(TESTFN, 'b')
210 support.create_empty_file(self.child_file_path)
211 os.mkdir(self.child_dir_path)
212 old_dir_mode = os.stat(TESTFN).st_mode
213 old_child_file_mode = os.stat(self.child_file_path).st_mode
214 old_child_dir_mode = os.stat(self.child_dir_path).st_mode
215 # Make unwritable.
216 new_mode = stat.S_IREAD|stat.S_IEXEC
217 os.chmod(self.child_file_path, new_mode)
218 os.chmod(self.child_dir_path, new_mode)
219 os.chmod(TESTFN, new_mode)
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000220
Serhiy Storchaka43767632013-11-03 21:31:38 +0200221 self.addCleanup(os.chmod, TESTFN, old_dir_mode)
222 self.addCleanup(os.chmod, self.child_file_path, old_child_file_mode)
223 self.addCleanup(os.chmod, self.child_dir_path, old_child_dir_mode)
Antoine Pitrou2f8a75c2012-06-23 21:28:15 +0200224
Serhiy Storchaka43767632013-11-03 21:31:38 +0200225 shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror)
226 # Test whether onerror has actually been called.
227 self.assertEqual(self.errorState, 3,
228 "Expected call to onerror function did not happen.")
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000229
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000230 def check_args_to_onerror(self, func, arg, exc):
Benjamin Peterson25c95f12009-05-08 20:42:26 +0000231 # test_rmtree_errors deliberately runs rmtree
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200232 # on a directory that is chmod 500, which will fail.
Benjamin Peterson25c95f12009-05-08 20:42:26 +0000233 # This function is run when shutil.rmtree fails.
234 # 99.9% of the time it initially fails to remove
235 # a file in the directory, so the first time through
236 # func is os.remove.
237 # However, some Linux machines running ZFS on
238 # FUSE experienced a failure earlier in the process
239 # at os.listdir. The first failure may legally
240 # be either.
Antoine Pitrou4f6e3f72012-06-23 22:05:11 +0200241 if self.errorState < 2:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200242 if func is os.unlink:
Antoine Pitrou4f6e3f72012-06-23 22:05:11 +0200243 self.assertEqual(arg, self.child_file_path)
244 elif func is os.rmdir:
245 self.assertEqual(arg, self.child_dir_path)
Benjamin Peterson25c95f12009-05-08 20:42:26 +0000246 else:
Antoine Pitrou4f6e3f72012-06-23 22:05:11 +0200247 self.assertIs(func, os.listdir)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200248 self.assertIn(arg, [TESTFN, self.child_dir_path])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000249 self.assertTrue(issubclass(exc[0], OSError))
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200250 self.errorState += 1
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000251 else:
252 self.assertEqual(func, os.rmdir)
253 self.assertEqual(arg, TESTFN)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000254 self.assertTrue(issubclass(exc[0], OSError))
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200255 self.errorState = 3
256
257 def test_rmtree_does_not_choke_on_failing_lstat(self):
258 try:
259 orig_lstat = os.lstat
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200260 def raiser(fn, *args, **kwargs):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200261 if fn != TESTFN:
262 raise OSError()
263 else:
264 return orig_lstat(fn)
265 os.lstat = raiser
266
267 os.mkdir(TESTFN)
268 write_file((TESTFN, 'foo'), 'foo')
269 shutil.rmtree(TESTFN)
270 finally:
271 os.lstat = orig_lstat
Barry Warsaw7fc2cca2003-01-24 17:34:13 +0000272
Antoine Pitrou78091e62011-12-29 18:54:15 +0100273 @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod')
274 @support.skip_unless_symlink
275 def test_copymode_follow_symlinks(self):
276 tmp_dir = self.mkdtemp()
277 src = os.path.join(tmp_dir, 'foo')
278 dst = os.path.join(tmp_dir, 'bar')
279 src_link = os.path.join(tmp_dir, 'baz')
280 dst_link = os.path.join(tmp_dir, 'quux')
281 write_file(src, 'foo')
282 write_file(dst, 'foo')
283 os.symlink(src, src_link)
284 os.symlink(dst, dst_link)
285 os.chmod(src, stat.S_IRWXU|stat.S_IRWXG)
286 # file to file
287 os.chmod(dst, stat.S_IRWXO)
288 self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
289 shutil.copymode(src, dst)
290 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
Antoine Pitrou3f48ac92014-01-01 02:50:45 +0100291 # On Windows, os.chmod does not follow symlinks (issue #15411)
292 if os.name != 'nt':
293 # follow src link
294 os.chmod(dst, stat.S_IRWXO)
295 shutil.copymode(src_link, dst)
296 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
297 # follow dst link
298 os.chmod(dst, stat.S_IRWXO)
299 shutil.copymode(src, dst_link)
300 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
301 # follow both links
302 os.chmod(dst, stat.S_IRWXO)
303 shutil.copymode(src_link, dst_link)
304 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100305
306 @unittest.skipUnless(hasattr(os, 'lchmod'), 'requires os.lchmod')
307 @support.skip_unless_symlink
308 def test_copymode_symlink_to_symlink(self):
309 tmp_dir = self.mkdtemp()
310 src = os.path.join(tmp_dir, 'foo')
311 dst = os.path.join(tmp_dir, 'bar')
312 src_link = os.path.join(tmp_dir, 'baz')
313 dst_link = os.path.join(tmp_dir, 'quux')
314 write_file(src, 'foo')
315 write_file(dst, 'foo')
316 os.symlink(src, src_link)
317 os.symlink(dst, dst_link)
318 os.chmod(src, stat.S_IRWXU|stat.S_IRWXG)
319 os.chmod(dst, stat.S_IRWXU)
320 os.lchmod(src_link, stat.S_IRWXO|stat.S_IRWXG)
321 # link to link
322 os.lchmod(dst_link, stat.S_IRWXO)
Larry Hastingsb4038062012-07-15 10:57:38 -0700323 shutil.copymode(src_link, dst_link, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100324 self.assertEqual(os.lstat(src_link).st_mode,
325 os.lstat(dst_link).st_mode)
326 self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
327 # src link - use chmod
328 os.lchmod(dst_link, stat.S_IRWXO)
Larry Hastingsb4038062012-07-15 10:57:38 -0700329 shutil.copymode(src_link, dst, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100330 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
331 # dst link - use chmod
332 os.lchmod(dst_link, stat.S_IRWXO)
Larry Hastingsb4038062012-07-15 10:57:38 -0700333 shutil.copymode(src, dst_link, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100334 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
335
336 @unittest.skipIf(hasattr(os, 'lchmod'), 'requires os.lchmod to be missing')
337 @support.skip_unless_symlink
338 def test_copymode_symlink_to_symlink_wo_lchmod(self):
339 tmp_dir = self.mkdtemp()
340 src = os.path.join(tmp_dir, 'foo')
341 dst = os.path.join(tmp_dir, 'bar')
342 src_link = os.path.join(tmp_dir, 'baz')
343 dst_link = os.path.join(tmp_dir, 'quux')
344 write_file(src, 'foo')
345 write_file(dst, 'foo')
346 os.symlink(src, src_link)
347 os.symlink(dst, dst_link)
Larry Hastingsb4038062012-07-15 10:57:38 -0700348 shutil.copymode(src_link, dst_link, follow_symlinks=False) # silent fail
Antoine Pitrou78091e62011-12-29 18:54:15 +0100349
350 @support.skip_unless_symlink
351 def test_copystat_symlinks(self):
352 tmp_dir = self.mkdtemp()
353 src = os.path.join(tmp_dir, 'foo')
354 dst = os.path.join(tmp_dir, 'bar')
355 src_link = os.path.join(tmp_dir, 'baz')
356 dst_link = os.path.join(tmp_dir, 'qux')
357 write_file(src, 'foo')
358 src_stat = os.stat(src)
359 os.utime(src, (src_stat.st_atime,
360 src_stat.st_mtime - 42.0)) # ensure different mtimes
361 write_file(dst, 'bar')
362 self.assertNotEqual(os.stat(src).st_mtime, os.stat(dst).st_mtime)
363 os.symlink(src, src_link)
364 os.symlink(dst, dst_link)
365 if hasattr(os, 'lchmod'):
366 os.lchmod(src_link, stat.S_IRWXO)
367 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'):
368 os.lchflags(src_link, stat.UF_NODUMP)
369 src_link_stat = os.lstat(src_link)
370 # follow
371 if hasattr(os, 'lchmod'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700372 shutil.copystat(src_link, dst_link, follow_symlinks=True)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100373 self.assertNotEqual(src_link_stat.st_mode, os.stat(dst).st_mode)
374 # don't follow
Larry Hastingsb4038062012-07-15 10:57:38 -0700375 shutil.copystat(src_link, dst_link, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100376 dst_link_stat = os.lstat(dst_link)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700377 if os.utime in os.supports_follow_symlinks:
Antoine Pitrou78091e62011-12-29 18:54:15 +0100378 for attr in 'st_atime', 'st_mtime':
379 # The modification times may be truncated in the new file.
380 self.assertLessEqual(getattr(src_link_stat, attr),
381 getattr(dst_link_stat, attr) + 1)
382 if hasattr(os, 'lchmod'):
383 self.assertEqual(src_link_stat.st_mode, dst_link_stat.st_mode)
384 if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'):
385 self.assertEqual(src_link_stat.st_flags, dst_link_stat.st_flags)
386 # tell to follow but dst is not a link
Larry Hastingsb4038062012-07-15 10:57:38 -0700387 shutil.copystat(src_link, dst, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100388 self.assertTrue(abs(os.stat(src).st_mtime - os.stat(dst).st_mtime) <
389 00000.1)
390
Ned Deilybaf75712012-05-10 17:05:19 -0700391 @unittest.skipUnless(hasattr(os, 'chflags') and
392 hasattr(errno, 'EOPNOTSUPP') and
393 hasattr(errno, 'ENOTSUP'),
394 "requires os.chflags, EOPNOTSUPP & ENOTSUP")
395 def test_copystat_handles_harmless_chflags_errors(self):
396 tmpdir = self.mkdtemp()
397 file1 = os.path.join(tmpdir, 'file1')
398 file2 = os.path.join(tmpdir, 'file2')
399 write_file(file1, 'xxx')
400 write_file(file2, 'xxx')
401
402 def make_chflags_raiser(err):
403 ex = OSError()
404
Larry Hastings90867a52012-06-22 17:01:41 -0700405 def _chflags_raiser(path, flags, *, follow_symlinks=True):
Ned Deilybaf75712012-05-10 17:05:19 -0700406 ex.errno = err
407 raise ex
408 return _chflags_raiser
409 old_chflags = os.chflags
410 try:
411 for err in errno.EOPNOTSUPP, errno.ENOTSUP:
412 os.chflags = make_chflags_raiser(err)
413 shutil.copystat(file1, file2)
414 # assert others errors break it
415 os.chflags = make_chflags_raiser(errno.EOPNOTSUPP + errno.ENOTSUP)
416 self.assertRaises(OSError, shutil.copystat, file1, file2)
417 finally:
418 os.chflags = old_chflags
419
Antoine Pitrou424246f2012-05-12 19:02:01 +0200420 @support.skip_unless_xattr
421 def test_copyxattr(self):
422 tmp_dir = self.mkdtemp()
423 src = os.path.join(tmp_dir, 'foo')
424 write_file(src, 'foo')
425 dst = os.path.join(tmp_dir, 'bar')
426 write_file(dst, 'bar')
427
428 # no xattr == no problem
429 shutil._copyxattr(src, dst)
430 # common case
431 os.setxattr(src, 'user.foo', b'42')
432 os.setxattr(src, 'user.bar', b'43')
433 shutil._copyxattr(src, dst)
Gregory P. Smith1093bf22014-01-17 12:01:22 -0800434 self.assertEqual(sorted(os.listxattr(src)), sorted(os.listxattr(dst)))
Antoine Pitrou424246f2012-05-12 19:02:01 +0200435 self.assertEqual(
436 os.getxattr(src, 'user.foo'),
437 os.getxattr(dst, 'user.foo'))
438 # check errors don't affect other attrs
439 os.remove(dst)
440 write_file(dst, 'bar')
441 os_error = OSError(errno.EPERM, 'EPERM')
442
Larry Hastings9cf065c2012-06-22 16:30:09 -0700443 def _raise_on_user_foo(fname, attr, val, **kwargs):
Antoine Pitrou424246f2012-05-12 19:02:01 +0200444 if attr == 'user.foo':
445 raise os_error
446 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700447 orig_setxattr(fname, attr, val, **kwargs)
Antoine Pitrou424246f2012-05-12 19:02:01 +0200448 try:
449 orig_setxattr = os.setxattr
450 os.setxattr = _raise_on_user_foo
451 shutil._copyxattr(src, dst)
Antoine Pitrou61597d32012-05-12 23:37:35 +0200452 self.assertIn('user.bar', os.listxattr(dst))
Antoine Pitrou424246f2012-05-12 19:02:01 +0200453 finally:
454 os.setxattr = orig_setxattr
Hynek Schlawack0beab052013-02-05 08:22:44 +0100455 # the source filesystem not supporting xattrs should be ok, too.
456 def _raise_on_src(fname, *, follow_symlinks=True):
457 if fname == src:
458 raise OSError(errno.ENOTSUP, 'Operation not supported')
459 return orig_listxattr(fname, follow_symlinks=follow_symlinks)
460 try:
461 orig_listxattr = os.listxattr
462 os.listxattr = _raise_on_src
463 shutil._copyxattr(src, dst)
464 finally:
465 os.listxattr = orig_listxattr
Antoine Pitrou424246f2012-05-12 19:02:01 +0200466
Larry Hastingsad5ae042012-07-14 17:55:11 -0700467 # test that shutil.copystat copies xattrs
468 src = os.path.join(tmp_dir, 'the_original')
469 write_file(src, src)
470 os.setxattr(src, 'user.the_value', b'fiddly')
471 dst = os.path.join(tmp_dir, 'the_copy')
472 write_file(dst, dst)
473 shutil.copystat(src, dst)
Hynek Schlawackc2d481f2012-07-16 17:11:10 +0200474 self.assertEqual(os.getxattr(dst, 'user.the_value'), b'fiddly')
Larry Hastingsad5ae042012-07-14 17:55:11 -0700475
Antoine Pitrou424246f2012-05-12 19:02:01 +0200476 @support.skip_unless_symlink
477 @support.skip_unless_xattr
478 @unittest.skipUnless(hasattr(os, 'geteuid') and os.geteuid() == 0,
479 'root privileges required')
480 def test_copyxattr_symlinks(self):
481 # On Linux, it's only possible to access non-user xattr for symlinks;
482 # which in turn require root privileges. This test should be expanded
483 # as soon as other platforms gain support for extended attributes.
484 tmp_dir = self.mkdtemp()
485 src = os.path.join(tmp_dir, 'foo')
486 src_link = os.path.join(tmp_dir, 'baz')
487 write_file(src, 'foo')
488 os.symlink(src, src_link)
489 os.setxattr(src, 'trusted.foo', b'42')
Larry Hastings9cf065c2012-06-22 16:30:09 -0700490 os.setxattr(src_link, 'trusted.foo', b'43', follow_symlinks=False)
Antoine Pitrou424246f2012-05-12 19:02:01 +0200491 dst = os.path.join(tmp_dir, 'bar')
492 dst_link = os.path.join(tmp_dir, 'qux')
493 write_file(dst, 'bar')
494 os.symlink(dst, dst_link)
Larry Hastingsb4038062012-07-15 10:57:38 -0700495 shutil._copyxattr(src_link, dst_link, follow_symlinks=False)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700496 self.assertEqual(os.getxattr(dst_link, 'trusted.foo', follow_symlinks=False), b'43')
Antoine Pitrou424246f2012-05-12 19:02:01 +0200497 self.assertRaises(OSError, os.getxattr, dst, 'trusted.foo')
Larry Hastingsb4038062012-07-15 10:57:38 -0700498 shutil._copyxattr(src_link, dst, follow_symlinks=False)
Antoine Pitrou424246f2012-05-12 19:02:01 +0200499 self.assertEqual(os.getxattr(dst, 'trusted.foo'), b'43')
500
Antoine Pitrou78091e62011-12-29 18:54:15 +0100501 @support.skip_unless_symlink
502 def test_copy_symlinks(self):
503 tmp_dir = self.mkdtemp()
504 src = os.path.join(tmp_dir, 'foo')
505 dst = os.path.join(tmp_dir, 'bar')
506 src_link = os.path.join(tmp_dir, 'baz')
507 write_file(src, 'foo')
508 os.symlink(src, src_link)
509 if hasattr(os, 'lchmod'):
510 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO)
511 # don't follow
Larry Hastingsb4038062012-07-15 10:57:38 -0700512 shutil.copy(src_link, dst, follow_symlinks=True)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100513 self.assertFalse(os.path.islink(dst))
514 self.assertEqual(read_file(src), read_file(dst))
515 os.remove(dst)
516 # follow
Larry Hastingsb4038062012-07-15 10:57:38 -0700517 shutil.copy(src_link, dst, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100518 self.assertTrue(os.path.islink(dst))
519 self.assertEqual(os.readlink(dst), os.readlink(src_link))
520 if hasattr(os, 'lchmod'):
521 self.assertEqual(os.lstat(src_link).st_mode,
522 os.lstat(dst).st_mode)
523
524 @support.skip_unless_symlink
525 def test_copy2_symlinks(self):
526 tmp_dir = self.mkdtemp()
527 src = os.path.join(tmp_dir, 'foo')
528 dst = os.path.join(tmp_dir, 'bar')
529 src_link = os.path.join(tmp_dir, 'baz')
530 write_file(src, 'foo')
531 os.symlink(src, src_link)
532 if hasattr(os, 'lchmod'):
533 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO)
534 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'):
535 os.lchflags(src_link, stat.UF_NODUMP)
536 src_stat = os.stat(src)
537 src_link_stat = os.lstat(src_link)
538 # follow
Larry Hastingsb4038062012-07-15 10:57:38 -0700539 shutil.copy2(src_link, dst, follow_symlinks=True)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100540 self.assertFalse(os.path.islink(dst))
541 self.assertEqual(read_file(src), read_file(dst))
542 os.remove(dst)
543 # don't follow
Larry Hastingsb4038062012-07-15 10:57:38 -0700544 shutil.copy2(src_link, dst, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100545 self.assertTrue(os.path.islink(dst))
546 self.assertEqual(os.readlink(dst), os.readlink(src_link))
547 dst_stat = os.lstat(dst)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700548 if os.utime in os.supports_follow_symlinks:
Antoine Pitrou78091e62011-12-29 18:54:15 +0100549 for attr in 'st_atime', 'st_mtime':
550 # The modification times may be truncated in the new file.
551 self.assertLessEqual(getattr(src_link_stat, attr),
552 getattr(dst_stat, attr) + 1)
553 if hasattr(os, 'lchmod'):
554 self.assertEqual(src_link_stat.st_mode, dst_stat.st_mode)
555 self.assertNotEqual(src_stat.st_mode, dst_stat.st_mode)
556 if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'):
557 self.assertEqual(src_link_stat.st_flags, dst_stat.st_flags)
558
Antoine Pitrou424246f2012-05-12 19:02:01 +0200559 @support.skip_unless_xattr
560 def test_copy2_xattr(self):
561 tmp_dir = self.mkdtemp()
562 src = os.path.join(tmp_dir, 'foo')
563 dst = os.path.join(tmp_dir, 'bar')
564 write_file(src, 'foo')
565 os.setxattr(src, 'user.foo', b'42')
566 shutil.copy2(src, dst)
567 self.assertEqual(
568 os.getxattr(src, 'user.foo'),
569 os.getxattr(dst, 'user.foo'))
570 os.remove(dst)
571
Antoine Pitrou78091e62011-12-29 18:54:15 +0100572 @support.skip_unless_symlink
573 def test_copyfile_symlinks(self):
574 tmp_dir = self.mkdtemp()
575 src = os.path.join(tmp_dir, 'src')
576 dst = os.path.join(tmp_dir, 'dst')
577 dst_link = os.path.join(tmp_dir, 'dst_link')
578 link = os.path.join(tmp_dir, 'link')
579 write_file(src, 'foo')
580 os.symlink(src, link)
581 # don't follow
Larry Hastingsb4038062012-07-15 10:57:38 -0700582 shutil.copyfile(link, dst_link, follow_symlinks=False)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100583 self.assertTrue(os.path.islink(dst_link))
584 self.assertEqual(os.readlink(link), os.readlink(dst_link))
585 # follow
586 shutil.copyfile(link, dst)
587 self.assertFalse(os.path.islink(dst))
588
Hynek Schlawack2100b422012-06-23 20:28:32 +0200589 def test_rmtree_uses_safe_fd_version_if_available(self):
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200590 _use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
591 os.supports_dir_fd and
592 os.listdir in os.supports_fd and
593 os.stat in os.supports_follow_symlinks)
594 if _use_fd_functions:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200595 self.assertTrue(shutil._use_fd_functions)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000596 self.assertTrue(shutil.rmtree.avoids_symlink_attacks)
Hynek Schlawack2100b422012-06-23 20:28:32 +0200597 tmp_dir = self.mkdtemp()
598 d = os.path.join(tmp_dir, 'a')
599 os.mkdir(d)
600 try:
601 real_rmtree = shutil._rmtree_safe_fd
602 class Called(Exception): pass
603 def _raiser(*args, **kwargs):
604 raise Called
605 shutil._rmtree_safe_fd = _raiser
606 self.assertRaises(Called, shutil.rmtree, d)
607 finally:
608 shutil._rmtree_safe_fd = real_rmtree
609 else:
610 self.assertFalse(shutil._use_fd_functions)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000611 self.assertFalse(shutil.rmtree.avoids_symlink_attacks)
Hynek Schlawack2100b422012-06-23 20:28:32 +0200612
Johannes Gijsbersd60e92a2004-09-11 21:26:21 +0000613 def test_rmtree_dont_delete_file(self):
614 # When called on a file instead of a directory, don't delete it.
615 handle, path = tempfile.mkstemp()
Victor Stinnerbf816222011-06-30 23:25:47 +0200616 os.close(handle)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200617 self.assertRaises(NotADirectoryError, shutil.rmtree, path)
Johannes Gijsbersd60e92a2004-09-11 21:26:21 +0000618 os.remove(path)
619
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000620 def test_copytree_simple(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000621 src_dir = tempfile.mkdtemp()
622 dst_dir = os.path.join(tempfile.mkdtemp(), 'destination')
Éric Araujoa7e33a12011-08-12 19:51:35 +0200623 self.addCleanup(shutil.rmtree, src_dir)
624 self.addCleanup(shutil.rmtree, os.path.dirname(dst_dir))
625 write_file((src_dir, 'test.txt'), '123')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000626 os.mkdir(os.path.join(src_dir, 'test_dir'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200627 write_file((src_dir, 'test_dir', 'test.txt'), '456')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000628
Éric Araujoa7e33a12011-08-12 19:51:35 +0200629 shutil.copytree(src_dir, dst_dir)
630 self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test.txt')))
631 self.assertTrue(os.path.isdir(os.path.join(dst_dir, 'test_dir')))
632 self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test_dir',
633 'test.txt')))
634 actual = read_file((dst_dir, 'test.txt'))
635 self.assertEqual(actual, '123')
636 actual = read_file((dst_dir, 'test_dir', 'test.txt'))
637 self.assertEqual(actual, '456')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000638
Antoine Pitrou78091e62011-12-29 18:54:15 +0100639 @support.skip_unless_symlink
640 def test_copytree_symlinks(self):
641 tmp_dir = self.mkdtemp()
642 src_dir = os.path.join(tmp_dir, 'src')
643 dst_dir = os.path.join(tmp_dir, 'dst')
644 sub_dir = os.path.join(src_dir, 'sub')
645 os.mkdir(src_dir)
646 os.mkdir(sub_dir)
647 write_file((src_dir, 'file.txt'), 'foo')
648 src_link = os.path.join(sub_dir, 'link')
649 dst_link = os.path.join(dst_dir, 'sub/link')
650 os.symlink(os.path.join(src_dir, 'file.txt'),
651 src_link)
652 if hasattr(os, 'lchmod'):
653 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO)
654 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'):
655 os.lchflags(src_link, stat.UF_NODUMP)
656 src_stat = os.lstat(src_link)
657 shutil.copytree(src_dir, dst_dir, symlinks=True)
658 self.assertTrue(os.path.islink(os.path.join(dst_dir, 'sub', 'link')))
659 self.assertEqual(os.readlink(os.path.join(dst_dir, 'sub', 'link')),
660 os.path.join(src_dir, 'file.txt'))
661 dst_stat = os.lstat(dst_link)
662 if hasattr(os, 'lchmod'):
663 self.assertEqual(dst_stat.st_mode, src_stat.st_mode)
664 if hasattr(os, 'lchflags'):
665 self.assertEqual(dst_stat.st_flags, src_stat.st_flags)
666
Georg Brandl2ee470f2008-07-16 12:55:28 +0000667 def test_copytree_with_exclude(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000668 # creating data
669 join = os.path.join
670 exists = os.path.exists
671 src_dir = tempfile.mkdtemp()
Georg Brandl2ee470f2008-07-16 12:55:28 +0000672 try:
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000673 dst_dir = join(tempfile.mkdtemp(), 'destination')
Éric Araujoa7e33a12011-08-12 19:51:35 +0200674 write_file((src_dir, 'test.txt'), '123')
675 write_file((src_dir, 'test.tmp'), '123')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000676 os.mkdir(join(src_dir, 'test_dir'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200677 write_file((src_dir, 'test_dir', 'test.txt'), '456')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000678 os.mkdir(join(src_dir, 'test_dir2'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200679 write_file((src_dir, 'test_dir2', 'test.txt'), '456')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000680 os.mkdir(join(src_dir, 'test_dir2', 'subdir'))
681 os.mkdir(join(src_dir, 'test_dir2', 'subdir2'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200682 write_file((src_dir, 'test_dir2', 'subdir', 'test.txt'), '456')
683 write_file((src_dir, 'test_dir2', 'subdir2', 'test.py'), '456')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000684
685 # testing glob-like patterns
686 try:
687 patterns = shutil.ignore_patterns('*.tmp', 'test_dir2')
688 shutil.copytree(src_dir, dst_dir, ignore=patterns)
689 # checking the result: some elements should not be copied
690 self.assertTrue(exists(join(dst_dir, 'test.txt')))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200691 self.assertFalse(exists(join(dst_dir, 'test.tmp')))
692 self.assertFalse(exists(join(dst_dir, 'test_dir2')))
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000693 finally:
Éric Araujoa7e33a12011-08-12 19:51:35 +0200694 shutil.rmtree(dst_dir)
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000695 try:
696 patterns = shutil.ignore_patterns('*.tmp', 'subdir*')
697 shutil.copytree(src_dir, dst_dir, ignore=patterns)
698 # checking the result: some elements should not be copied
Éric Araujoa7e33a12011-08-12 19:51:35 +0200699 self.assertFalse(exists(join(dst_dir, 'test.tmp')))
700 self.assertFalse(exists(join(dst_dir, 'test_dir2', 'subdir2')))
701 self.assertFalse(exists(join(dst_dir, 'test_dir2', 'subdir')))
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000702 finally:
Éric Araujoa7e33a12011-08-12 19:51:35 +0200703 shutil.rmtree(dst_dir)
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000704
705 # testing callable-style
706 try:
707 def _filter(src, names):
708 res = []
709 for name in names:
710 path = os.path.join(src, name)
711
712 if (os.path.isdir(path) and
713 path.split()[-1] == 'subdir'):
714 res.append(name)
715 elif os.path.splitext(path)[-1] in ('.py'):
716 res.append(name)
717 return res
718
719 shutil.copytree(src_dir, dst_dir, ignore=_filter)
720
721 # checking the result: some elements should not be copied
Éric Araujoa7e33a12011-08-12 19:51:35 +0200722 self.assertFalse(exists(join(dst_dir, 'test_dir2', 'subdir2',
723 'test.py')))
724 self.assertFalse(exists(join(dst_dir, 'test_dir2', 'subdir')))
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000725
726 finally:
Éric Araujoa7e33a12011-08-12 19:51:35 +0200727 shutil.rmtree(dst_dir)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000728 finally:
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000729 shutil.rmtree(src_dir)
730 shutil.rmtree(os.path.dirname(dst_dir))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000731
Antoine Pitrouac601602013-08-16 19:35:02 +0200732 def test_copytree_retains_permissions(self):
733 tmp_dir = tempfile.mkdtemp()
734 src_dir = os.path.join(tmp_dir, 'source')
735 os.mkdir(src_dir)
736 dst_dir = os.path.join(tmp_dir, 'destination')
737 self.addCleanup(shutil.rmtree, tmp_dir)
738
739 os.chmod(src_dir, 0o777)
740 write_file((src_dir, 'permissive.txt'), '123')
741 os.chmod(os.path.join(src_dir, 'permissive.txt'), 0o777)
742 write_file((src_dir, 'restrictive.txt'), '456')
743 os.chmod(os.path.join(src_dir, 'restrictive.txt'), 0o600)
744 restrictive_subdir = tempfile.mkdtemp(dir=src_dir)
745 os.chmod(restrictive_subdir, 0o600)
746
747 shutil.copytree(src_dir, dst_dir)
Brett Cannon9c7eb552013-08-23 14:38:11 -0400748 self.assertEqual(os.stat(src_dir).st_mode, os.stat(dst_dir).st_mode)
749 self.assertEqual(os.stat(os.path.join(src_dir, 'permissive.txt')).st_mode,
Antoine Pitrouac601602013-08-16 19:35:02 +0200750 os.stat(os.path.join(dst_dir, 'permissive.txt')).st_mode)
Brett Cannon9c7eb552013-08-23 14:38:11 -0400751 self.assertEqual(os.stat(os.path.join(src_dir, 'restrictive.txt')).st_mode,
Antoine Pitrouac601602013-08-16 19:35:02 +0200752 os.stat(os.path.join(dst_dir, 'restrictive.txt')).st_mode)
753 restrictive_subdir_dst = os.path.join(dst_dir,
754 os.path.split(restrictive_subdir)[1])
Brett Cannon9c7eb552013-08-23 14:38:11 -0400755 self.assertEqual(os.stat(restrictive_subdir).st_mode,
Antoine Pitrouac601602013-08-16 19:35:02 +0200756 os.stat(restrictive_subdir_dst).st_mode)
757
Zachary Ware9fe6d862013-12-08 00:20:35 -0600758 @unittest.skipIf(os.name == 'nt', 'temporarily disabled on Windows')
Hirokazu Yamamoto26681452010-12-05 02:04:16 +0000759 @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000760 def test_dont_copy_file_onto_link_to_itself(self):
761 # bug 851123.
762 os.mkdir(TESTFN)
763 src = os.path.join(TESTFN, 'cheese')
764 dst = os.path.join(TESTFN, 'shop')
765 try:
Hirokazu Yamamoto26681452010-12-05 02:04:16 +0000766 with open(src, 'w') as f:
767 f.write('cheddar')
768 os.link(src, dst)
Hynek Schlawack48653762012-10-07 12:49:58 +0200769 self.assertRaises(shutil.SameFileError, shutil.copyfile, src, dst)
Hirokazu Yamamoto26681452010-12-05 02:04:16 +0000770 with open(src, 'r') as f:
771 self.assertEqual(f.read(), 'cheddar')
772 os.remove(dst)
773 finally:
774 shutil.rmtree(TESTFN, ignore_errors=True)
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000775
Brian Curtin3b4499c2010-12-28 14:31:47 +0000776 @support.skip_unless_symlink
Hirokazu Yamamoto26681452010-12-05 02:04:16 +0000777 def test_dont_copy_file_onto_symlink_to_itself(self):
778 # bug 851123.
779 os.mkdir(TESTFN)
780 src = os.path.join(TESTFN, 'cheese')
781 dst = os.path.join(TESTFN, 'shop')
782 try:
783 with open(src, 'w') as f:
784 f.write('cheddar')
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000785 # Using `src` here would mean we end up with a symlink pointing
786 # to TESTFN/TESTFN/cheese, while it should point at
787 # TESTFN/cheese.
788 os.symlink('cheese', dst)
Hynek Schlawack48653762012-10-07 12:49:58 +0200789 self.assertRaises(shutil.SameFileError, shutil.copyfile, src, dst)
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000790 with open(src, 'r') as f:
791 self.assertEqual(f.read(), 'cheddar')
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000792 os.remove(dst)
793 finally:
Hirokazu Yamamoto26681452010-12-05 02:04:16 +0000794 shutil.rmtree(TESTFN, ignore_errors=True)
Johannes Gijsbers68128712004-08-14 13:57:08 +0000795
Brian Curtin3b4499c2010-12-28 14:31:47 +0000796 @support.skip_unless_symlink
Brian Curtind40e6f72010-07-08 21:39:08 +0000797 def test_rmtree_on_symlink(self):
798 # bug 1669.
799 os.mkdir(TESTFN)
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000800 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000801 src = os.path.join(TESTFN, 'cheese')
802 dst = os.path.join(TESTFN, 'shop')
803 os.mkdir(src)
804 os.symlink(src, dst)
805 self.assertRaises(OSError, shutil.rmtree, dst)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200806 shutil.rmtree(dst, ignore_errors=True)
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000807 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000808 shutil.rmtree(TESTFN, ignore_errors=True)
809
Serhiy Storchaka43767632013-11-03 21:31:38 +0200810 # Issue #3002: copyfile and copytree block indefinitely on named pipes
811 @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()')
812 def test_copyfile_named_pipe(self):
813 os.mkfifo(TESTFN)
814 try:
815 self.assertRaises(shutil.SpecialFileError,
816 shutil.copyfile, TESTFN, TESTFN2)
817 self.assertRaises(shutil.SpecialFileError,
818 shutil.copyfile, __file__, TESTFN)
819 finally:
820 os.remove(TESTFN)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000821
Serhiy Storchaka43767632013-11-03 21:31:38 +0200822 @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()')
823 @support.skip_unless_symlink
824 def test_copytree_named_pipe(self):
825 os.mkdir(TESTFN)
826 try:
827 subdir = os.path.join(TESTFN, "subdir")
828 os.mkdir(subdir)
829 pipe = os.path.join(subdir, "mypipe")
830 os.mkfifo(pipe)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000831 try:
Serhiy Storchaka43767632013-11-03 21:31:38 +0200832 shutil.copytree(TESTFN, TESTFN2)
833 except shutil.Error as e:
834 errors = e.args[0]
835 self.assertEqual(len(errors), 1)
836 src, dst, error_msg = errors[0]
837 self.assertEqual("`%s` is a named pipe" % pipe, error_msg)
838 else:
839 self.fail("shutil.Error should have been raised")
840 finally:
841 shutil.rmtree(TESTFN, ignore_errors=True)
842 shutil.rmtree(TESTFN2, ignore_errors=True)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000843
Tarek Ziadé5340db32010-04-19 22:30:51 +0000844 def test_copytree_special_func(self):
845
846 src_dir = self.mkdtemp()
847 dst_dir = os.path.join(self.mkdtemp(), 'destination')
Éric Araujoa7e33a12011-08-12 19:51:35 +0200848 write_file((src_dir, 'test.txt'), '123')
Tarek Ziadé5340db32010-04-19 22:30:51 +0000849 os.mkdir(os.path.join(src_dir, 'test_dir'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200850 write_file((src_dir, 'test_dir', 'test.txt'), '456')
Tarek Ziadé5340db32010-04-19 22:30:51 +0000851
852 copied = []
853 def _copy(src, dst):
854 copied.append((src, dst))
855
856 shutil.copytree(src_dir, dst_dir, copy_function=_copy)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000857 self.assertEqual(len(copied), 2)
Tarek Ziadé5340db32010-04-19 22:30:51 +0000858
Brian Curtin3b4499c2010-12-28 14:31:47 +0000859 @support.skip_unless_symlink
Tarek Ziadéfb437512010-04-20 08:57:33 +0000860 def test_copytree_dangling_symlinks(self):
861
862 # a dangling symlink raises an error at the end
863 src_dir = self.mkdtemp()
864 dst_dir = os.path.join(self.mkdtemp(), 'destination')
865 os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))
866 os.mkdir(os.path.join(src_dir, 'test_dir'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200867 write_file((src_dir, 'test_dir', 'test.txt'), '456')
Tarek Ziadéfb437512010-04-20 08:57:33 +0000868 self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
869
870 # a dangling symlink is ignored with the proper flag
871 dst_dir = os.path.join(self.mkdtemp(), 'destination2')
872 shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
873 self.assertNotIn('test.txt', os.listdir(dst_dir))
874
875 # a dangling symlink is copied if symlinks=True
876 dst_dir = os.path.join(self.mkdtemp(), 'destination3')
877 shutil.copytree(src_dir, dst_dir, symlinks=True)
878 self.assertIn('test.txt', os.listdir(dst_dir))
879
Nick Coghlan8ed3cf32011-03-16 14:05:35 -0400880 def _copy_file(self, method):
881 fname = 'test.txt'
882 tmpdir = self.mkdtemp()
Éric Araujoa7e33a12011-08-12 19:51:35 +0200883 write_file((tmpdir, fname), 'xxx')
Nick Coghlan8ed3cf32011-03-16 14:05:35 -0400884 file1 = os.path.join(tmpdir, fname)
885 tmpdir2 = self.mkdtemp()
886 method(file1, tmpdir2)
887 file2 = os.path.join(tmpdir2, fname)
888 return (file1, file2)
889
890 @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod')
891 def test_copy(self):
892 # Ensure that the copied file exists and has the same mode bits.
893 file1, file2 = self._copy_file(shutil.copy)
894 self.assertTrue(os.path.exists(file2))
895 self.assertEqual(os.stat(file1).st_mode, os.stat(file2).st_mode)
896
897 @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod')
Senthil Kumaran0c2dba52011-07-03 18:21:38 -0700898 @unittest.skipUnless(hasattr(os, 'utime'), 'requires os.utime')
Nick Coghlan8ed3cf32011-03-16 14:05:35 -0400899 def test_copy2(self):
900 # Ensure that the copied file exists and has the same mode and
901 # modification time bits.
902 file1, file2 = self._copy_file(shutil.copy2)
903 self.assertTrue(os.path.exists(file2))
904 file1_stat = os.stat(file1)
905 file2_stat = os.stat(file2)
906 self.assertEqual(file1_stat.st_mode, file2_stat.st_mode)
907 for attr in 'st_atime', 'st_mtime':
908 # The modification times may be truncated in the new file.
909 self.assertLessEqual(getattr(file1_stat, attr),
910 getattr(file2_stat, attr) + 1)
911 if hasattr(os, 'chflags') and hasattr(file1_stat, 'st_flags'):
912 self.assertEqual(getattr(file1_stat, 'st_flags'),
913 getattr(file2_stat, 'st_flags'))
914
Ezio Melotti975077a2011-05-19 22:03:22 +0300915 @requires_zlib
Tarek Ziadé396fad72010-02-23 05:30:31 +0000916 def test_make_tarball(self):
917 # creating something to tar
918 tmpdir = self.mkdtemp()
Éric Araujoa7e33a12011-08-12 19:51:35 +0200919 write_file((tmpdir, 'file1'), 'xxx')
920 write_file((tmpdir, 'file2'), 'xxx')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000921 os.mkdir(os.path.join(tmpdir, 'sub'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200922 write_file((tmpdir, 'sub', 'file3'), 'xxx')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000923
924 tmpdir2 = self.mkdtemp()
Nick Coghlan8ed3cf32011-03-16 14:05:35 -0400925 # force shutil to create the directory
926 os.rmdir(tmpdir2)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000927 unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
928 "source and target should be on same drive")
929
930 base_name = os.path.join(tmpdir2, 'archive')
931
932 # working with relative paths to avoid tar warnings
933 old_dir = os.getcwd()
934 os.chdir(tmpdir)
935 try:
936 _make_tarball(splitdrive(base_name)[1], '.')
937 finally:
938 os.chdir(old_dir)
939
940 # check if the compressed tarball was created
941 tarball = base_name + '.tar.gz'
942 self.assertTrue(os.path.exists(tarball))
943
944 # trying an uncompressed one
945 base_name = os.path.join(tmpdir2, 'archive')
946 old_dir = os.getcwd()
947 os.chdir(tmpdir)
948 try:
949 _make_tarball(splitdrive(base_name)[1], '.', compress=None)
950 finally:
951 os.chdir(old_dir)
952 tarball = base_name + '.tar'
953 self.assertTrue(os.path.exists(tarball))
954
955 def _tarinfo(self, path):
956 tar = tarfile.open(path)
957 try:
958 names = tar.getnames()
959 names.sort()
960 return tuple(names)
961 finally:
962 tar.close()
963
964 def _create_files(self):
965 # creating something to tar
966 tmpdir = self.mkdtemp()
967 dist = os.path.join(tmpdir, 'dist')
968 os.mkdir(dist)
Éric Araujoa7e33a12011-08-12 19:51:35 +0200969 write_file((dist, 'file1'), 'xxx')
970 write_file((dist, 'file2'), 'xxx')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000971 os.mkdir(os.path.join(dist, 'sub'))
Éric Araujoa7e33a12011-08-12 19:51:35 +0200972 write_file((dist, 'sub', 'file3'), 'xxx')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000973 os.mkdir(os.path.join(dist, 'sub2'))
974 tmpdir2 = self.mkdtemp()
975 base_name = os.path.join(tmpdir2, 'archive')
976 return tmpdir, tmpdir2, base_name
977
Ezio Melotti975077a2011-05-19 22:03:22 +0300978 @requires_zlib
Tarek Ziadé396fad72010-02-23 05:30:31 +0000979 @unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
980 'Need the tar command to run')
981 def test_tarfile_vs_tar(self):
982 tmpdir, tmpdir2, base_name = self._create_files()
983 old_dir = os.getcwd()
984 os.chdir(tmpdir)
985 try:
986 _make_tarball(base_name, 'dist')
987 finally:
988 os.chdir(old_dir)
989
990 # check if the compressed tarball was created
991 tarball = base_name + '.tar.gz'
992 self.assertTrue(os.path.exists(tarball))
993
994 # now create another tarball using `tar`
995 tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
996 tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist']
997 gzip_cmd = ['gzip', '-f9', 'archive2.tar']
998 old_dir = os.getcwd()
999 os.chdir(tmpdir)
1000 try:
1001 with captured_stdout() as s:
1002 spawn(tar_cmd)
1003 spawn(gzip_cmd)
1004 finally:
1005 os.chdir(old_dir)
1006
1007 self.assertTrue(os.path.exists(tarball2))
1008 # let's compare both tarballs
Ezio Melottib3aedd42010-11-20 19:04:17 +00001009 self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2))
Tarek Ziadé396fad72010-02-23 05:30:31 +00001010
1011 # trying an uncompressed one
1012 base_name = os.path.join(tmpdir2, 'archive')
1013 old_dir = os.getcwd()
1014 os.chdir(tmpdir)
1015 try:
1016 _make_tarball(base_name, 'dist', compress=None)
1017 finally:
1018 os.chdir(old_dir)
1019 tarball = base_name + '.tar'
1020 self.assertTrue(os.path.exists(tarball))
1021
1022 # now for a dry_run
1023 base_name = os.path.join(tmpdir2, 'archive')
1024 old_dir = os.getcwd()
1025 os.chdir(tmpdir)
1026 try:
1027 _make_tarball(base_name, 'dist', compress=None, dry_run=True)
1028 finally:
1029 os.chdir(old_dir)
1030 tarball = base_name + '.tar'
1031 self.assertTrue(os.path.exists(tarball))
1032
Ezio Melotti975077a2011-05-19 22:03:22 +03001033 @requires_zlib
Tarek Ziadé396fad72010-02-23 05:30:31 +00001034 @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
1035 def test_make_zipfile(self):
1036 # creating something to tar
1037 tmpdir = self.mkdtemp()
Éric Araujoa7e33a12011-08-12 19:51:35 +02001038 write_file((tmpdir, 'file1'), 'xxx')
1039 write_file((tmpdir, 'file2'), 'xxx')
Tarek Ziadé396fad72010-02-23 05:30:31 +00001040
1041 tmpdir2 = self.mkdtemp()
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001042 # force shutil to create the directory
1043 os.rmdir(tmpdir2)
Tarek Ziadé396fad72010-02-23 05:30:31 +00001044 base_name = os.path.join(tmpdir2, 'archive')
1045 _make_zipfile(base_name, tmpdir)
1046
1047 # check if the compressed tarball was created
1048 tarball = base_name + '.zip'
Éric Araujo1c505492010-11-06 02:12:51 +00001049 self.assertTrue(os.path.exists(tarball))
Tarek Ziadé396fad72010-02-23 05:30:31 +00001050
1051
1052 def test_make_archive(self):
1053 tmpdir = self.mkdtemp()
1054 base_name = os.path.join(tmpdir, 'archive')
1055 self.assertRaises(ValueError, make_archive, base_name, 'xxx')
1056
Ezio Melotti975077a2011-05-19 22:03:22 +03001057 @requires_zlib
Tarek Ziadé396fad72010-02-23 05:30:31 +00001058 def test_make_archive_owner_group(self):
1059 # testing make_archive with owner and group, with various combinations
1060 # this works even if there's not gid/uid support
1061 if UID_GID_SUPPORT:
1062 group = grp.getgrgid(0)[0]
1063 owner = pwd.getpwuid(0)[0]
1064 else:
1065 group = owner = 'root'
1066
1067 base_dir, root_dir, base_name = self._create_files()
1068 base_name = os.path.join(self.mkdtemp() , 'archive')
1069 res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner,
1070 group=group)
1071 self.assertTrue(os.path.exists(res))
1072
1073 res = make_archive(base_name, 'zip', root_dir, base_dir)
1074 self.assertTrue(os.path.exists(res))
1075
1076 res = make_archive(base_name, 'tar', root_dir, base_dir,
1077 owner=owner, group=group)
1078 self.assertTrue(os.path.exists(res))
1079
1080 res = make_archive(base_name, 'tar', root_dir, base_dir,
1081 owner='kjhkjhkjg', group='oihohoh')
1082 self.assertTrue(os.path.exists(res))
1083
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001084
Ezio Melotti975077a2011-05-19 22:03:22 +03001085 @requires_zlib
Tarek Ziadé396fad72010-02-23 05:30:31 +00001086 @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
1087 def test_tarfile_root_owner(self):
1088 tmpdir, tmpdir2, base_name = self._create_files()
1089 old_dir = os.getcwd()
1090 os.chdir(tmpdir)
1091 group = grp.getgrgid(0)[0]
1092 owner = pwd.getpwuid(0)[0]
1093 try:
1094 archive_name = _make_tarball(base_name, 'dist', compress=None,
1095 owner=owner, group=group)
1096 finally:
1097 os.chdir(old_dir)
1098
1099 # check if the compressed tarball was created
1100 self.assertTrue(os.path.exists(archive_name))
1101
1102 # now checks the rights
1103 archive = tarfile.open(archive_name)
1104 try:
1105 for member in archive.getmembers():
Ezio Melottib3aedd42010-11-20 19:04:17 +00001106 self.assertEqual(member.uid, 0)
1107 self.assertEqual(member.gid, 0)
Tarek Ziadé396fad72010-02-23 05:30:31 +00001108 finally:
1109 archive.close()
1110
1111 def test_make_archive_cwd(self):
1112 current_dir = os.getcwd()
1113 def _breaks(*args, **kw):
1114 raise RuntimeError()
1115
1116 register_archive_format('xxx', _breaks, [], 'xxx file')
1117 try:
1118 try:
1119 make_archive('xxx', 'xxx', root_dir=self.mkdtemp())
1120 except Exception:
1121 pass
Ezio Melottib3aedd42010-11-20 19:04:17 +00001122 self.assertEqual(os.getcwd(), current_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +00001123 finally:
1124 unregister_archive_format('xxx')
1125
1126 def test_register_archive_format(self):
1127
1128 self.assertRaises(TypeError, register_archive_format, 'xxx', 1)
1129 self.assertRaises(TypeError, register_archive_format, 'xxx', lambda: x,
1130 1)
1131 self.assertRaises(TypeError, register_archive_format, 'xxx', lambda: x,
1132 [(1, 2), (1, 2, 3)])
1133
1134 register_archive_format('xxx', lambda: x, [(1, 2)], 'xxx file')
1135 formats = [name for name, params in get_archive_formats()]
1136 self.assertIn('xxx', formats)
1137
1138 unregister_archive_format('xxx')
1139 formats = [name for name, params in get_archive_formats()]
1140 self.assertNotIn('xxx', formats)
1141
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001142 def _compare_dirs(self, dir1, dir2):
1143 # check that dir1 and dir2 are equivalent,
1144 # return the diff
1145 diff = []
1146 for root, dirs, files in os.walk(dir1):
1147 for file_ in files:
1148 path = os.path.join(root, file_)
1149 target_path = os.path.join(dir2, os.path.split(path)[-1])
1150 if not os.path.exists(target_path):
1151 diff.append(file_)
1152 return diff
1153
Ezio Melotti975077a2011-05-19 22:03:22 +03001154 @requires_zlib
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001155 def test_unpack_archive(self):
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001156 formats = ['tar', 'gztar', 'zip']
1157 if BZ2_SUPPORTED:
1158 formats.append('bztar')
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001159
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001160 for format in formats:
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001161 tmpdir = self.mkdtemp()
1162 base_dir, root_dir, base_name = self._create_files()
1163 tmpdir2 = self.mkdtemp()
1164 filename = make_archive(base_name, format, root_dir, base_dir)
1165
1166 # let's try to unpack it now
1167 unpack_archive(filename, tmpdir2)
1168 diff = self._compare_dirs(tmpdir, tmpdir2)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001169 self.assertEqual(diff, [])
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001170
Nick Coghlanabf202d2011-03-16 13:52:20 -04001171 # and again, this time with the format specified
1172 tmpdir3 = self.mkdtemp()
1173 unpack_archive(filename, tmpdir3, format=format)
1174 diff = self._compare_dirs(tmpdir, tmpdir3)
1175 self.assertEqual(diff, [])
1176 self.assertRaises(shutil.ReadError, unpack_archive, TESTFN)
1177 self.assertRaises(ValueError, unpack_archive, TESTFN, format='xxx')
1178
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001179 def test_unpack_registery(self):
1180
1181 formats = get_unpack_formats()
1182
1183 def _boo(filename, extract_dir, extra):
Ezio Melottib3aedd42010-11-20 19:04:17 +00001184 self.assertEqual(extra, 1)
1185 self.assertEqual(filename, 'stuff.boo')
1186 self.assertEqual(extract_dir, 'xx')
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001187
1188 register_unpack_format('Boo', ['.boo', '.b2'], _boo, [('extra', 1)])
1189 unpack_archive('stuff.boo', 'xx')
1190
1191 # trying to register a .boo unpacker again
1192 self.assertRaises(RegistryError, register_unpack_format, 'Boo2',
1193 ['.boo'], _boo)
1194
1195 # should work now
1196 unregister_unpack_format('Boo')
1197 register_unpack_format('Boo2', ['.boo'], _boo)
1198 self.assertIn(('Boo2', ['.boo'], ''), get_unpack_formats())
1199 self.assertNotIn(('Boo', ['.boo'], ''), get_unpack_formats())
1200
1201 # let's leave a clean state
1202 unregister_unpack_format('Boo2')
Ezio Melottib3aedd42010-11-20 19:04:17 +00001203 self.assertEqual(get_unpack_formats(), formats)
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001204
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001205 @unittest.skipUnless(hasattr(shutil, 'disk_usage'),
1206 "disk_usage not available on this platform")
1207 def test_disk_usage(self):
1208 usage = shutil.disk_usage(os.getcwd())
Éric Araujo2ee61882011-07-02 16:45:45 +02001209 self.assertGreater(usage.total, 0)
1210 self.assertGreater(usage.used, 0)
1211 self.assertGreaterEqual(usage.free, 0)
1212 self.assertGreaterEqual(usage.total, usage.used)
1213 self.assertGreater(usage.total, usage.free)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001214
Sandro Tosid902a142011-08-22 23:28:27 +02001215 @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
1216 @unittest.skipUnless(hasattr(os, 'chown'), 'requires os.chown')
1217 def test_chown(self):
1218
1219 # cleaned-up automatically by TestShutil.tearDown method
1220 dirname = self.mkdtemp()
1221 filename = tempfile.mktemp(dir=dirname)
1222 write_file(filename, 'testing chown function')
1223
1224 with self.assertRaises(ValueError):
1225 shutil.chown(filename)
1226
1227 with self.assertRaises(LookupError):
1228 shutil.chown(filename, user='non-exising username')
1229
1230 with self.assertRaises(LookupError):
1231 shutil.chown(filename, group='non-exising groupname')
1232
1233 with self.assertRaises(TypeError):
1234 shutil.chown(filename, b'spam')
1235
1236 with self.assertRaises(TypeError):
1237 shutil.chown(filename, 3.14)
1238
1239 uid = os.getuid()
1240 gid = os.getgid()
1241
1242 def check_chown(path, uid=None, gid=None):
1243 s = os.stat(filename)
1244 if uid is not None:
1245 self.assertEqual(uid, s.st_uid)
1246 if gid is not None:
1247 self.assertEqual(gid, s.st_gid)
1248
1249 shutil.chown(filename, uid, gid)
1250 check_chown(filename, uid, gid)
1251 shutil.chown(filename, uid)
1252 check_chown(filename, uid)
1253 shutil.chown(filename, user=uid)
1254 check_chown(filename, uid)
1255 shutil.chown(filename, group=gid)
Sandro Tosi91f948a2011-08-22 23:55:39 +02001256 check_chown(filename, gid=gid)
Sandro Tosid902a142011-08-22 23:28:27 +02001257
1258 shutil.chown(dirname, uid, gid)
1259 check_chown(dirname, uid, gid)
1260 shutil.chown(dirname, uid)
1261 check_chown(dirname, uid)
1262 shutil.chown(dirname, user=uid)
1263 check_chown(dirname, uid)
1264 shutil.chown(dirname, group=gid)
Sandro Tosi91f948a2011-08-22 23:55:39 +02001265 check_chown(dirname, gid=gid)
Sandro Tosid902a142011-08-22 23:28:27 +02001266
1267 user = pwd.getpwuid(uid)[0]
1268 group = grp.getgrgid(gid)[0]
1269 shutil.chown(filename, user, group)
1270 check_chown(filename, uid, gid)
1271 shutil.chown(dirname, user, group)
1272 check_chown(dirname, uid, gid)
1273
Brian Curtin0d0a1de2012-06-18 18:41:07 -05001274 def test_copy_return_value(self):
1275 # copy and copy2 both return their destination path.
1276 for fn in (shutil.copy, shutil.copy2):
1277 src_dir = self.mkdtemp()
1278 dst_dir = self.mkdtemp()
1279 src = os.path.join(src_dir, 'foo')
1280 write_file(src, 'foo')
1281 rv = fn(src, dst_dir)
1282 self.assertEqual(rv, os.path.join(dst_dir, 'foo'))
1283 rv = fn(src, os.path.join(dst_dir, 'bar'))
1284 self.assertEqual(rv, os.path.join(dst_dir, 'bar'))
1285
1286 def test_copyfile_return_value(self):
1287 # copytree returns its destination path.
1288 src_dir = self.mkdtemp()
1289 dst_dir = self.mkdtemp()
1290 dst_file = os.path.join(dst_dir, 'bar')
1291 src_file = os.path.join(src_dir, 'foo')
1292 write_file(src_file, 'foo')
1293 rv = shutil.copyfile(src_file, dst_file)
1294 self.assertTrue(os.path.exists(rv))
1295 self.assertEqual(read_file(src_file), read_file(dst_file))
1296
Hynek Schlawack48653762012-10-07 12:49:58 +02001297 def test_copyfile_same_file(self):
1298 # copyfile() should raise SameFileError if the source and destination
1299 # are the same.
1300 src_dir = self.mkdtemp()
1301 src_file = os.path.join(src_dir, 'foo')
1302 write_file(src_file, 'foo')
1303 self.assertRaises(SameFileError, shutil.copyfile, src_file, src_file)
Hynek Schlawack27ddb572012-10-28 13:59:27 +01001304 # But Error should work too, to stay backward compatible.
1305 self.assertRaises(Error, shutil.copyfile, src_file, src_file)
Hynek Schlawack48653762012-10-07 12:49:58 +02001306
Brian Curtin0d0a1de2012-06-18 18:41:07 -05001307 def test_copytree_return_value(self):
1308 # copytree returns its destination path.
1309 src_dir = self.mkdtemp()
1310 dst_dir = src_dir + "dest"
Larry Hastings5b2f9c02012-06-25 23:50:01 -07001311 self.addCleanup(shutil.rmtree, dst_dir, True)
Brian Curtin0d0a1de2012-06-18 18:41:07 -05001312 src = os.path.join(src_dir, 'foo')
1313 write_file(src, 'foo')
1314 rv = shutil.copytree(src_dir, dst_dir)
1315 self.assertEqual(['foo'], os.listdir(rv))
1316
Christian Heimes9bd667a2008-01-20 15:14:11 +00001317
Brian Curtinc57a3452012-06-22 16:00:30 -05001318class TestWhich(unittest.TestCase):
1319
1320 def setUp(self):
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001321 self.temp_dir = tempfile.mkdtemp(prefix="Tmp")
Larry Hastings5b2f9c02012-06-25 23:50:01 -07001322 self.addCleanup(shutil.rmtree, self.temp_dir, True)
Brian Curtinc57a3452012-06-22 16:00:30 -05001323 # Give the temp_file an ".exe" suffix for all.
1324 # It's needed on Windows and not harmful on other platforms.
1325 self.temp_file = tempfile.NamedTemporaryFile(dir=self.temp_dir,
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001326 prefix="Tmp",
1327 suffix=".Exe")
Brian Curtinc57a3452012-06-22 16:00:30 -05001328 os.chmod(self.temp_file.name, stat.S_IXUSR)
1329 self.addCleanup(self.temp_file.close)
1330 self.dir, self.file = os.path.split(self.temp_file.name)
1331
1332 def test_basic(self):
1333 # Given an EXE in a directory, it should be returned.
1334 rv = shutil.which(self.file, path=self.dir)
1335 self.assertEqual(rv, self.temp_file.name)
1336
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001337 def test_absolute_cmd(self):
Brian Curtinc57a3452012-06-22 16:00:30 -05001338 # When given the fully qualified path to an executable that exists,
1339 # it should be returned.
1340 rv = shutil.which(self.temp_file.name, path=self.temp_dir)
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001341 self.assertEqual(rv, self.temp_file.name)
1342
1343 def test_relative_cmd(self):
1344 # When given the relative path with a directory part to an executable
1345 # that exists, it should be returned.
1346 base_dir, tail_dir = os.path.split(self.dir)
1347 relpath = os.path.join(tail_dir, self.file)
Nick Coghlan55175962013-07-28 22:11:50 +10001348 with support.change_cwd(path=base_dir):
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001349 rv = shutil.which(relpath, path=self.temp_dir)
1350 self.assertEqual(rv, relpath)
1351 # But it shouldn't be searched in PATH directories (issue #16957).
Nick Coghlan55175962013-07-28 22:11:50 +10001352 with support.change_cwd(path=self.dir):
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001353 rv = shutil.which(relpath, path=base_dir)
1354 self.assertIsNone(rv)
1355
1356 def test_cwd(self):
1357 # Issue #16957
1358 base_dir = os.path.dirname(self.dir)
Nick Coghlan55175962013-07-28 22:11:50 +10001359 with support.change_cwd(path=self.dir):
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001360 rv = shutil.which(self.file, path=base_dir)
1361 if sys.platform == "win32":
1362 # Windows: current directory implicitly on PATH
1363 self.assertEqual(rv, os.path.join(os.curdir, self.file))
1364 else:
1365 # Other platforms: shouldn't match in the current directory.
1366 self.assertIsNone(rv)
Brian Curtinc57a3452012-06-22 16:00:30 -05001367
Serhiy Storchaka12516e22013-05-28 15:50:15 +03001368 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
1369 'non-root user required')
Brian Curtinc57a3452012-06-22 16:00:30 -05001370 def test_non_matching_mode(self):
1371 # Set the file read-only and ask for writeable files.
1372 os.chmod(self.temp_file.name, stat.S_IREAD)
Serhiy Storchaka12516e22013-05-28 15:50:15 +03001373 if os.access(self.temp_file.name, os.W_OK):
1374 self.skipTest("can't set the file read-only")
Brian Curtinc57a3452012-06-22 16:00:30 -05001375 rv = shutil.which(self.file, path=self.dir, mode=os.W_OK)
1376 self.assertIsNone(rv)
1377
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001378 def test_relative_path(self):
Antoine Pitrou07c24d12012-06-22 23:33:05 +02001379 base_dir, tail_dir = os.path.split(self.dir)
Nick Coghlan55175962013-07-28 22:11:50 +10001380 with support.change_cwd(path=base_dir):
Antoine Pitrou07c24d12012-06-22 23:33:05 +02001381 rv = shutil.which(self.file, path=tail_dir)
1382 self.assertEqual(rv, os.path.join(tail_dir, self.file))
Antoine Pitrou07c24d12012-06-22 23:33:05 +02001383
Brian Curtinc57a3452012-06-22 16:00:30 -05001384 def test_nonexistent_file(self):
1385 # Return None when no matching executable file is found on the path.
1386 rv = shutil.which("foo.exe", path=self.dir)
1387 self.assertIsNone(rv)
1388
1389 @unittest.skipUnless(sys.platform == "win32",
1390 "pathext check is Windows-only")
1391 def test_pathext_checking(self):
1392 # Ask for the file without the ".exe" extension, then ensure that
1393 # it gets found properly with the extension.
Serhiy Storchakad70127a2013-01-24 20:03:49 +02001394 rv = shutil.which(self.file[:-4], path=self.dir)
Serhiy Storchaka80c88f42013-01-22 10:31:36 +02001395 self.assertEqual(rv, self.temp_file.name[:-4] + ".EXE")
Brian Curtinc57a3452012-06-22 16:00:30 -05001396
Barry Warsaw618738b2013-04-16 11:05:03 -04001397 def test_environ_path(self):
1398 with support.EnvironmentVarGuard() as env:
Victor Stinner1d006a22013-12-16 23:39:40 +01001399 env['PATH'] = self.dir
Barry Warsaw618738b2013-04-16 11:05:03 -04001400 rv = shutil.which(self.file)
1401 self.assertEqual(rv, self.temp_file.name)
1402
1403 def test_empty_path(self):
1404 base_dir = os.path.dirname(self.dir)
Nick Coghlan55175962013-07-28 22:11:50 +10001405 with support.change_cwd(path=self.dir), \
Barry Warsaw618738b2013-04-16 11:05:03 -04001406 support.EnvironmentVarGuard() as env:
Victor Stinner1d006a22013-12-16 23:39:40 +01001407 env['PATH'] = self.dir
Barry Warsaw618738b2013-04-16 11:05:03 -04001408 rv = shutil.which(self.file, path='')
1409 self.assertIsNone(rv)
1410
1411 def test_empty_path_no_PATH(self):
1412 with support.EnvironmentVarGuard() as env:
1413 env.pop('PATH', None)
1414 rv = shutil.which(self.file)
1415 self.assertIsNone(rv)
1416
Brian Curtinc57a3452012-06-22 16:00:30 -05001417
Christian Heimesada8c3b2008-03-18 18:26:33 +00001418class TestMove(unittest.TestCase):
1419
1420 def setUp(self):
1421 filename = "foo"
1422 self.src_dir = tempfile.mkdtemp()
1423 self.dst_dir = tempfile.mkdtemp()
1424 self.src_file = os.path.join(self.src_dir, filename)
1425 self.dst_file = os.path.join(self.dst_dir, filename)
Christian Heimesada8c3b2008-03-18 18:26:33 +00001426 with open(self.src_file, "wb") as f:
1427 f.write(b"spam")
1428
1429 def tearDown(self):
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001430 for d in (self.src_dir, self.dst_dir):
Christian Heimesada8c3b2008-03-18 18:26:33 +00001431 try:
1432 if d:
1433 shutil.rmtree(d)
1434 except:
1435 pass
1436
1437 def _check_move_file(self, src, dst, real_dst):
Antoine Pitrou92f60ed2010-10-14 22:11:44 +00001438 with open(src, "rb") as f:
1439 contents = f.read()
Christian Heimesada8c3b2008-03-18 18:26:33 +00001440 shutil.move(src, dst)
Antoine Pitrou92f60ed2010-10-14 22:11:44 +00001441 with open(real_dst, "rb") as f:
1442 self.assertEqual(contents, f.read())
Christian Heimesada8c3b2008-03-18 18:26:33 +00001443 self.assertFalse(os.path.exists(src))
1444
1445 def _check_move_dir(self, src, dst, real_dst):
1446 contents = sorted(os.listdir(src))
1447 shutil.move(src, dst)
1448 self.assertEqual(contents, sorted(os.listdir(real_dst)))
1449 self.assertFalse(os.path.exists(src))
1450
1451 def test_move_file(self):
1452 # Move a file to another location on the same filesystem.
1453 self._check_move_file(self.src_file, self.dst_file, self.dst_file)
1454
1455 def test_move_file_to_dir(self):
1456 # Move a file inside an existing dir on the same filesystem.
1457 self._check_move_file(self.src_file, self.dst_dir, self.dst_file)
1458
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001459 @mock_rename
Christian Heimesada8c3b2008-03-18 18:26:33 +00001460 def test_move_file_other_fs(self):
1461 # Move a file to an existing dir on another filesystem.
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001462 self.test_move_file()
Christian Heimesada8c3b2008-03-18 18:26:33 +00001463
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001464 @mock_rename
Christian Heimesada8c3b2008-03-18 18:26:33 +00001465 def test_move_file_to_dir_other_fs(self):
1466 # Move a file to another location on another filesystem.
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001467 self.test_move_file_to_dir()
Christian Heimesada8c3b2008-03-18 18:26:33 +00001468
1469 def test_move_dir(self):
1470 # Move a dir to another location on the same filesystem.
1471 dst_dir = tempfile.mktemp()
1472 try:
1473 self._check_move_dir(self.src_dir, dst_dir, dst_dir)
1474 finally:
1475 try:
1476 shutil.rmtree(dst_dir)
1477 except:
1478 pass
1479
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001480 @mock_rename
Christian Heimesada8c3b2008-03-18 18:26:33 +00001481 def test_move_dir_other_fs(self):
1482 # Move a dir to another location on another filesystem.
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001483 self.test_move_dir()
Christian Heimesada8c3b2008-03-18 18:26:33 +00001484
1485 def test_move_dir_to_dir(self):
1486 # Move a dir inside an existing dir on the same filesystem.
1487 self._check_move_dir(self.src_dir, self.dst_dir,
1488 os.path.join(self.dst_dir, os.path.basename(self.src_dir)))
1489
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001490 @mock_rename
Christian Heimesada8c3b2008-03-18 18:26:33 +00001491 def test_move_dir_to_dir_other_fs(self):
1492 # Move a dir inside an existing dir on another filesystem.
Nick Coghlan8ed3cf32011-03-16 14:05:35 -04001493 self.test_move_dir_to_dir()
Christian Heimesada8c3b2008-03-18 18:26:33 +00001494
1495 def test_existing_file_inside_dest_dir(self):
1496 # A file with the same name inside the destination dir already exists.
1497 with open(self.dst_file, "wb"):
1498 pass
1499 self.assertRaises(shutil.Error, shutil.move, self.src_file, self.dst_dir)
1500
1501 def test_dont_move_dir_in_itself(self):
1502 # Moving a dir inside itself raises an Error.
1503 dst = os.path.join(self.src_dir, "bar")
1504 self.assertRaises(shutil.Error, shutil.move, self.src_dir, dst)
1505
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +00001506 def test_destinsrc_false_negative(self):
1507 os.mkdir(TESTFN)
1508 try:
1509 for src, dst in [('srcdir', 'srcdir/dest')]:
1510 src = os.path.join(TESTFN, src)
1511 dst = os.path.join(TESTFN, dst)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001512 self.assertTrue(shutil._destinsrc(src, dst),
Benjamin Peterson247a9b82009-02-20 04:09:19 +00001513 msg='_destinsrc() wrongly concluded that '
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +00001514 'dst (%s) is not in src (%s)' % (dst, src))
1515 finally:
1516 shutil.rmtree(TESTFN, ignore_errors=True)
Christian Heimesada8c3b2008-03-18 18:26:33 +00001517
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +00001518 def test_destinsrc_false_positive(self):
1519 os.mkdir(TESTFN)
1520 try:
1521 for src, dst in [('srcdir', 'src/dest'), ('srcdir', 'srcdir.new')]:
1522 src = os.path.join(TESTFN, src)
1523 dst = os.path.join(TESTFN, dst)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001524 self.assertFalse(shutil._destinsrc(src, dst),
Benjamin Peterson247a9b82009-02-20 04:09:19 +00001525 msg='_destinsrc() wrongly concluded that '
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +00001526 'dst (%s) is in src (%s)' % (dst, src))
1527 finally:
1528 shutil.rmtree(TESTFN, ignore_errors=True)
Christian Heimes9bd667a2008-01-20 15:14:11 +00001529
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +01001530 @support.skip_unless_symlink
1531 @mock_rename
1532 def test_move_file_symlink(self):
1533 dst = os.path.join(self.src_dir, 'bar')
1534 os.symlink(self.src_file, dst)
1535 shutil.move(dst, self.dst_file)
1536 self.assertTrue(os.path.islink(self.dst_file))
1537 self.assertTrue(os.path.samefile(self.src_file, self.dst_file))
1538
1539 @support.skip_unless_symlink
1540 @mock_rename
1541 def test_move_file_symlink_to_dir(self):
1542 filename = "bar"
1543 dst = os.path.join(self.src_dir, filename)
1544 os.symlink(self.src_file, dst)
1545 shutil.move(dst, self.dst_dir)
1546 final_link = os.path.join(self.dst_dir, filename)
1547 self.assertTrue(os.path.islink(final_link))
1548 self.assertTrue(os.path.samefile(self.src_file, final_link))
1549
1550 @support.skip_unless_symlink
1551 @mock_rename
1552 def test_move_dangling_symlink(self):
1553 src = os.path.join(self.src_dir, 'baz')
1554 dst = os.path.join(self.src_dir, 'bar')
1555 os.symlink(src, dst)
1556 dst_link = os.path.join(self.dst_dir, 'quux')
1557 shutil.move(dst, dst_link)
1558 self.assertTrue(os.path.islink(dst_link))
Antoine Pitrou3f48ac92014-01-01 02:50:45 +01001559 # On Windows, os.path.realpath does not follow symlinks (issue #9949)
1560 if os.name == 'nt':
1561 self.assertEqual(os.path.realpath(src), os.readlink(dst_link))
1562 else:
1563 self.assertEqual(os.path.realpath(src), os.path.realpath(dst_link))
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +01001564
1565 @support.skip_unless_symlink
1566 @mock_rename
1567 def test_move_dir_symlink(self):
1568 src = os.path.join(self.src_dir, 'baz')
1569 dst = os.path.join(self.src_dir, 'bar')
1570 os.mkdir(src)
1571 os.symlink(src, dst)
1572 dst_link = os.path.join(self.dst_dir, 'quux')
1573 shutil.move(dst, dst_link)
1574 self.assertTrue(os.path.islink(dst_link))
1575 self.assertTrue(os.path.samefile(src, dst_link))
1576
Brian Curtin0d0a1de2012-06-18 18:41:07 -05001577 def test_move_return_value(self):
1578 rv = shutil.move(self.src_file, self.dst_dir)
1579 self.assertEqual(rv,
1580 os.path.join(self.dst_dir, os.path.basename(self.src_file)))
1581
1582 def test_move_as_rename_return_value(self):
1583 rv = shutil.move(self.src_file, os.path.join(self.dst_dir, 'bar'))
1584 self.assertEqual(rv, os.path.join(self.dst_dir, 'bar'))
1585
Tarek Ziadé5340db32010-04-19 22:30:51 +00001586
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001587class TestCopyFile(unittest.TestCase):
1588
1589 _delete = False
1590
1591 class Faux(object):
1592 _entered = False
1593 _exited_with = None
1594 _raised = False
1595 def __init__(self, raise_in_exit=False, suppress_at_exit=True):
1596 self._raise_in_exit = raise_in_exit
1597 self._suppress_at_exit = suppress_at_exit
1598 def read(self, *args):
1599 return ''
1600 def __enter__(self):
1601 self._entered = True
1602 def __exit__(self, exc_type, exc_val, exc_tb):
1603 self._exited_with = exc_type, exc_val, exc_tb
1604 if self._raise_in_exit:
1605 self._raised = True
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001606 raise OSError("Cannot close")
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001607 return self._suppress_at_exit
1608
1609 def tearDown(self):
1610 if self._delete:
1611 del shutil.open
1612
1613 def _set_shutil_open(self, func):
1614 shutil.open = func
1615 self._delete = True
1616
1617 def test_w_source_open_fails(self):
1618 def _open(filename, mode='r'):
1619 if filename == 'srcfile':
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001620 raise OSError('Cannot open "srcfile"')
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001621 assert 0 # shouldn't reach here.
1622
1623 self._set_shutil_open(_open)
1624
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001625 self.assertRaises(OSError, shutil.copyfile, 'srcfile', 'destfile')
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001626
1627 def test_w_dest_open_fails(self):
1628
1629 srcfile = self.Faux()
1630
1631 def _open(filename, mode='r'):
1632 if filename == 'srcfile':
1633 return srcfile
1634 if filename == 'destfile':
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001635 raise OSError('Cannot open "destfile"')
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001636 assert 0 # shouldn't reach here.
1637
1638 self._set_shutil_open(_open)
1639
1640 shutil.copyfile('srcfile', 'destfile')
1641 self.assertTrue(srcfile._entered)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001642 self.assertTrue(srcfile._exited_with[0] is OSError)
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001643 self.assertEqual(srcfile._exited_with[1].args,
1644 ('Cannot open "destfile"',))
1645
1646 def test_w_dest_close_fails(self):
1647
1648 srcfile = self.Faux()
1649 destfile = self.Faux(True)
1650
1651 def _open(filename, mode='r'):
1652 if filename == 'srcfile':
1653 return srcfile
1654 if filename == 'destfile':
1655 return destfile
1656 assert 0 # shouldn't reach here.
1657
1658 self._set_shutil_open(_open)
1659
1660 shutil.copyfile('srcfile', 'destfile')
1661 self.assertTrue(srcfile._entered)
1662 self.assertTrue(destfile._entered)
1663 self.assertTrue(destfile._raised)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001664 self.assertTrue(srcfile._exited_with[0] is OSError)
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001665 self.assertEqual(srcfile._exited_with[1].args,
1666 ('Cannot close',))
1667
1668 def test_w_source_close_fails(self):
1669
1670 srcfile = self.Faux(True)
1671 destfile = self.Faux()
1672
1673 def _open(filename, mode='r'):
1674 if filename == 'srcfile':
1675 return srcfile
1676 if filename == 'destfile':
1677 return destfile
1678 assert 0 # shouldn't reach here.
1679
1680 self._set_shutil_open(_open)
1681
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001682 self.assertRaises(OSError,
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001683 shutil.copyfile, 'srcfile', 'destfile')
1684 self.assertTrue(srcfile._entered)
1685 self.assertTrue(destfile._entered)
1686 self.assertFalse(destfile._raised)
1687 self.assertTrue(srcfile._exited_with[0] is None)
1688 self.assertTrue(srcfile._raised)
1689
Ronald Oussorenf51738b2011-05-06 10:23:04 +02001690 def test_move_dir_caseinsensitive(self):
1691 # Renames a folder to the same name
1692 # but a different case.
1693
1694 self.src_dir = tempfile.mkdtemp()
Larry Hastings5b2f9c02012-06-25 23:50:01 -07001695 self.addCleanup(shutil.rmtree, self.src_dir, True)
Ronald Oussorenf51738b2011-05-06 10:23:04 +02001696 dst_dir = os.path.join(
1697 os.path.dirname(self.src_dir),
1698 os.path.basename(self.src_dir).upper())
1699 self.assertNotEqual(self.src_dir, dst_dir)
1700
1701 try:
1702 shutil.move(self.src_dir, dst_dir)
1703 self.assertTrue(os.path.isdir(dst_dir))
1704 finally:
Éric Araujoa7e33a12011-08-12 19:51:35 +02001705 os.rmdir(dst_dir)
Ronald Oussorenf51738b2011-05-06 10:23:04 +02001706
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001707class TermsizeTests(unittest.TestCase):
1708 def test_does_not_crash(self):
1709 """Check if get_terminal_size() returns a meaningful value.
1710
1711 There's no easy portable way to actually check the size of the
1712 terminal, so let's check if it returns something sensible instead.
1713 """
1714 size = shutil.get_terminal_size()
Antoine Pitroucfade362012-02-08 23:48:59 +01001715 self.assertGreaterEqual(size.columns, 0)
1716 self.assertGreaterEqual(size.lines, 0)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001717
1718 def test_os_environ_first(self):
1719 "Check if environment variables have precedence"
1720
1721 with support.EnvironmentVarGuard() as env:
1722 env['COLUMNS'] = '777'
1723 size = shutil.get_terminal_size()
1724 self.assertEqual(size.columns, 777)
1725
1726 with support.EnvironmentVarGuard() as env:
1727 env['LINES'] = '888'
1728 size = shutil.get_terminal_size()
1729 self.assertEqual(size.lines, 888)
1730
1731 @unittest.skipUnless(os.isatty(sys.__stdout__.fileno()), "not on tty")
1732 def test_stty_match(self):
1733 """Check if stty returns the same results ignoring env
1734
1735 This test will fail if stdin and stdout are connected to
1736 different terminals with different sizes. Nevertheless, such
1737 situations should be pretty rare.
1738 """
1739 try:
1740 size = subprocess.check_output(['stty', 'size']).decode().split()
1741 except (FileNotFoundError, subprocess.CalledProcessError):
1742 self.skipTest("stty invocation failed")
1743 expected = (int(size[1]), int(size[0])) # reversed order
1744
1745 with support.EnvironmentVarGuard() as env:
1746 del env['LINES']
1747 del env['COLUMNS']
1748 actual = shutil.get_terminal_size()
1749
1750 self.assertEqual(expected, actual)
Ronald Oussorenf51738b2011-05-06 10:23:04 +02001751
Tarek Ziadéae4d5c62010-05-05 22:27:31 +00001752
Barry Warsaw7fc2cca2003-01-24 17:34:13 +00001753if __name__ == '__main__':
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04001754 unittest.main()