Skip to content

Commit 713b9e5

Browse files
authored
Review rm_rf handling of FileNotFoundErrors (#6044)
Review rm_rf handling of FileNotFoundErrors
2 parents 82e9013 + ba4b8c8 commit 713b9e5

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

changelog/6044.bugfix.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Properly ignore ``FileNotFoundError`` exceptions when trying to remove old temporary directories,
2+
for instance when multiple processes try to remove the same directory (common with ``pytest-xdist``
3+
for example).

src/_pytest/pathlib.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,35 @@ def ensure_reset_dir(path):
3838
path.mkdir()
3939

4040

41-
def on_rm_rf_error(func, path: str, exc, *, start_path):
42-
"""Handles known read-only errors during rmtree."""
43-
excvalue = exc[1]
41+
def on_rm_rf_error(func, path: str, exc, *, start_path) -> bool:
42+
"""Handles known read-only errors during rmtree.
43+
44+
The returned value is used only by our own tests.
45+
"""
46+
exctype, excvalue = exc[:2]
47+
48+
# another process removed the file in the middle of the "rm_rf" (xdist for example)
49+
# more context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
50+
if isinstance(excvalue, FileNotFoundError):
51+
return False
4452

4553
if not isinstance(excvalue, PermissionError):
4654
warnings.warn(
47-
PytestWarning("(rm_rf) error removing {}: {}".format(path, excvalue))
55+
PytestWarning(
56+
"(rm_rf) error removing {}\n{}: {}".format(path, exctype, excvalue)
57+
)
4858
)
49-
return
59+
return False
5060

5161
if func not in (os.rmdir, os.remove, os.unlink):
5262
warnings.warn(
53-
PytestWarning("(rm_rf) error removing {}: {}".format(path, excvalue))
63+
PytestWarning(
64+
"(rm_rf) unknown function {} when removing {}:\n{}: {}".format(
65+
path, func, exctype, excvalue
66+
)
67+
)
5468
)
55-
return
69+
return False
5670

5771
# Chmod + retry.
5872
import stat
@@ -73,6 +87,7 @@ def chmod_rw(p: str):
7387
chmod_rw(str(path))
7488

7589
func(path)
90+
return True
7691

7792

7893
def rm_rf(path: Path):

testing/test_tmpdir.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@ def test_on_rm_rf_error(self, tmp_path):
383383
on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
384384
assert fn.is_file()
385385

386+
# we ignore FileNotFoundError
387+
exc_info = (None, FileNotFoundError(), None)
388+
assert not on_rm_rf_error(None, str(fn), exc_info, start_path=tmp_path)
389+
386390
# unknown function
387391
with pytest.warns(pytest.PytestWarning):
388392
exc_info = (None, PermissionError(), None)

0 commit comments

Comments
 (0)