blob: b34165d1cd2b5aea7af2becf2afda4dff76fa9dd [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
Benjamin Petersonee8712c2008-05-20 21:35:26 +000010from test import support
11from test.support import TESTFN
Tarek Ziadé396fad72010-02-23 05:30:31 +000012from os.path import splitdrive
13from distutils.spawn import find_executable, spawn
14from shutil import (_make_tarball, _make_zipfile, make_archive,
15 register_archive_format, unregister_archive_format,
Tarek Ziadé6ac91722010-04-28 17:51:36 +000016 get_archive_formats, Error, unpack_archive,
17 register_unpack_format, RegistryError,
18 unregister_unpack_format, get_unpack_formats)
Tarek Ziadé396fad72010-02-23 05:30:31 +000019import tarfile
20import warnings
21
22from test import support
23from test.support import TESTFN, check_warnings, captured_stdout
24
Antoine Pitrou7fff0962009-05-01 21:09:44 +000025TESTFN2 = TESTFN + "2"
Barry Warsaw7fc2cca2003-01-24 17:34:13 +000026
Tarek Ziadé396fad72010-02-23 05:30:31 +000027try:
28 import grp
29 import pwd
30 UID_GID_SUPPORT = True
31except ImportError:
32 UID_GID_SUPPORT = False
33
34try:
35 import zlib
36except ImportError:
37 zlib = None
38
39try:
40 import zipfile
41 ZIP_SUPPORT = True
42except ImportError:
43 ZIP_SUPPORT = find_executable('zip')
44
Barry Warsaw7fc2cca2003-01-24 17:34:13 +000045class TestShutil(unittest.TestCase):
Tarek Ziadé396fad72010-02-23 05:30:31 +000046
47 def setUp(self):
48 super(TestShutil, self).setUp()
49 self.tempdirs = []
50
51 def tearDown(self):
52 super(TestShutil, self).tearDown()
53 while self.tempdirs:
54 d = self.tempdirs.pop()
55 shutil.rmtree(d, os.name in ('nt', 'cygwin'))
56
57 def write_file(self, path, content='xxx'):
58 """Writes a file in the given path.
59
60
61 path can be a string or a sequence.
62 """
63 if isinstance(path, (list, tuple)):
64 path = os.path.join(*path)
65 f = open(path, 'w')
66 try:
67 f.write(content)
68 finally:
69 f.close()
70
71 def mkdtemp(self):
72 """Create a temporary directory that will be cleaned up.
73
74 Returns the path of the directory.
75 """
76 d = tempfile.mkdtemp()
77 self.tempdirs.append(d)
78 return d
Tarek Ziadé5340db32010-04-19 22:30:51 +000079
Barry Warsaw7fc2cca2003-01-24 17:34:13 +000080 def test_rmtree_errors(self):
81 # filename is guaranteed not to exist
82 filename = tempfile.mktemp()
83 self.assertRaises(OSError, shutil.rmtree, filename)
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +000084
Johannes Gijsbersb8b09d02004-12-06 20:50:15 +000085 # See bug #1071513 for why we don't run this on cygwin
86 # and bug #1076467 for why we don't run this as root.
87 if (hasattr(os, 'chmod') and sys.platform[:6] != 'cygwin'
Johannes Gijsbers6b220b02004-12-12 15:52:57 +000088 and not (hasattr(os, 'geteuid') and os.geteuid() == 0)):
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +000089 def test_on_error(self):
90 self.errorState = 0
91 os.mkdir(TESTFN)
Tim Peters4590c002004-11-01 02:40:52 +000092 self.childpath = os.path.join(TESTFN, 'a')
93 f = open(self.childpath, 'w')
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +000094 f.close()
Tim Peters4590c002004-11-01 02:40:52 +000095 old_dir_mode = os.stat(TESTFN).st_mode
96 old_child_mode = os.stat(self.childpath).st_mode
97 # Make unwritable.
98 os.chmod(self.childpath, stat.S_IREAD)
99 os.chmod(TESTFN, stat.S_IREAD)
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000100
101 shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror)
Johannes Gijsbers8e6f2de2004-11-23 09:27:27 +0000102 # Test whether onerror has actually been called.
Johannes Gijsbersb8b09d02004-12-06 20:50:15 +0000103 self.assertEqual(self.errorState, 2,
104 "Expected call to onerror function did not happen.")
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000105
Tim Peters4590c002004-11-01 02:40:52 +0000106 # Make writable again.
107 os.chmod(TESTFN, old_dir_mode)
108 os.chmod(self.childpath, old_child_mode)
109
110 # Clean up.
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000111 shutil.rmtree(TESTFN)
112
113 def check_args_to_onerror(self, func, arg, exc):
Benjamin Peterson25c95f12009-05-08 20:42:26 +0000114 # test_rmtree_errors deliberately runs rmtree
115 # on a directory that is chmod 400, which will fail.
116 # This function is run when shutil.rmtree fails.
117 # 99.9% of the time it initially fails to remove
118 # a file in the directory, so the first time through
119 # func is os.remove.
120 # However, some Linux machines running ZFS on
121 # FUSE experienced a failure earlier in the process
122 # at os.listdir. The first failure may legally
123 # be either.
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000124 if self.errorState == 0:
Benjamin Peterson25c95f12009-05-08 20:42:26 +0000125 if func is os.remove:
126 self.assertEqual(arg, self.childpath)
127 else:
128 self.assertIs(func, os.listdir,
129 "func must be either os.remove or os.listdir")
130 self.assertEqual(arg, TESTFN)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000131 self.assertTrue(issubclass(exc[0], OSError))
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000132 self.errorState = 1
133 else:
134 self.assertEqual(func, os.rmdir)
135 self.assertEqual(arg, TESTFN)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000136 self.assertTrue(issubclass(exc[0], OSError))
Johannes Gijsbers8e6f2de2004-11-23 09:27:27 +0000137 self.errorState = 2
Barry Warsaw7fc2cca2003-01-24 17:34:13 +0000138
Johannes Gijsbersd60e92a2004-09-11 21:26:21 +0000139 def test_rmtree_dont_delete_file(self):
140 # When called on a file instead of a directory, don't delete it.
141 handle, path = tempfile.mkstemp()
142 os.fdopen(handle).close()
143 self.assertRaises(OSError, shutil.rmtree, path)
144 os.remove(path)
145
Tarek Ziadé5340db32010-04-19 22:30:51 +0000146 def _write_data(self, path, data):
147 f = open(path, "w")
148 f.write(data)
149 f.close()
150
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000151 def test_copytree_simple(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000152
153 def read_data(path):
154 f = open(path)
155 data = f.read()
156 f.close()
157 return data
158
159 src_dir = tempfile.mkdtemp()
160 dst_dir = os.path.join(tempfile.mkdtemp(), 'destination')
Tarek Ziadé5340db32010-04-19 22:30:51 +0000161 self._write_data(os.path.join(src_dir, 'test.txt'), '123')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000162 os.mkdir(os.path.join(src_dir, 'test_dir'))
Tarek Ziadé5340db32010-04-19 22:30:51 +0000163 self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000164
165 try:
166 shutil.copytree(src_dir, dst_dir)
167 self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test.txt')))
168 self.assertTrue(os.path.isdir(os.path.join(dst_dir, 'test_dir')))
169 self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test_dir',
170 'test.txt')))
171 actual = read_data(os.path.join(dst_dir, 'test.txt'))
172 self.assertEqual(actual, '123')
173 actual = read_data(os.path.join(dst_dir, 'test_dir', 'test.txt'))
174 self.assertEqual(actual, '456')
175 finally:
176 for path in (
177 os.path.join(src_dir, 'test.txt'),
178 os.path.join(dst_dir, 'test.txt'),
179 os.path.join(src_dir, 'test_dir', 'test.txt'),
180 os.path.join(dst_dir, 'test_dir', 'test.txt'),
181 ):
182 if os.path.exists(path):
183 os.remove(path)
Christian Heimese052dd82007-11-20 03:20:04 +0000184 for path in (src_dir,
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000185 os.path.dirname(dst_dir)
Christian Heimese052dd82007-11-20 03:20:04 +0000186 ):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000187 if os.path.exists(path):
Christian Heimes94140152007-11-20 01:45:17 +0000188 shutil.rmtree(path)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000189
Georg Brandl2ee470f2008-07-16 12:55:28 +0000190 def test_copytree_with_exclude(self):
191
Georg Brandl2ee470f2008-07-16 12:55:28 +0000192 def read_data(path):
193 f = open(path)
194 data = f.read()
195 f.close()
196 return data
197
198 # creating data
199 join = os.path.join
200 exists = os.path.exists
201 src_dir = tempfile.mkdtemp()
Georg Brandl2ee470f2008-07-16 12:55:28 +0000202 try:
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000203 dst_dir = join(tempfile.mkdtemp(), 'destination')
Tarek Ziadé5340db32010-04-19 22:30:51 +0000204 self._write_data(join(src_dir, 'test.txt'), '123')
205 self._write_data(join(src_dir, 'test.tmp'), '123')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000206 os.mkdir(join(src_dir, 'test_dir'))
Tarek Ziadé5340db32010-04-19 22:30:51 +0000207 self._write_data(join(src_dir, 'test_dir', 'test.txt'), '456')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000208 os.mkdir(join(src_dir, 'test_dir2'))
Tarek Ziadé5340db32010-04-19 22:30:51 +0000209 self._write_data(join(src_dir, 'test_dir2', 'test.txt'), '456')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000210 os.mkdir(join(src_dir, 'test_dir2', 'subdir'))
211 os.mkdir(join(src_dir, 'test_dir2', 'subdir2'))
Tarek Ziadé5340db32010-04-19 22:30:51 +0000212 self._write_data(join(src_dir, 'test_dir2', 'subdir', 'test.txt'),
213 '456')
214 self._write_data(join(src_dir, 'test_dir2', 'subdir2', 'test.py'),
215 '456')
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000216
217
218 # testing glob-like patterns
219 try:
220 patterns = shutil.ignore_patterns('*.tmp', 'test_dir2')
221 shutil.copytree(src_dir, dst_dir, ignore=patterns)
222 # checking the result: some elements should not be copied
223 self.assertTrue(exists(join(dst_dir, 'test.txt')))
224 self.assertTrue(not exists(join(dst_dir, 'test.tmp')))
225 self.assertTrue(not exists(join(dst_dir, 'test_dir2')))
226 finally:
227 if os.path.exists(dst_dir):
228 shutil.rmtree(dst_dir)
229 try:
230 patterns = shutil.ignore_patterns('*.tmp', 'subdir*')
231 shutil.copytree(src_dir, dst_dir, ignore=patterns)
232 # checking the result: some elements should not be copied
233 self.assertTrue(not exists(join(dst_dir, 'test.tmp')))
234 self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir2')))
235 self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir')))
236 finally:
237 if os.path.exists(dst_dir):
238 shutil.rmtree(dst_dir)
239
240 # testing callable-style
241 try:
242 def _filter(src, names):
243 res = []
244 for name in names:
245 path = os.path.join(src, name)
246
247 if (os.path.isdir(path) and
248 path.split()[-1] == 'subdir'):
249 res.append(name)
250 elif os.path.splitext(path)[-1] in ('.py'):
251 res.append(name)
252 return res
253
254 shutil.copytree(src_dir, dst_dir, ignore=_filter)
255
256 # checking the result: some elements should not be copied
257 self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir2',
258 'test.py')))
259 self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir')))
260
261 finally:
262 if os.path.exists(dst_dir):
263 shutil.rmtree(dst_dir)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000264 finally:
Antoine Pitrou97c81ef2009-11-04 00:57:15 +0000265 shutil.rmtree(src_dir)
266 shutil.rmtree(os.path.dirname(dst_dir))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000267
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000268 @unittest.skipUnless(hasattr(os, 'symlink'), 'requires os.symlink')
269 def test_dont_copy_file_onto_link_to_itself(self):
270 # bug 851123.
271 os.mkdir(TESTFN)
272 src = os.path.join(TESTFN, 'cheese')
273 dst = os.path.join(TESTFN, 'shop')
274 try:
275 f = open(src, 'w')
276 f.write('cheddar')
277 f.close()
278
279 os.link(src, dst)
280 self.assertRaises(shutil.Error, shutil.copyfile, src, dst)
281 self.assertEqual(open(src,'r').read(), 'cheddar')
282 os.remove(dst)
283
284 # Using `src` here would mean we end up with a symlink pointing
285 # to TESTFN/TESTFN/cheese, while it should point at
286 # TESTFN/cheese.
287 os.symlink('cheese', dst)
288 self.assertRaises(shutil.Error, shutil.copyfile, src, dst)
289 self.assertEqual(open(src,'r').read(), 'cheddar')
290 os.remove(dst)
291 finally:
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000292 try:
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000293 shutil.rmtree(TESTFN)
294 except OSError:
295 pass
Johannes Gijsbers68128712004-08-14 13:57:08 +0000296
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000297 @unittest.skipUnless(hasattr(os, 'symlink'), 'requires os.symlink')
Christian Heimes9bd667a2008-01-20 15:14:11 +0000298 def test_rmtree_on_symlink(self):
299 # bug 1669.
300 os.mkdir(TESTFN)
301 try:
302 src = os.path.join(TESTFN, 'cheese')
303 dst = os.path.join(TESTFN, 'shop')
304 os.mkdir(src)
305 os.symlink(src, dst)
306 self.assertRaises(OSError, shutil.rmtree, dst)
307 finally:
308 shutil.rmtree(TESTFN, ignore_errors=True)
309
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000310 @unittest.skipUnless(hasattr(os, 'mkfifo'), 'requires os.mkfifo')
311 # Issue #3002: copyfile and copytree block indefinitely on named pipes
312 def test_copyfile_named_pipe(self):
313 os.mkfifo(TESTFN)
314 try:
315 self.assertRaises(shutil.SpecialFileError,
316 shutil.copyfile, TESTFN, TESTFN2)
317 self.assertRaises(shutil.SpecialFileError,
318 shutil.copyfile, __file__, TESTFN)
319 finally:
320 os.remove(TESTFN)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000321
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000322 @unittest.skipUnless(hasattr(os, 'mkfifo'), 'requires os.mkfifo')
323 def test_copytree_named_pipe(self):
324 os.mkdir(TESTFN)
325 try:
326 subdir = os.path.join(TESTFN, "subdir")
327 os.mkdir(subdir)
328 pipe = os.path.join(subdir, "mypipe")
329 os.mkfifo(pipe)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000330 try:
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000331 shutil.copytree(TESTFN, TESTFN2)
332 except shutil.Error as e:
333 errors = e.args[0]
334 self.assertEqual(len(errors), 1)
335 src, dst, error_msg = errors[0]
336 self.assertEqual("`%s` is a named pipe" % pipe, error_msg)
337 else:
338 self.fail("shutil.Error should have been raised")
339 finally:
340 shutil.rmtree(TESTFN, ignore_errors=True)
341 shutil.rmtree(TESTFN2, ignore_errors=True)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000342
Tarek Ziadé5340db32010-04-19 22:30:51 +0000343 def test_copytree_special_func(self):
344
345 src_dir = self.mkdtemp()
346 dst_dir = os.path.join(self.mkdtemp(), 'destination')
347 self._write_data(os.path.join(src_dir, 'test.txt'), '123')
348 os.mkdir(os.path.join(src_dir, 'test_dir'))
349 self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
350
351 copied = []
352 def _copy(src, dst):
353 copied.append((src, dst))
354
355 shutil.copytree(src_dir, dst_dir, copy_function=_copy)
356 self.assertEquals(len(copied), 2)
357
Tarek Ziadé51a6f722010-04-23 13:03:09 +0000358 @unittest.skipUnless(hasattr(os, 'symlink'), 'requires os.symlink')
Tarek Ziadéfb437512010-04-20 08:57:33 +0000359 def test_copytree_dangling_symlinks(self):
360
361 # a dangling symlink raises an error at the end
362 src_dir = self.mkdtemp()
363 dst_dir = os.path.join(self.mkdtemp(), 'destination')
364 os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))
365 os.mkdir(os.path.join(src_dir, 'test_dir'))
366 self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
367 self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
368
369 # a dangling symlink is ignored with the proper flag
370 dst_dir = os.path.join(self.mkdtemp(), 'destination2')
371 shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
372 self.assertNotIn('test.txt', os.listdir(dst_dir))
373
374 # a dangling symlink is copied if symlinks=True
375 dst_dir = os.path.join(self.mkdtemp(), 'destination3')
376 shutil.copytree(src_dir, dst_dir, symlinks=True)
377 self.assertIn('test.txt', os.listdir(dst_dir))
378
Tarek Ziadé396fad72010-02-23 05:30:31 +0000379 @unittest.skipUnless(zlib, "requires zlib")
380 def test_make_tarball(self):
381 # creating something to tar
382 tmpdir = self.mkdtemp()
383 self.write_file([tmpdir, 'file1'], 'xxx')
384 self.write_file([tmpdir, 'file2'], 'xxx')
385 os.mkdir(os.path.join(tmpdir, 'sub'))
386 self.write_file([tmpdir, 'sub', 'file3'], 'xxx')
387
388 tmpdir2 = self.mkdtemp()
389 unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
390 "source and target should be on same drive")
391
392 base_name = os.path.join(tmpdir2, 'archive')
393
394 # working with relative paths to avoid tar warnings
395 old_dir = os.getcwd()
396 os.chdir(tmpdir)
397 try:
398 _make_tarball(splitdrive(base_name)[1], '.')
399 finally:
400 os.chdir(old_dir)
401
402 # check if the compressed tarball was created
403 tarball = base_name + '.tar.gz'
404 self.assertTrue(os.path.exists(tarball))
405
406 # trying an uncompressed one
407 base_name = os.path.join(tmpdir2, 'archive')
408 old_dir = os.getcwd()
409 os.chdir(tmpdir)
410 try:
411 _make_tarball(splitdrive(base_name)[1], '.', compress=None)
412 finally:
413 os.chdir(old_dir)
414 tarball = base_name + '.tar'
415 self.assertTrue(os.path.exists(tarball))
416
417 def _tarinfo(self, path):
418 tar = tarfile.open(path)
419 try:
420 names = tar.getnames()
421 names.sort()
422 return tuple(names)
423 finally:
424 tar.close()
425
426 def _create_files(self):
427 # creating something to tar
428 tmpdir = self.mkdtemp()
429 dist = os.path.join(tmpdir, 'dist')
430 os.mkdir(dist)
431 self.write_file([dist, 'file1'], 'xxx')
432 self.write_file([dist, 'file2'], 'xxx')
433 os.mkdir(os.path.join(dist, 'sub'))
434 self.write_file([dist, 'sub', 'file3'], 'xxx')
435 os.mkdir(os.path.join(dist, 'sub2'))
436 tmpdir2 = self.mkdtemp()
437 base_name = os.path.join(tmpdir2, 'archive')
438 return tmpdir, tmpdir2, base_name
439
440 @unittest.skipUnless(zlib, "Requires zlib")
441 @unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
442 'Need the tar command to run')
443 def test_tarfile_vs_tar(self):
444 tmpdir, tmpdir2, base_name = self._create_files()
445 old_dir = os.getcwd()
446 os.chdir(tmpdir)
447 try:
448 _make_tarball(base_name, 'dist')
449 finally:
450 os.chdir(old_dir)
451
452 # check if the compressed tarball was created
453 tarball = base_name + '.tar.gz'
454 self.assertTrue(os.path.exists(tarball))
455
456 # now create another tarball using `tar`
457 tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
458 tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist']
459 gzip_cmd = ['gzip', '-f9', 'archive2.tar']
460 old_dir = os.getcwd()
461 os.chdir(tmpdir)
462 try:
463 with captured_stdout() as s:
464 spawn(tar_cmd)
465 spawn(gzip_cmd)
466 finally:
467 os.chdir(old_dir)
468
469 self.assertTrue(os.path.exists(tarball2))
470 # let's compare both tarballs
471 self.assertEquals(self._tarinfo(tarball), self._tarinfo(tarball2))
472
473 # trying an uncompressed one
474 base_name = os.path.join(tmpdir2, 'archive')
475 old_dir = os.getcwd()
476 os.chdir(tmpdir)
477 try:
478 _make_tarball(base_name, 'dist', compress=None)
479 finally:
480 os.chdir(old_dir)
481 tarball = base_name + '.tar'
482 self.assertTrue(os.path.exists(tarball))
483
484 # now for a dry_run
485 base_name = os.path.join(tmpdir2, 'archive')
486 old_dir = os.getcwd()
487 os.chdir(tmpdir)
488 try:
489 _make_tarball(base_name, 'dist', compress=None, dry_run=True)
490 finally:
491 os.chdir(old_dir)
492 tarball = base_name + '.tar'
493 self.assertTrue(os.path.exists(tarball))
494
Tarek Ziadé396fad72010-02-23 05:30:31 +0000495 @unittest.skipUnless(zlib, "Requires zlib")
496 @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
497 def test_make_zipfile(self):
498 # creating something to tar
499 tmpdir = self.mkdtemp()
500 self.write_file([tmpdir, 'file1'], 'xxx')
501 self.write_file([tmpdir, 'file2'], 'xxx')
502
503 tmpdir2 = self.mkdtemp()
504 base_name = os.path.join(tmpdir2, 'archive')
505 _make_zipfile(base_name, tmpdir)
506
507 # check if the compressed tarball was created
508 tarball = base_name + '.zip'
509
510
511 def test_make_archive(self):
512 tmpdir = self.mkdtemp()
513 base_name = os.path.join(tmpdir, 'archive')
514 self.assertRaises(ValueError, make_archive, base_name, 'xxx')
515
516 @unittest.skipUnless(zlib, "Requires zlib")
517 def test_make_archive_owner_group(self):
518 # testing make_archive with owner and group, with various combinations
519 # this works even if there's not gid/uid support
520 if UID_GID_SUPPORT:
521 group = grp.getgrgid(0)[0]
522 owner = pwd.getpwuid(0)[0]
523 else:
524 group = owner = 'root'
525
526 base_dir, root_dir, base_name = self._create_files()
527 base_name = os.path.join(self.mkdtemp() , 'archive')
528 res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner,
529 group=group)
530 self.assertTrue(os.path.exists(res))
531
532 res = make_archive(base_name, 'zip', root_dir, base_dir)
533 self.assertTrue(os.path.exists(res))
534
535 res = make_archive(base_name, 'tar', root_dir, base_dir,
536 owner=owner, group=group)
537 self.assertTrue(os.path.exists(res))
538
539 res = make_archive(base_name, 'tar', root_dir, base_dir,
540 owner='kjhkjhkjg', group='oihohoh')
541 self.assertTrue(os.path.exists(res))
542
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000543
Tarek Ziadé396fad72010-02-23 05:30:31 +0000544 @unittest.skipUnless(zlib, "Requires zlib")
545 @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
546 def test_tarfile_root_owner(self):
547 tmpdir, tmpdir2, base_name = self._create_files()
548 old_dir = os.getcwd()
549 os.chdir(tmpdir)
550 group = grp.getgrgid(0)[0]
551 owner = pwd.getpwuid(0)[0]
552 try:
553 archive_name = _make_tarball(base_name, 'dist', compress=None,
554 owner=owner, group=group)
555 finally:
556 os.chdir(old_dir)
557
558 # check if the compressed tarball was created
559 self.assertTrue(os.path.exists(archive_name))
560
561 # now checks the rights
562 archive = tarfile.open(archive_name)
563 try:
564 for member in archive.getmembers():
565 self.assertEquals(member.uid, 0)
566 self.assertEquals(member.gid, 0)
567 finally:
568 archive.close()
569
570 def test_make_archive_cwd(self):
571 current_dir = os.getcwd()
572 def _breaks(*args, **kw):
573 raise RuntimeError()
574
575 register_archive_format('xxx', _breaks, [], 'xxx file')
576 try:
577 try:
578 make_archive('xxx', 'xxx', root_dir=self.mkdtemp())
579 except Exception:
580 pass
581 self.assertEquals(os.getcwd(), current_dir)
582 finally:
583 unregister_archive_format('xxx')
584
585 def test_register_archive_format(self):
586
587 self.assertRaises(TypeError, register_archive_format, 'xxx', 1)
588 self.assertRaises(TypeError, register_archive_format, 'xxx', lambda: x,
589 1)
590 self.assertRaises(TypeError, register_archive_format, 'xxx', lambda: x,
591 [(1, 2), (1, 2, 3)])
592
593 register_archive_format('xxx', lambda: x, [(1, 2)], 'xxx file')
594 formats = [name for name, params in get_archive_formats()]
595 self.assertIn('xxx', formats)
596
597 unregister_archive_format('xxx')
598 formats = [name for name, params in get_archive_formats()]
599 self.assertNotIn('xxx', formats)
600
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000601 def _compare_dirs(self, dir1, dir2):
602 # check that dir1 and dir2 are equivalent,
603 # return the diff
604 diff = []
605 for root, dirs, files in os.walk(dir1):
606 for file_ in files:
607 path = os.path.join(root, file_)
608 target_path = os.path.join(dir2, os.path.split(path)[-1])
609 if not os.path.exists(target_path):
610 diff.append(file_)
611 return diff
612
613 @unittest.skipUnless(zlib, "Requires zlib")
614 def test_unpack_archive(self):
615
616 for format in ('tar', 'gztar', 'bztar', 'zip'):
617 tmpdir = self.mkdtemp()
618 base_dir, root_dir, base_name = self._create_files()
619 tmpdir2 = self.mkdtemp()
620 filename = make_archive(base_name, format, root_dir, base_dir)
621
622 # let's try to unpack it now
623 unpack_archive(filename, tmpdir2)
624 diff = self._compare_dirs(tmpdir, tmpdir2)
625 self.assertEquals(diff, [])
626
627 def test_unpack_registery(self):
628
629 formats = get_unpack_formats()
630
631 def _boo(filename, extract_dir, extra):
632 self.assertEquals(extra, 1)
633 self.assertEquals(filename, 'stuff.boo')
634 self.assertEquals(extract_dir, 'xx')
635
636 register_unpack_format('Boo', ['.boo', '.b2'], _boo, [('extra', 1)])
637 unpack_archive('stuff.boo', 'xx')
638
639 # trying to register a .boo unpacker again
640 self.assertRaises(RegistryError, register_unpack_format, 'Boo2',
641 ['.boo'], _boo)
642
643 # should work now
644 unregister_unpack_format('Boo')
645 register_unpack_format('Boo2', ['.boo'], _boo)
646 self.assertIn(('Boo2', ['.boo'], ''), get_unpack_formats())
647 self.assertNotIn(('Boo', ['.boo'], ''), get_unpack_formats())
648
649 # let's leave a clean state
650 unregister_unpack_format('Boo2')
651 self.assertEquals(get_unpack_formats(), formats)
652
Christian Heimes9bd667a2008-01-20 15:14:11 +0000653
Christian Heimesada8c3b2008-03-18 18:26:33 +0000654class TestMove(unittest.TestCase):
655
656 def setUp(self):
657 filename = "foo"
658 self.src_dir = tempfile.mkdtemp()
659 self.dst_dir = tempfile.mkdtemp()
660 self.src_file = os.path.join(self.src_dir, filename)
661 self.dst_file = os.path.join(self.dst_dir, filename)
662 # Try to create a dir in the current directory, hoping that it is
663 # not located on the same filesystem as the system tmp dir.
664 try:
665 self.dir_other_fs = tempfile.mkdtemp(
666 dir=os.path.dirname(__file__))
667 self.file_other_fs = os.path.join(self.dir_other_fs,
668 filename)
669 except OSError:
670 self.dir_other_fs = None
671 with open(self.src_file, "wb") as f:
672 f.write(b"spam")
673
674 def tearDown(self):
675 for d in (self.src_dir, self.dst_dir, self.dir_other_fs):
676 try:
677 if d:
678 shutil.rmtree(d)
679 except:
680 pass
681
682 def _check_move_file(self, src, dst, real_dst):
683 contents = open(src, "rb").read()
684 shutil.move(src, dst)
685 self.assertEqual(contents, open(real_dst, "rb").read())
686 self.assertFalse(os.path.exists(src))
687
688 def _check_move_dir(self, src, dst, real_dst):
689 contents = sorted(os.listdir(src))
690 shutil.move(src, dst)
691 self.assertEqual(contents, sorted(os.listdir(real_dst)))
692 self.assertFalse(os.path.exists(src))
693
694 def test_move_file(self):
695 # Move a file to another location on the same filesystem.
696 self._check_move_file(self.src_file, self.dst_file, self.dst_file)
697
698 def test_move_file_to_dir(self):
699 # Move a file inside an existing dir on the same filesystem.
700 self._check_move_file(self.src_file, self.dst_dir, self.dst_file)
701
702 def test_move_file_other_fs(self):
703 # Move a file to an existing dir on another filesystem.
704 if not self.dir_other_fs:
705 # skip
706 return
707 self._check_move_file(self.src_file, self.file_other_fs,
708 self.file_other_fs)
709
710 def test_move_file_to_dir_other_fs(self):
711 # Move a file to another location on another filesystem.
712 if not self.dir_other_fs:
713 # skip
714 return
715 self._check_move_file(self.src_file, self.dir_other_fs,
716 self.file_other_fs)
717
718 def test_move_dir(self):
719 # Move a dir to another location on the same filesystem.
720 dst_dir = tempfile.mktemp()
721 try:
722 self._check_move_dir(self.src_dir, dst_dir, dst_dir)
723 finally:
724 try:
725 shutil.rmtree(dst_dir)
726 except:
727 pass
728
729 def test_move_dir_other_fs(self):
730 # Move a dir to another location on another filesystem.
731 if not self.dir_other_fs:
732 # skip
733 return
734 dst_dir = tempfile.mktemp(dir=self.dir_other_fs)
735 try:
736 self._check_move_dir(self.src_dir, dst_dir, dst_dir)
737 finally:
738 try:
739 shutil.rmtree(dst_dir)
740 except:
741 pass
742
743 def test_move_dir_to_dir(self):
744 # Move a dir inside an existing dir on the same filesystem.
745 self._check_move_dir(self.src_dir, self.dst_dir,
746 os.path.join(self.dst_dir, os.path.basename(self.src_dir)))
747
748 def test_move_dir_to_dir_other_fs(self):
749 # Move a dir inside an existing dir on another filesystem.
750 if not self.dir_other_fs:
751 # skip
752 return
753 self._check_move_dir(self.src_dir, self.dir_other_fs,
754 os.path.join(self.dir_other_fs, os.path.basename(self.src_dir)))
755
756 def test_existing_file_inside_dest_dir(self):
757 # A file with the same name inside the destination dir already exists.
758 with open(self.dst_file, "wb"):
759 pass
760 self.assertRaises(shutil.Error, shutil.move, self.src_file, self.dst_dir)
761
762 def test_dont_move_dir_in_itself(self):
763 # Moving a dir inside itself raises an Error.
764 dst = os.path.join(self.src_dir, "bar")
765 self.assertRaises(shutil.Error, shutil.move, self.src_dir, dst)
766
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000767 def test_destinsrc_false_negative(self):
768 os.mkdir(TESTFN)
769 try:
770 for src, dst in [('srcdir', 'srcdir/dest')]:
771 src = os.path.join(TESTFN, src)
772 dst = os.path.join(TESTFN, dst)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000773 self.assertTrue(shutil._destinsrc(src, dst),
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000774 msg='_destinsrc() wrongly concluded that '
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000775 'dst (%s) is not in src (%s)' % (dst, src))
776 finally:
777 shutil.rmtree(TESTFN, ignore_errors=True)
Christian Heimesada8c3b2008-03-18 18:26:33 +0000778
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000779 def test_destinsrc_false_positive(self):
780 os.mkdir(TESTFN)
781 try:
782 for src, dst in [('srcdir', 'src/dest'), ('srcdir', 'srcdir.new')]:
783 src = os.path.join(TESTFN, src)
784 dst = os.path.join(TESTFN, dst)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000785 self.assertFalse(shutil._destinsrc(src, dst),
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000786 msg='_destinsrc() wrongly concluded that '
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000787 'dst (%s) is in src (%s)' % (dst, src))
788 finally:
789 shutil.rmtree(TESTFN, ignore_errors=True)
Christian Heimes9bd667a2008-01-20 15:14:11 +0000790
Tarek Ziadé5340db32010-04-19 22:30:51 +0000791
Barry Warsaw7fc2cca2003-01-24 17:34:13 +0000792def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000793 support.run_unittest(TestShutil, TestMove)
Barry Warsaw7fc2cca2003-01-24 17:34:13 +0000794
Barry Warsaw7fc2cca2003-01-24 17:34:13 +0000795if __name__ == '__main__':
Walter Dörwald21d3a322003-05-01 17:45:56 +0000796 test_main()