changeset: 105215:63820871014d branch: 2.7 parent: 105141:ea91bb92c28b user: Serhiy Storchaka date: Sun Nov 20 16:15:35 2016 +0200 files: Lib/test/test_support.py Misc/NEWS description: Issue #28666: Now test.support.rmtree is able to remove unwritable or unreadable directories. diff -r ea91bb92c28b -r 63820871014d Lib/test/test_support.py --- a/Lib/test/test_support.py Tue Nov 15 21:21:35 2016 -0500 +++ b/Lib/test/test_support.py Sun Nov 20 16:15:35 2016 +0200 @@ -236,7 +236,38 @@ else: _unlink = os.unlink _rmdir = os.rmdir - _rmtree = shutil.rmtree + + def _rmtree(path): + import stat + try: + shutil.rmtree(path) + return + except EnvironmentError: + pass + + def force_run(path, func, *args): + try: + return func(*args) + except EnvironmentError 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 EnvironmentError: + 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 -r ea91bb92c28b -r 63820871014d Misc/NEWS --- a/Misc/NEWS Tue Nov 15 21:21:35 2016 -0500 +++ b/Misc/NEWS Sun Nov 20 16:15:35 2016 +0200 @@ -262,6 +262,9 @@ Tests ----- +- Issue #28666: Now test.test_support.rmtree is able to remove unwritable or + unreadable directories. + - Issue #23839: Various caches now are cleared before running every test file. - Issue #27369: In test_pyexpat, avoid testing an error message detail that