Issue #28666: Now test.support.rmtree is able to remove unwritable or

unreadable directories on Windows too.
This commit is contained in:
Serhiy Storchaka 2016-11-20 17:43:09 +02:00
commit 8551495ad1
1 changed files with 16 additions and 15 deletions

View File

@ -298,6 +298,16 @@ def unload(name):
except KeyError: except KeyError:
pass 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)
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
def _waitfor(func, pathname, waitall=False): def _waitfor(func, pathname, waitall=False):
# Perform the operation # Perform the operation
@ -340,7 +350,7 @@ if sys.platform.startswith("win"):
def _rmtree(path): def _rmtree(path):
def _rmtree_inner(path): def _rmtree_inner(path):
for name in os.listdir(path): for name in _force_run(path, os.listdir, path):
fullname = os.path.join(path, name) fullname = os.path.join(path, name)
try: try:
mode = os.lstat(fullname).st_mode mode = os.lstat(fullname).st_mode
@ -350,9 +360,9 @@ if sys.platform.startswith("win"):
mode = 0 mode = 0
if stat.S_ISDIR(mode): if stat.S_ISDIR(mode):
_waitfor(_rmtree_inner, fullname, waitall=True) _waitfor(_rmtree_inner, fullname, waitall=True)
os.rmdir(fullname) _force_run(path, os.rmdir, fullname)
else: else:
os.unlink(fullname) _force_run(path, os.unlink, fullname)
_waitfor(_rmtree_inner, path, waitall=True) _waitfor(_rmtree_inner, path, waitall=True)
_waitfor(os.rmdir, path) _waitfor(os.rmdir, path)
else: else:
@ -366,17 +376,8 @@ else:
except OSError: except OSError:
pass 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): def _rmtree_inner(path):
for name in force_run(path, os.listdir, path): for name in _force_run(path, os.listdir, path):
fullname = os.path.join(path, name) fullname = os.path.join(path, name)
try: try:
mode = os.lstat(fullname).st_mode mode = os.lstat(fullname).st_mode
@ -384,9 +385,9 @@ else:
mode = 0 mode = 0
if stat.S_ISDIR(mode): if stat.S_ISDIR(mode):
_rmtree_inner(fullname) _rmtree_inner(fullname)
force_run(path, os.rmdir, fullname) _force_run(path, os.rmdir, fullname)
else: else:
force_run(path, os.unlink, fullname) _force_run(path, os.unlink, fullname)
_rmtree_inner(path) _rmtree_inner(path)
os.rmdir(path) os.rmdir(path)