[Python-checkins] cpython (3.5): Issue #28666: Now test.support.rmtree is able to remove unwritable or

serhiy.storchaka python-checkins at python.org
Sun Nov 20 09:28:55 EST 2016


https://hg.python.org/cpython/rev/c92f9be77b9b
changeset:   105216:c92f9be77b9b
branch:      3.5
parent:      105211:75fe67538905
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sun Nov 20 16:16:06 2016 +0200
summary:
  Issue #28666: Now test.support.rmtree is able to remove unwritable or
unreadable directories.

files:
  Lib/test/support/__init__.py |  32 ++++++++++++++++++++++-
  Lib/test/test_support.py     |  33 ++++++++++++++++-------
  Misc/NEWS                    |   3 ++
  3 files changed, 57 insertions(+), 11 deletions(-)


diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -357,7 +357,37 @@
 else:
     _unlink = os.unlink
     _rmdir = os.rmdir
-    _rmtree = shutil.rmtree
+
+    def _rmtree(path):
+        try:
+            shutil.rmtree(path)
+            return
+        except OSError:
+            pass
+
+        def force_run(path, func, *args):
+            try:
+                return func(*args)
+            except OSError as err:
+                if verbose >= 2:
+                    print('%s: %s' % (err.__class__.__name__, err))
+                    print('re-run %s%r' % (func.__name__, args))
+                os.chmod(path, stat.S_IRWXU)
+                return func(*args)
+        def _rmtree_inner(path):
+            for name in force_run(path, os.listdir, path):
+                fullname = os.path.join(path, name)
+                try:
+                    mode = os.lstat(fullname).st_mode
+                except OSError:
+                    mode = 0
+                if stat.S_ISDIR(mode):
+                    _rmtree_inner(fullname)
+                    force_run(path, os.rmdir, fullname)
+                else:
+                    force_run(path, os.unlink, fullname)
+        _rmtree_inner(path)
+        os.rmdir(path)
 
 def unlink(filename):
     try:
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -1,5 +1,6 @@
 import importlib
 import shutil
+import stat
 import sys
 import os
 import unittest
@@ -9,14 +10,9 @@
 from test import support
 
 TESTFN = support.TESTFN
-TESTDIRN = os.path.basename(tempfile.mkdtemp(dir='.'))
 
 
 class TestSupport(unittest.TestCase):
-    def setUp(self):
-        support.unlink(TESTFN)
-        support.rmtree(TESTDIRN)
-    tearDown = setUp
 
     def test_import_module(self):
         support.import_module("ftplib")
@@ -48,11 +44,28 @@
         support.unlink(TESTFN)
 
     def test_rmtree(self):
-        os.mkdir(TESTDIRN)
-        os.mkdir(os.path.join(TESTDIRN, TESTDIRN))
-        support.rmtree(TESTDIRN)
-        self.assertFalse(os.path.exists(TESTDIRN))
-        support.rmtree(TESTDIRN)
+        dirpath = support.TESTFN + 'd'
+        subdirpath = os.path.join(dirpath, 'subdir')
+        os.mkdir(dirpath)
+        os.mkdir(subdirpath)
+        support.rmtree(dirpath)
+        self.assertFalse(os.path.exists(dirpath))
+        with support.swap_attr(support, 'verbose', 0):
+            support.rmtree(dirpath)
+
+        os.mkdir(dirpath)
+        os.mkdir(subdirpath)
+        os.chmod(dirpath, stat.S_IRUSR|stat.S_IXUSR)
+        with support.swap_attr(support, 'verbose', 0):
+            support.rmtree(dirpath)
+        self.assertFalse(os.path.exists(dirpath))
+
+        os.mkdir(dirpath)
+        os.mkdir(subdirpath)
+        os.chmod(dirpath, 0)
+        with support.swap_attr(support, 'verbose', 0):
+            support.rmtree(dirpath)
+        self.assertFalse(os.path.exists(dirpath))
 
     def test_forget(self):
         mod_filename = TESTFN + '.py'
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -511,6 +511,9 @@
 Tests
 -----
 
+- Issue #28666: Now test.support.rmtree is able to remove unwritable or
+  unreadable directories.
+
 - Issue #23839: Various caches now are cleared before running every test file.
 
 - Issue #28409: regrtest: fix the parser of command line arguments.

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list