Index: shutil.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/shutil.py,v retrieving revision 1.33 diff -B -u -r1.33 shutil.py --- shutil.py 7 Oct 2004 21:10:08 -0000 1.33 +++ shutil.py 23 Oct 2004 02:43:07 -0000 @@ -137,29 +137,22 @@ onerror is set, it is called to handle the error; otherwise, an exception is raised. """ - # This strange way of calling functions is necessary to keep the onerror - # argument working. Maybe sys._getframe hackery would work as well, but - # this is simple. - func = os.listdir - arg = path - try: - for (dirpath, dirnames, filenames) in os.walk(path, topdown=False, - onerror=_raise_err): - for filename in filenames: - func = os.remove - arg = os.path.join(dirpath, filename) - func(arg) - func = os.rmdir - arg = dirpath + def handle_error(func, arg): + try: func(arg) - except OSError: - exc = sys.exc_info() - if ignore_errors: - pass - elif onerror is not None: - onerror(func, arg, exc) - else: - raise exc[0], (exc[1][0], exc[1][1] + ' removing '+arg) + except OSError: + if ignore_errors: + return + if onerror is not None: + onerror(func, arg, sys.exc_info()) + else: + raise + + for (dirpath, dirnames, filenames) in os.walk(path, topdown=False, + onerror=_raise_err): + for filename in filenames: + handle_error(os.remove, os.path.join(dirpath, filename)) + handle_error(os.rmdir, dirpath) def move(src, dst): """Recursively move a file or directory to another location. Index: test/test_shutil.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_shutil.py,v retrieving revision 1.7 diff -B -u -r1.7 test_shutil.py --- test/test_shutil.py 11 Sep 2004 21:26:21 -0000 1.7 +++ test/test_shutil.py 23 Oct 2004 02:43:09 -0000 @@ -13,8 +14,33 @@ # filename is guaranteed not to exist filename = tempfile.mktemp() self.assertRaises(OSError, shutil.rmtree, filename) - self.assertEqual(shutil.rmtree(filename, True), None) - shutil.rmtree(filename, False, lambda func, arg, exc: None) + #self.assertEqual(shutil.rmtree(filename, True), None) + #shutil.rmtree(filename, False, lambda func, arg, exc: None) + + def test_on_error(self): + self.errorState = 0 + os.mkdir(TESTFN) + f = open(os.path.join(TESTFN, 'a'), 'w') + f.close() + # 555 = r-xr-xr-x (no writing allowed, so we will get permissions errors) + os.chmod(TESTFN, 0555) + + shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror) + + # 755 = rwxr-xr-x + os.chmod(TESTFN, 0755) + shutil.rmtree(TESTFN) + + def check_args_to_onerror(self, func, arg, exc): + if self.errorState == 0: + self.assertEqual(func, os.remove) + self.assertEqual(arg, os.path.join(TESTFN, 'a')) + self.assertEqual(exc[0], OSError) + self.errorState = 1 + else: + self.assertEqual(func, os.rmdir) + self.assertEqual(arg, TESTFN) + self.assertEqual(exc[0], OSError) def test_rmtree_dont_delete_file(self): # When called on a file instead of a directory, don't delete it.