diff -r 917295aaad76 Lib/test/support.py --- a/Lib/test/support.py Mon Jul 30 00:01:44 2012 +0200 +++ b/Lib/test/support.py Sun Jul 29 19:56:54 2012 -0600 @@ -225,18 +225,83 @@ except KeyError: pass +if sys.platform.startswith("win"): + import ctypes as _ctypes + from ctypes import wintypes as _wintypes + _kernel32 = _ctypes.windll.kernel32 + def _waitfor(func, pathname, waitall=False): + # Peform the operation + func(pathname) + # Now setup the wait loop + if waitall: + findname = pathname + '\\*' + else: + findname = pathname + wfd = _wintypes.WIN32_FIND_DATAW() + pwfd = _ctypes.byref(wfd) + # Check for `pathname` to be removed from the filesystem. + # The exponential backoff of the timeout amounts to a total + # of ~1 second after which the deletion is probably an error + # anyway. + # Testing on a i7@4.3GHz shows that usually only 1 iteration is + # required when contention occurs. + timeout = 0.001 + while timeout < 1.0: + hnd = _kernel32.FindFirstFileW(findname, pwfd) + if hnd == -1: # INVALID_HANDLE_VALUE + return + try: + while wfd.cFileName in ('.', '..'): + if not _kernel32.FindNextFileW(hnd, pwfd): + return + else: + time.sleep(timeout) + timeout *= 2 + finally: + _kernel32.FindClose(hnd) + warnings.warn('tests may fail, delete still pending for ' + pathname, + RuntimeWarning, stacklevel=4) + def _unlink(filename): + _waitfor(os.unlink, filename) + def _rmdir(dirname): + _waitfor(os.rmdir, dirname) + def _rmtree(path): + def _rmtree_inner(path): + for name in os.listdir(path): + fullname = os.path.join(path, name) + if os.path.isdir(fullname): + _waitfor(_rmtree_inner, fullname, waitall=True) + os.rmdir(fullname) + else: + os.unlink(fullname) + _waitfor(_rmtree_inner, path, waitall=True) + _waitfor(os.rmdir, path) +else: + _unlink = os.unlink + _rmdir = os.rmdir + _rmtree = shutil.rmtree + def unlink(filename): try: - os.unlink(filename) + _unlink(filename) except OSError as error: # The filename need not exist. if error.errno not in (errno.ENOENT, errno.ENOTDIR): raise +def rmdir(dirname): + try: + _rmdir(dirname) + except OSError as error: + # The directory need not exist. + if error.errno != errno.ENOENT: + raise + def rmtree(path): try: - shutil.rmtree(path) + _rmtree(path) except OSError as error: + # The directory need not exist. if error.errno != errno.ENOENT: raise