Review rm_rf handling of FileNotFoundErrors

This commit is contained in:
Bruno Oliveira 2019-10-22 20:19:52 -03:00 committed by Bruno Oliveira
parent 82e9013e73
commit ba4b8c869c
3 changed files with 29 additions and 7 deletions

View File

@ -0,0 +1,3 @@
Properly ignore ``FileNotFoundError`` exceptions when trying to remove old temporary directories,
for instance when multiple processes try to remove the same directory (common with ``pytest-xdist``
for example).

View File

@ -38,21 +38,35 @@ def ensure_reset_dir(path):
path.mkdir()
def on_rm_rf_error(func, path: str, exc, *, start_path):
"""Handles known read-only errors during rmtree."""
excvalue = exc[1]
def on_rm_rf_error(func, path: str, exc, *, start_path) -> bool:
"""Handles known read-only errors during rmtree.
The returned value is used only by our own tests.
"""
exctype, excvalue = exc[:2]
# another process removed the file in the middle of the "rm_rf" (xdist for example)
# more context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
if isinstance(excvalue, FileNotFoundError):
return False
if not isinstance(excvalue, PermissionError):
warnings.warn(
PytestWarning("(rm_rf) error removing {}: {}".format(path, excvalue))
PytestWarning(
"(rm_rf) error removing {}\n{}: {}".format(path, exctype, excvalue)
)
)
return
return False
if func not in (os.rmdir, os.remove, os.unlink):
warnings.warn(
PytestWarning("(rm_rf) error removing {}: {}".format(path, excvalue))
PytestWarning(
"(rm_rf) unknown function {} when removing {}:\n{}: {}".format(
path, func, exctype, excvalue
)
)
)
return
return False
# Chmod + retry.
import stat
@ -73,6 +87,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path):
chmod_rw(str(path))
func(path)
return True
def rm_rf(path: Path):

View File

@ -383,6 +383,10 @@ class TestRmRf:
on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
assert fn.is_file()
# we ignore FileNotFoundError
exc_info = (None, FileNotFoundError(), None)
assert not on_rm_rf_error(None, str(fn), exc_info, start_path=tmp_path)
# unknown function
with pytest.warns(pytest.PytestWarning):
exc_info = (None, PermissionError(), None)