Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6f5c5cb

Browse files
committed
Fix #15496. Add directory removal helpers to make Windows tests more reliable. Patch by Jeremy Kloth
1 parent 59db401 commit 6f5c5cb

2 files changed

Lines changed: 69 additions & 2 deletions

File tree

Lib/test/support.py

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,81 @@ def unload(name):
200200
except KeyError:
201201
pass
202202

203+
if sys.platform.startswith("win"):
204+
def _waitfor(func, pathname, waitall=False):
205+
# Peform the operation
206+
func(pathname)
207+
# Now setup the wait loop
208+
if waitall:
209+
dirname = pathname
210+
else:
211+
dirname, name = os.path.split(pathname)
212+
dirname = dirname or '.'
213+
# Check for `pathname` to be removed from the filesystem.
214+
# The exponential backoff of the timeout amounts to a total
215+
# of ~1 second after which the deletion is probably an error
216+
# anyway.
217+
# Testing on a [email protected] shows that usually only 1 iteration is
218+
# required when contention occurs.
219+
timeout = 0.001
220+
while timeout < 1.0:
221+
# Note we are only testing for the existance of the file(s) in
222+
# the contents of the directory regardless of any security or
223+
# access rights. If we have made it this far, we have sufficient
224+
# permissions to do that much using Python's equivalent of the
225+
# Windows API FindFirstFile.
226+
# Other Windows APIs can fail or give incorrect results when
227+
# dealing with files that are pending deletion.
228+
L = os.listdir(dirname)
229+
if not (L if waitall else name in L):
230+
return
231+
# Increase the timeout and try again
232+
time.sleep(timeout)
233+
timeout *= 2
234+
warnings.warn('tests may fail, delete still pending for ' + pathname,
235+
RuntimeWarning, stacklevel=4)
236+
237+
def _unlink(filename):
238+
_waitfor(os.unlink, filename)
239+
240+
def _rmdir(dirname):
241+
_waitfor(os.rmdir, dirname)
242+
243+
def _rmtree(path):
244+
def _rmtree_inner(path):
245+
for name in os.listdir(path):
246+
fullname = os.path.join(path, name)
247+
if os.path.isdir(fullname):
248+
_waitfor(_rmtree_inner, fullname, waitall=True)
249+
os.rmdir(fullname)
250+
else:
251+
os.unlink(fullname)
252+
_waitfor(_rmtree_inner, path, waitall=True)
253+
_waitfor(os.rmdir, path)
254+
else:
255+
_unlink = os.unlink
256+
_rmdir = os.rmdir
257+
_rmtree = shutil.rmtree
258+
203259
def unlink(filename):
204260
try:
205-
os.unlink(filename)
261+
_unlink(filename)
206262
except OSError as error:
207263
# The filename need not exist.
208264
if error.errno not in (errno.ENOENT, errno.ENOTDIR):
209265
raise
210266

267+
def rmdir(dirname):
268+
try:
269+
_rmdir(dirname)
270+
except OSError as error:
271+
# The directory need not exist.
272+
if error.errno != errno.ENOENT:
273+
raise
274+
211275
def rmtree(path):
212276
try:
213-
shutil.rmtree(path)
277+
_rmtree(path)
214278
except OSError as error:
215279
# Unix returns ENOENT, Windows returns ESRCH.
216280
if error.errno not in (errno.ENOENT, errno.ESRCH):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ Extension Modules
413413
Tests
414414
-----
415415

416+
- Issue #15496: Add directory removal helpers for tests on Windows.
417+
Patch by Jeremy Kloth.
418+
416419
- Issue #15467: Move helpers for __sizeof__ tests into test_support.
417420
Patch by Serhiy Storchaka.
418421

0 commit comments

Comments
 (0)