1 # Copyright (C) 2003 Python Software Foundation
10 from test
import test_support
11 from test
.test_support
import TESTFN
12 TESTFN2
= TESTFN
+ "2"
14 class TestShutil(unittest
.TestCase
):
15 def test_rmtree_errors(self
):
16 # filename is guaranteed not to exist
17 filename
= tempfile
.mktemp()
18 self
.assertRaises(OSError, shutil
.rmtree
, filename
)
20 # See bug #1071513 for why we don't run this on cygwin
21 # and bug #1076467 for why we don't run this as root.
22 if (hasattr(os
, 'chmod') and sys
.platform
[:6] != 'cygwin'
23 and not (hasattr(os
, 'geteuid') and os
.geteuid() == 0)):
24 def test_on_error(self
):
27 self
.childpath
= os
.path
.join(TESTFN
, 'a')
28 f
= open(self
.childpath
, 'w')
30 old_dir_mode
= os
.stat(TESTFN
).st_mode
31 old_child_mode
= os
.stat(self
.childpath
).st_mode
33 os
.chmod(self
.childpath
, stat
.S_IREAD
)
34 os
.chmod(TESTFN
, stat
.S_IREAD
)
36 shutil
.rmtree(TESTFN
, onerror
=self
.check_args_to_onerror
)
37 # Test whether onerror has actually been called.
38 self
.assertEqual(self
.errorState
, 2,
39 "Expected call to onerror function did not happen.")
41 # Make writable again.
42 os
.chmod(TESTFN
, old_dir_mode
)
43 os
.chmod(self
.childpath
, old_child_mode
)
48 def check_args_to_onerror(self
, func
, arg
, exc
):
49 # test_rmtree_errors deliberately runs rmtree
50 # on a directory that is chmod 400, which will fail.
51 # This function is run when shutil.rmtree fails.
52 # 99.9% of the time it initially fails to remove
53 # a file in the directory, so the first time through
55 # However, some Linux machines running ZFS on
56 # FUSE experienced a failure earlier in the process
57 # at os.listdir. The first failure may legally
59 if self
.errorState
== 0:
61 self
.assertEqual(arg
, self
.childpath
)
63 self
.assertIs(func
, os
.listdir
,
64 "func must be either os.remove or os.listdir")
65 self
.assertEqual(arg
, TESTFN
)
66 self
.failUnless(issubclass(exc
[0], OSError))
69 self
.assertEqual(func
, os
.rmdir
)
70 self
.assertEqual(arg
, TESTFN
)
71 self
.failUnless(issubclass(exc
[0], OSError))
74 def test_rmtree_dont_delete_file(self
):
75 # When called on a file instead of a directory, don't delete it.
76 handle
, path
= tempfile
.mkstemp()
77 os
.fdopen(handle
).close()
78 self
.assertRaises(OSError, shutil
.rmtree
, path
)
81 def test_copytree_simple(self
):
82 def write_data(path
, data
):
93 src_dir
= tempfile
.mkdtemp()
94 dst_dir
= os
.path
.join(tempfile
.mkdtemp(), 'destination')
96 write_data(os
.path
.join(src_dir
, 'test.txt'), '123')
98 os
.mkdir(os
.path
.join(src_dir
, 'test_dir'))
99 write_data(os
.path
.join(src_dir
, 'test_dir', 'test.txt'), '456')
102 shutil
.copytree(src_dir
, dst_dir
)
103 self
.assertTrue(os
.path
.isfile(os
.path
.join(dst_dir
, 'test.txt')))
104 self
.assertTrue(os
.path
.isdir(os
.path
.join(dst_dir
, 'test_dir')))
105 self
.assertTrue(os
.path
.isfile(os
.path
.join(dst_dir
, 'test_dir',
107 actual
= read_data(os
.path
.join(dst_dir
, 'test.txt'))
108 self
.assertEqual(actual
, '123')
109 actual
= read_data(os
.path
.join(dst_dir
, 'test_dir', 'test.txt'))
110 self
.assertEqual(actual
, '456')
113 os
.path
.join(src_dir
, 'test.txt'),
114 os
.path
.join(dst_dir
, 'test.txt'),
115 os
.path
.join(src_dir
, 'test_dir', 'test.txt'),
116 os
.path
.join(dst_dir
, 'test_dir', 'test.txt'),
118 if os
.path
.exists(path
):
120 for path
in (src_dir
,
121 os
.path
.abspath(os
.path
.join(dst_dir
, os
.path
.pardir
))
123 if os
.path
.exists(path
):
126 def test_copytree_with_exclude(self
):
128 def write_data(path
, data
):
141 exists
= os
.path
.exists
142 src_dir
= tempfile
.mkdtemp()
143 dst_dir
= join(tempfile
.mkdtemp(), 'destination')
144 write_data(join(src_dir
, 'test.txt'), '123')
145 write_data(join(src_dir
, 'test.tmp'), '123')
146 os
.mkdir(join(src_dir
, 'test_dir'))
147 write_data(join(src_dir
, 'test_dir', 'test.txt'), '456')
148 os
.mkdir(join(src_dir
, 'test_dir2'))
149 write_data(join(src_dir
, 'test_dir2', 'test.txt'), '456')
150 os
.mkdir(join(src_dir
, 'test_dir2', 'subdir'))
151 os
.mkdir(join(src_dir
, 'test_dir2', 'subdir2'))
152 write_data(join(src_dir
, 'test_dir2', 'subdir', 'test.txt'), '456')
153 write_data(join(src_dir
, 'test_dir2', 'subdir2', 'test.py'), '456')
156 # testing glob-like patterns
158 patterns
= shutil
.ignore_patterns('*.tmp', 'test_dir2')
159 shutil
.copytree(src_dir
, dst_dir
, ignore
=patterns
)
160 # checking the result: some elements should not be copied
161 self
.assert_(exists(join(dst_dir
, 'test.txt')))
162 self
.assert_(not exists(join(dst_dir
, 'test.tmp')))
163 self
.assert_(not exists(join(dst_dir
, 'test_dir2')))
165 if os
.path
.exists(dst_dir
):
166 shutil
.rmtree(dst_dir
)
168 patterns
= shutil
.ignore_patterns('*.tmp', 'subdir*')
169 shutil
.copytree(src_dir
, dst_dir
, ignore
=patterns
)
170 # checking the result: some elements should not be copied
171 self
.assert_(not exists(join(dst_dir
, 'test.tmp')))
172 self
.assert_(not exists(join(dst_dir
, 'test_dir2', 'subdir2')))
173 self
.assert_(not exists(join(dst_dir
, 'test_dir2', 'subdir')))
175 if os
.path
.exists(dst_dir
):
176 shutil
.rmtree(dst_dir
)
178 # testing callable-style
180 def _filter(src
, names
):
183 path
= os
.path
.join(src
, name
)
185 if (os
.path
.isdir(path
) and
186 path
.split()[-1] == 'subdir'):
188 elif os
.path
.splitext(path
)[-1] in ('.py'):
192 shutil
.copytree(src_dir
, dst_dir
, ignore
=_filter
)
194 # checking the result: some elements should not be copied
195 self
.assert_(not exists(join(dst_dir
, 'test_dir2', 'subdir2',
197 self
.assert_(not exists(join(dst_dir
, 'test_dir2', 'subdir')))
200 if os
.path
.exists(dst_dir
):
201 shutil
.rmtree(dst_dir
)
203 if hasattr(os
, "symlink"):
204 def test_dont_copy_file_onto_link_to_itself(self
):
207 src
= os
.path
.join(TESTFN
, 'cheese')
208 dst
= os
.path
.join(TESTFN
, 'shop')
215 self
.assertRaises(shutil
.Error
, shutil
.copyfile
, src
, dst
)
216 self
.assertEqual(open(src
,'r').read(), 'cheddar')
219 # Using `src` here would mean we end up with a symlink pointing
220 # to TESTFN/TESTFN/cheese, while it should point at
222 os
.symlink('cheese', dst
)
223 self
.assertRaises(shutil
.Error
, shutil
.copyfile
, src
, dst
)
224 self
.assertEqual(open(src
,'r').read(), 'cheddar')
228 shutil
.rmtree(TESTFN
)
232 def test_rmtree_on_symlink(self
):
236 src
= os
.path
.join(TESTFN
, 'cheese')
237 dst
= os
.path
.join(TESTFN
, 'shop')
240 self
.assertRaises(OSError, shutil
.rmtree
, dst
)
242 shutil
.rmtree(TESTFN
, ignore_errors
=True)
244 if hasattr(os
, "mkfifo"):
245 # Issue #3002: copyfile and copytree block indefinitely on named pipes
246 def test_copyfile_named_pipe(self
):
249 self
.assertRaises(shutil
.SpecialFileError
,
250 shutil
.copyfile
, TESTFN
, TESTFN2
)
251 self
.assertRaises(shutil
.SpecialFileError
,
252 shutil
.copyfile
, __file__
, TESTFN
)
256 def test_copytree_named_pipe(self
):
259 subdir
= os
.path
.join(TESTFN
, "subdir")
261 pipe
= os
.path
.join(subdir
, "mypipe")
264 shutil
.copytree(TESTFN
, TESTFN2
)
265 except shutil
.Error
as e
:
267 self
.assertEqual(len(errors
), 1)
268 src
, dst
, error_msg
= errors
[0]
269 self
.assertEqual("`%s` is a named pipe" % pipe
, error_msg
)
271 self
.fail("shutil.Error should have been raised")
273 shutil
.rmtree(TESTFN
, ignore_errors
=True)
274 shutil
.rmtree(TESTFN2
, ignore_errors
=True)
277 class TestMove(unittest
.TestCase
):
281 self
.src_dir
= tempfile
.mkdtemp()
282 self
.dst_dir
= tempfile
.mkdtemp()
283 self
.src_file
= os
.path
.join(self
.src_dir
, filename
)
284 self
.dst_file
= os
.path
.join(self
.dst_dir
, filename
)
285 # Try to create a dir in the current directory, hoping that it is
286 # not located on the same filesystem as the system tmp dir.
288 self
.dir_other_fs
= tempfile
.mkdtemp(
289 dir=os
.path
.dirname(__file__
))
290 self
.file_other_fs
= os
.path
.join(self
.dir_other_fs
,
293 self
.dir_other_fs
= None
294 with
open(self
.src_file
, "wb") as f
:
298 for d
in (self
.src_dir
, self
.dst_dir
, self
.dir_other_fs
):
305 def _check_move_file(self
, src
, dst
, real_dst
):
306 contents
= open(src
, "rb").read()
307 shutil
.move(src
, dst
)
308 self
.assertEqual(contents
, open(real_dst
, "rb").read())
309 self
.assertFalse(os
.path
.exists(src
))
311 def _check_move_dir(self
, src
, dst
, real_dst
):
312 contents
= sorted(os
.listdir(src
))
313 shutil
.move(src
, dst
)
314 self
.assertEqual(contents
, sorted(os
.listdir(real_dst
)))
315 self
.assertFalse(os
.path
.exists(src
))
317 def test_move_file(self
):
318 # Move a file to another location on the same filesystem.
319 self
._check
_move
_file
(self
.src_file
, self
.dst_file
, self
.dst_file
)
321 def test_move_file_to_dir(self
):
322 # Move a file inside an existing dir on the same filesystem.
323 self
._check
_move
_file
(self
.src_file
, self
.dst_dir
, self
.dst_file
)
325 def test_move_file_other_fs(self
):
326 # Move a file to an existing dir on another filesystem.
327 if not self
.dir_other_fs
:
330 self
._check
_move
_file
(self
.src_file
, self
.file_other_fs
,
333 def test_move_file_to_dir_other_fs(self
):
334 # Move a file to another location on another filesystem.
335 if not self
.dir_other_fs
:
338 self
._check
_move
_file
(self
.src_file
, self
.dir_other_fs
,
341 def test_move_dir(self
):
342 # Move a dir to another location on the same filesystem.
343 dst_dir
= tempfile
.mktemp()
345 self
._check
_move
_dir
(self
.src_dir
, dst_dir
, dst_dir
)
348 shutil
.rmtree(dst_dir
)
352 def test_move_dir_other_fs(self
):
353 # Move a dir to another location on another filesystem.
354 if not self
.dir_other_fs
:
357 dst_dir
= tempfile
.mktemp(dir=self
.dir_other_fs
)
359 self
._check
_move
_dir
(self
.src_dir
, dst_dir
, dst_dir
)
362 shutil
.rmtree(dst_dir
)
366 def test_move_dir_to_dir(self
):
367 # Move a dir inside an existing dir on the same filesystem.
368 self
._check
_move
_dir
(self
.src_dir
, self
.dst_dir
,
369 os
.path
.join(self
.dst_dir
, os
.path
.basename(self
.src_dir
)))
371 def test_move_dir_to_dir_other_fs(self
):
372 # Move a dir inside an existing dir on another filesystem.
373 if not self
.dir_other_fs
:
376 self
._check
_move
_dir
(self
.src_dir
, self
.dir_other_fs
,
377 os
.path
.join(self
.dir_other_fs
, os
.path
.basename(self
.src_dir
)))
379 def test_existing_file_inside_dest_dir(self
):
380 # A file with the same name inside the destination dir already exists.
381 with
open(self
.dst_file
, "wb"):
383 self
.assertRaises(shutil
.Error
, shutil
.move
, self
.src_file
, self
.dst_dir
)
385 def test_dont_move_dir_in_itself(self
):
386 # Moving a dir inside itself raises an Error.
387 dst
= os
.path
.join(self
.src_dir
, "bar")
388 self
.assertRaises(shutil
.Error
, shutil
.move
, self
.src_dir
, dst
)
390 def test_destinsrc_false_negative(self
):
393 for src
, dst
in [('srcdir', 'srcdir/dest')]:
394 src
= os
.path
.join(TESTFN
, src
)
395 dst
= os
.path
.join(TESTFN
, dst
)
396 self
.assert_(shutil
._destinsrc
(src
, dst
),
397 msg
='_destinsrc() wrongly concluded that '
398 'dst (%s) is not in src (%s)' % (dst
, src
))
400 shutil
.rmtree(TESTFN
, ignore_errors
=True)
402 def test_destinsrc_false_positive(self
):
405 for src
, dst
in [('srcdir', 'src/dest'), ('srcdir', 'srcdir.new')]:
406 src
= os
.path
.join(TESTFN
, src
)
407 dst
= os
.path
.join(TESTFN
, dst
)
408 self
.failIf(shutil
._destinsrc
(src
, dst
),
409 msg
='_destinsrc() wrongly concluded that '
410 'dst (%s) is in src (%s)' % (dst
, src
))
412 shutil
.rmtree(TESTFN
, ignore_errors
=True)
415 test_support
.run_unittest(TestShutil
, TestMove
)
417 if __name__
== '__main__':