summaryrefslogtreecommitdiff
path: root/Lib/test/test_support.py
diff options
context:
space:
mode:
authorBrian Curtin <brian@python.org>2012-08-13 17:26:48 -0500
committerBrian Curtin <brian@python.org>2012-08-13 17:26:48 -0500
commitbc77d3690b4b0c9dbb8a00b15cfea74c4bdb134f (patch)
treeef80992e2791a4c734a46f954e1770f17eb61581 /Lib/test/test_support.py
parent33f87a59b8855aa17970c9f680681d24669e7d20 (diff)
downloadcpython-git-bc77d3690b4b0c9dbb8a00b15cfea74c4bdb134f.tar.gz
Fix #15496. Add directory removal helpers to make Windows tests more reliable. Patch by Jeremy Kloth
Diffstat (limited to 'Lib/test/test_support.py')
-rw-r--r--Lib/test/test_support.py68
1 files changed, 66 insertions, 2 deletions
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index a8d92c6013..270b46bc17 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -181,15 +181,79 @@ def unload(name):
except KeyError:
pass
+if sys.platform.startswith("win"):
+ def _waitfor(func, pathname, waitall=False):
+ # Peform the operation
+ func(pathname)
+ # Now setup the wait loop
+ if waitall:
+ dirname = pathname
+ else:
+ dirname, name = os.path.split(pathname)
+ dirname = dirname or '.'
+ # 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:
+ # Note we are only testing for the existance of the file(s) in
+ # the contents of the directory regardless of any security or
+ # access rights. If we have made it this far, we have sufficient
+ # permissions to do that much using Python's equivalent of the
+ # Windows API FindFirstFile.
+ # Other Windows APIs can fail or give incorrect results when
+ # dealing with files that are pending deletion.
+ L = os.listdir(dirname)
+ if not (L if waitall else name in L):
+ return
+ # Increase the timeout and try again
+ time.sleep(timeout)
+ timeout *= 2
+ 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:
pass
+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, e:
# Unix returns ENOENT, Windows returns ESRCH.
if e.errno not in (errno.ENOENT, errno.ESRCH):