Review rm_rf handling of FileNotFoundErrors (#6044)
Review rm_rf handling of FileNotFoundErrors
This commit is contained in:
commit
713b9e54c3
|
@ -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).
|
|
@ -38,21 +38,35 @@ def ensure_reset_dir(path):
|
||||||
path.mkdir()
|
path.mkdir()
|
||||||
|
|
||||||
|
|
||||||
def on_rm_rf_error(func, path: str, exc, *, start_path):
|
def on_rm_rf_error(func, path: str, exc, *, start_path) -> bool:
|
||||||
"""Handles known read-only errors during rmtree."""
|
"""Handles known read-only errors during rmtree.
|
||||||
excvalue = exc[1]
|
|
||||||
|
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):
|
if not isinstance(excvalue, PermissionError):
|
||||||
warnings.warn(
|
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):
|
if func not in (os.rmdir, os.remove, os.unlink):
|
||||||
warnings.warn(
|
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.
|
# Chmod + retry.
|
||||||
import stat
|
import stat
|
||||||
|
@ -73,6 +87,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path):
|
||||||
chmod_rw(str(path))
|
chmod_rw(str(path))
|
||||||
|
|
||||||
func(path)
|
func(path)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def rm_rf(path: Path):
|
def rm_rf(path: Path):
|
||||||
|
|
|
@ -383,6 +383,10 @@ class TestRmRf:
|
||||||
on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
|
on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
|
||||||
assert fn.is_file()
|
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
|
# unknown function
|
||||||
with pytest.warns(pytest.PytestWarning):
|
with pytest.warns(pytest.PytestWarning):
|
||||||
exc_info = (None, PermissionError(), None)
|
exc_info = (None, PermissionError(), None)
|
||||||
|
|
Loading…
Reference in New Issue