diff --git a/changelog/7491.bugfix.rst b/changelog/7491.bugfix.rst new file mode 100644 index 000000000..5b00a5713 --- /dev/null +++ b/changelog/7491.bugfix.rst @@ -0,0 +1,2 @@ +:fixture:`tmpdir` and :fixture:`tmp_path` no longer raise an error if the lock to check for +stale temporary directories is not accessible. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 6a0bf7f6f..92ba32082 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -286,12 +286,17 @@ def maybe_delete_a_numbered_dir(path: Path) -> None: def ensure_deletable(path: Path, consider_lock_dead_if_created_before: float) -> bool: - """checks if a lock exists and breaks it if its considered dead""" + """checks if `path` is deletable based on whether the lock file is expired""" if path.is_symlink(): return False lock = get_lock_path(path) - if not lock.exists(): - return True + try: + if not lock.is_file(): + return True + except OSError: + # we might not have access to the lock file at all, in this case assume + # we don't have access to the entire directory (#7491). + return False try: lock_time = lock.stat().st_mtime except Exception: diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index d9d3894f9..2c1a1c021 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -358,17 +358,25 @@ def test_get_extended_length_path_str(): def test_suppress_error_removing_lock(tmp_path): - """ensure_deletable should not raise an exception if the lock file cannot be removed (#5456)""" + """ensure_deletable should be resilient if lock file cannot be removed (#5456, #7491)""" path = tmp_path / "dir" path.mkdir() lock = get_lock_path(path) lock.touch() mtime = lock.stat().st_mtime - with unittest.mock.patch.object(Path, "unlink", side_effect=OSError): + with unittest.mock.patch.object(Path, "unlink", side_effect=OSError) as m: assert not ensure_deletable( path, consider_lock_dead_if_created_before=mtime + 30 ) + assert m.call_count == 1 + assert lock.is_file() + + with unittest.mock.patch.object(Path, "is_file", side_effect=OSError) as m: + assert not ensure_deletable( + path, consider_lock_dead_if_created_before=mtime + 30 + ) + assert m.call_count == 1 assert lock.is_file() # check now that we can remove the lock file in normal circumstances