| 
									
										
										
										
											2003-01-24 17:34:13 +00:00
										 |  |  | # Copyright (C) 2003 Python Software Foundation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import shutil | 
					
						
							|  |  |  | import tempfile | 
					
						
							| 
									
										
										
										
											2004-11-23 09:27:27 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  | import stat | 
					
						
							| 
									
										
										
										
											2004-06-19 21:11:35 +00:00
										 |  |  | import os | 
					
						
							|  |  |  | import os.path | 
					
						
							| 
									
										
										
										
											2003-01-24 17:34:13 +00:00
										 |  |  | from test import test_support | 
					
						
							| 
									
										
										
										
											2004-08-14 13:30:02 +00:00
										 |  |  | from test.test_support import TESTFN | 
					
						
							| 
									
										
										
										
											2003-01-24 17:34:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestShutil(unittest.TestCase): | 
					
						
							|  |  |  |     def test_rmtree_errors(self): | 
					
						
							|  |  |  |         # filename is guaranteed not to exist | 
					
						
							|  |  |  |         filename = tempfile.mktemp() | 
					
						
							|  |  |  |         self.assertRaises(OSError, shutil.rmtree, filename) | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-06 20:50:15 +00:00
										 |  |  |     # See bug #1071513 for why we don't run this on cygwin | 
					
						
							|  |  |  |     # and bug #1076467 for why we don't run this as root. | 
					
						
							|  |  |  |     if (hasattr(os, 'chmod') and sys.platform[:6] != 'cygwin' | 
					
						
							| 
									
										
										
										
											2004-12-12 15:52:57 +00:00
										 |  |  |         and not (hasattr(os, 'geteuid') and os.geteuid() == 0)): | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  |         def test_on_error(self): | 
					
						
							|  |  |  |             self.errorState = 0 | 
					
						
							|  |  |  |             os.mkdir(TESTFN) | 
					
						
							| 
									
										
										
										
											2004-11-01 02:40:52 +00:00
										 |  |  |             self.childpath = os.path.join(TESTFN, 'a') | 
					
						
							|  |  |  |             f = open(self.childpath, 'w') | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  |             f.close() | 
					
						
							| 
									
										
										
										
											2004-11-01 02:40:52 +00:00
										 |  |  |             old_dir_mode = os.stat(TESTFN).st_mode | 
					
						
							|  |  |  |             old_child_mode = os.stat(self.childpath).st_mode | 
					
						
							|  |  |  |             # Make unwritable. | 
					
						
							|  |  |  |             os.chmod(self.childpath, stat.S_IREAD) | 
					
						
							|  |  |  |             os.chmod(TESTFN, stat.S_IREAD) | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror) | 
					
						
							| 
									
										
										
										
											2004-11-23 09:27:27 +00:00
										 |  |  |             # Test whether onerror has actually been called. | 
					
						
							| 
									
										
										
										
											2004-12-06 20:50:15 +00:00
										 |  |  |             self.assertEqual(self.errorState, 2, | 
					
						
							|  |  |  |                              "Expected call to onerror function did not happen.") | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-01 02:40:52 +00:00
										 |  |  |             # Make writable again. | 
					
						
							|  |  |  |             os.chmod(TESTFN, old_dir_mode) | 
					
						
							|  |  |  |             os.chmod(self.childpath, old_child_mode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Clean up. | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  |             shutil.rmtree(TESTFN) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def check_args_to_onerror(self, func, arg, exc): | 
					
						
							|  |  |  |         if self.errorState == 0: | 
					
						
							|  |  |  |             self.assertEqual(func, os.remove) | 
					
						
							| 
									
										
										
										
											2004-11-01 02:40:52 +00:00
										 |  |  |             self.assertEqual(arg, self.childpath) | 
					
						
							| 
									
										
										
										
											2006-05-04 10:08:42 +00:00
										 |  |  |             self.failUnless(issubclass(exc[0], OSError)) | 
					
						
							| 
									
										
										
										
											2004-10-31 12:05:31 +00:00
										 |  |  |             self.errorState = 1 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.assertEqual(func, os.rmdir) | 
					
						
							|  |  |  |             self.assertEqual(arg, TESTFN) | 
					
						
							| 
									
										
										
										
											2006-05-04 10:08:42 +00:00
										 |  |  |             self.failUnless(issubclass(exc[0], OSError)) | 
					
						
							| 
									
										
										
										
											2004-11-23 09:27:27 +00:00
										 |  |  |             self.errorState = 2 | 
					
						
							| 
									
										
										
										
											2003-01-24 17:34:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-11 21:26:21 +00:00
										 |  |  |     def test_rmtree_dont_delete_file(self): | 
					
						
							|  |  |  |         # When called on a file instead of a directory, don't delete it. | 
					
						
							|  |  |  |         handle, path = tempfile.mkstemp() | 
					
						
							|  |  |  |         os.fdopen(handle).close() | 
					
						
							|  |  |  |         self.assertRaises(OSError, shutil.rmtree, path) | 
					
						
							|  |  |  |         os.remove(path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-30 13:00:31 +00:00
										 |  |  |     def test_copytree_simple(self): | 
					
						
							| 
									
										
										
										
											2006-08-10 03:01:26 +00:00
										 |  |  |         def write_data(path, data): | 
					
						
							|  |  |  |             f = open(path, "w") | 
					
						
							|  |  |  |             f.write(data) | 
					
						
							|  |  |  |             f.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read_data(path): | 
					
						
							|  |  |  |             f = open(path) | 
					
						
							|  |  |  |             data = f.read() | 
					
						
							|  |  |  |             f.close() | 
					
						
							|  |  |  |             return data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-30 13:00:31 +00:00
										 |  |  |         src_dir = tempfile.mkdtemp() | 
					
						
							|  |  |  |         dst_dir = os.path.join(tempfile.mkdtemp(), 'destination') | 
					
						
							| 
									
										
										
										
											2006-08-10 03:01:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         write_data(os.path.join(src_dir, 'test.txt'), '123') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-30 13:00:31 +00:00
										 |  |  |         os.mkdir(os.path.join(src_dir, 'test_dir')) | 
					
						
							| 
									
										
										
										
											2006-08-10 03:01:26 +00:00
										 |  |  |         write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-30 13:00:31 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             shutil.copytree(src_dir, dst_dir) | 
					
						
							|  |  |  |             self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test.txt'))) | 
					
						
							|  |  |  |             self.assertTrue(os.path.isdir(os.path.join(dst_dir, 'test_dir'))) | 
					
						
							| 
									
										
										
										
											2006-08-10 03:01:26 +00:00
										 |  |  |             self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test_dir', | 
					
						
							|  |  |  |                                                         'test.txt'))) | 
					
						
							|  |  |  |             actual = read_data(os.path.join(dst_dir, 'test.txt')) | 
					
						
							|  |  |  |             self.assertEqual(actual, '123') | 
					
						
							|  |  |  |             actual = read_data(os.path.join(dst_dir, 'test_dir', 'test.txt')) | 
					
						
							|  |  |  |             self.assertEqual(actual, '456') | 
					
						
							| 
									
										
										
										
											2006-07-30 13:00:31 +00:00
										 |  |  |         finally: | 
					
						
							| 
									
										
										
										
											2006-08-10 03:01:26 +00:00
										 |  |  |             for path in ( | 
					
						
							|  |  |  |                     os.path.join(src_dir, 'test.txt'), | 
					
						
							|  |  |  |                     os.path.join(dst_dir, 'test.txt'), | 
					
						
							|  |  |  |                     os.path.join(src_dir, 'test_dir', 'test.txt'), | 
					
						
							|  |  |  |                     os.path.join(dst_dir, 'test_dir', 'test.txt'), | 
					
						
							|  |  |  |                 ): | 
					
						
							|  |  |  |                 if os.path.exists(path): | 
					
						
							|  |  |  |                     os.remove(path) | 
					
						
							| 
									
										
										
										
											2007-11-20 03:21:02 +00:00
										 |  |  |             for path in (src_dir, | 
					
						
							|  |  |  |                     os.path.abspath(os.path.join(dst_dir, os.path.pardir)) | 
					
						
							|  |  |  |                 ): | 
					
						
							| 
									
										
										
										
											2006-08-10 03:01:26 +00:00
										 |  |  |                 if os.path.exists(path): | 
					
						
							| 
									
										
										
										
											2007-11-20 01:48:48 +00:00
										 |  |  |                     shutil.rmtree(path) | 
					
						
							| 
									
										
										
										
											2006-07-31 01:46:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-14 13:30:02 +00:00
										 |  |  |     if hasattr(os, "symlink"): | 
					
						
							|  |  |  |         def test_dont_copy_file_onto_link_to_itself(self): | 
					
						
							|  |  |  |             # bug 851123. | 
					
						
							|  |  |  |             os.mkdir(TESTFN) | 
					
						
							| 
									
										
										
										
											2004-08-14 13:57:08 +00:00
										 |  |  |             src = os.path.join(TESTFN, 'cheese') | 
					
						
							|  |  |  |             dst = os.path.join(TESTFN, 'shop') | 
					
						
							| 
									
										
										
										
											2004-08-14 13:30:02 +00:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2004-08-14 13:57:08 +00:00
										 |  |  |                 f = open(src, 'w') | 
					
						
							| 
									
										
										
										
											2004-08-14 13:30:02 +00:00
										 |  |  |                 f.write('cheddar') | 
					
						
							|  |  |  |                 f.close() | 
					
						
							| 
									
										
										
										
											2004-08-14 13:57:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 os.link(src, dst) | 
					
						
							|  |  |  |                 self.assertRaises(shutil.Error, shutil.copyfile, src, dst) | 
					
						
							|  |  |  |                 self.assertEqual(open(src,'r').read(), 'cheddar') | 
					
						
							|  |  |  |                 os.remove(dst) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Using `src` here would mean we end up with a symlink pointing | 
					
						
							|  |  |  |                 # to TESTFN/TESTFN/cheese, while it should point at | 
					
						
							|  |  |  |                 # TESTFN/cheese. | 
					
						
							|  |  |  |                 os.symlink('cheese', dst) | 
					
						
							|  |  |  |                 self.assertRaises(shutil.Error, shutil.copyfile, src, dst) | 
					
						
							|  |  |  |                 self.assertEqual(open(src,'r').read(), 'cheddar') | 
					
						
							|  |  |  |                 os.remove(dst) | 
					
						
							| 
									
										
										
										
											2004-08-14 13:30:02 +00:00
										 |  |  |             finally: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     shutil.rmtree(TESTFN) | 
					
						
							|  |  |  |                 except OSError: | 
					
						
							|  |  |  |                     pass | 
					
						
							| 
									
										
										
										
											2004-06-19 21:11:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-20 14:17:42 +00:00
										 |  |  |         def test_rmtree_on_symlink(self): | 
					
						
							|  |  |  |             # bug 1669. | 
					
						
							|  |  |  |             os.mkdir(TESTFN) | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 src = os.path.join(TESTFN, 'cheese') | 
					
						
							|  |  |  |                 dst = os.path.join(TESTFN, 'shop') | 
					
						
							|  |  |  |                 os.mkdir(src) | 
					
						
							|  |  |  |                 os.symlink(src, dst) | 
					
						
							|  |  |  |                 self.assertRaises(OSError, shutil.rmtree, dst) | 
					
						
							|  |  |  |             finally: | 
					
						
							|  |  |  |                 shutil.rmtree(TESTFN, ignore_errors=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-18 17:24:12 +00:00
										 |  |  | class TestMove(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							|  |  |  |         filename = "foo" | 
					
						
							|  |  |  |         self.src_dir = tempfile.mkdtemp() | 
					
						
							|  |  |  |         self.dst_dir = tempfile.mkdtemp() | 
					
						
							|  |  |  |         self.src_file = os.path.join(self.src_dir, filename) | 
					
						
							|  |  |  |         self.dst_file = os.path.join(self.dst_dir, filename) | 
					
						
							|  |  |  |         # Try to create a dir in the current directory, hoping that it is | 
					
						
							|  |  |  |         # not located on the same filesystem as the system tmp dir. | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self.dir_other_fs = tempfile.mkdtemp( | 
					
						
							|  |  |  |                 dir=os.path.dirname(__file__)) | 
					
						
							|  |  |  |             self.file_other_fs = os.path.join(self.dir_other_fs, | 
					
						
							|  |  |  |                 filename) | 
					
						
							|  |  |  |         except OSError: | 
					
						
							|  |  |  |             self.dir_other_fs = None | 
					
						
							|  |  |  |         with open(self.src_file, "wb") as f: | 
					
						
							|  |  |  |             f.write("spam") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         for d in (self.src_dir, self.dst_dir, self.dir_other_fs): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 if d: | 
					
						
							|  |  |  |                     shutil.rmtree(d) | 
					
						
							|  |  |  |             except: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _check_move_file(self, src, dst, real_dst): | 
					
						
							|  |  |  |         contents = open(src, "rb").read() | 
					
						
							|  |  |  |         shutil.move(src, dst) | 
					
						
							|  |  |  |         self.assertEqual(contents, open(real_dst, "rb").read()) | 
					
						
							|  |  |  |         self.assertFalse(os.path.exists(src)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _check_move_dir(self, src, dst, real_dst): | 
					
						
							|  |  |  |         contents = sorted(os.listdir(src)) | 
					
						
							|  |  |  |         shutil.move(src, dst) | 
					
						
							|  |  |  |         self.assertEqual(contents, sorted(os.listdir(real_dst))) | 
					
						
							|  |  |  |         self.assertFalse(os.path.exists(src)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_file(self): | 
					
						
							|  |  |  |         # Move a file to another location on the same filesystem. | 
					
						
							|  |  |  |         self._check_move_file(self.src_file, self.dst_file, self.dst_file) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_file_to_dir(self): | 
					
						
							|  |  |  |         # Move a file inside an existing dir on the same filesystem. | 
					
						
							|  |  |  |         self._check_move_file(self.src_file, self.dst_dir, self.dst_file) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_file_other_fs(self): | 
					
						
							|  |  |  |         # Move a file to an existing dir on another filesystem. | 
					
						
							|  |  |  |         if not self.dir_other_fs: | 
					
						
							|  |  |  |             # skip | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         self._check_move_file(self.src_file, self.file_other_fs, | 
					
						
							|  |  |  |             self.file_other_fs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_file_to_dir_other_fs(self): | 
					
						
							|  |  |  |         # Move a file to another location on another filesystem. | 
					
						
							|  |  |  |         if not self.dir_other_fs: | 
					
						
							|  |  |  |             # skip | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         self._check_move_file(self.src_file, self.dir_other_fs, | 
					
						
							|  |  |  |             self.file_other_fs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_dir(self): | 
					
						
							|  |  |  |         # Move a dir to another location on the same filesystem. | 
					
						
							|  |  |  |         dst_dir = tempfile.mktemp() | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self._check_move_dir(self.src_dir, dst_dir, dst_dir) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 shutil.rmtree(dst_dir) | 
					
						
							|  |  |  |             except: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_dir_other_fs(self): | 
					
						
							|  |  |  |         # Move a dir to another location on another filesystem. | 
					
						
							|  |  |  |         if not self.dir_other_fs: | 
					
						
							|  |  |  |             # skip | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         dst_dir = tempfile.mktemp(dir=self.dir_other_fs) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self._check_move_dir(self.src_dir, dst_dir, dst_dir) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 shutil.rmtree(dst_dir) | 
					
						
							|  |  |  |             except: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_dir_to_dir(self): | 
					
						
							|  |  |  |         # Move a dir inside an existing dir on the same filesystem. | 
					
						
							|  |  |  |         self._check_move_dir(self.src_dir, self.dst_dir, | 
					
						
							|  |  |  |             os.path.join(self.dst_dir, os.path.basename(self.src_dir))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_move_dir_to_dir_other_fs(self): | 
					
						
							|  |  |  |         # Move a dir inside an existing dir on another filesystem. | 
					
						
							|  |  |  |         if not self.dir_other_fs: | 
					
						
							|  |  |  |             # skip | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         self._check_move_dir(self.src_dir, self.dir_other_fs, | 
					
						
							|  |  |  |             os.path.join(self.dir_other_fs, os.path.basename(self.src_dir))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_existing_file_inside_dest_dir(self): | 
					
						
							|  |  |  |         # A file with the same name inside the destination dir already exists. | 
					
						
							|  |  |  |         with open(self.dst_file, "wb"): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         self.assertRaises(shutil.Error, shutil.move, self.src_file, self.dst_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_dont_move_dir_in_itself(self): | 
					
						
							|  |  |  |         # Moving a dir inside itself raises an Error. | 
					
						
							|  |  |  |         dst = os.path.join(self.src_dir, "bar") | 
					
						
							|  |  |  |         self.assertRaises(shutil.Error, shutil.move, self.src_dir, dst) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-20 14:17:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-24 17:34:13 +00:00
										 |  |  | def test_main(): | 
					
						
							| 
									
										
										
										
											2008-03-18 17:24:12 +00:00
										 |  |  |     test_support.run_unittest(TestShutil, TestMove) | 
					
						
							| 
									
										
										
										
											2003-01-24 17:34:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2003-05-01 17:45:56 +00:00
										 |  |  |     test_main() |