Skip to content

Commit ceea364

Browse files
committed
use tempfile.TemporaryDirectory to cleanup garbage- dir
Python has a very nice rm_rf hidden in tempfile.TemporaryDirectory._rmtree we can use it to cleanup our "garbage-" dir https://github.com/python/cpython/blob/3d43f1dce3e9aaded38f9a2c73e3c66acf85505c/Lib/tempfile.py#L784-L812
1 parent 096d096 commit ceea364

File tree

3 files changed

+26
-6
lines changed

3 files changed

+26
-6
lines changed

changelog/8940.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed an issue where dirs without S_IXUSR prevented pytest from cleaning up the temp dir

src/_pytest/pathlib.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import os
77
import shutil
88
import sys
9-
import uuid
9+
import tempfile
1010
import warnings
1111
from enum import Enum
1212
from functools import partial
@@ -254,11 +254,10 @@ def maybe_delete_a_numbered_dir(path: Path) -> None:
254254
lock_path = None
255255
try:
256256
lock_path = create_cleanup_lock(path)
257-
parent = path.parent
258-
259-
garbage = parent.joinpath(f"garbage-{uuid.uuid4()}")
260-
path.rename(garbage)
261-
rm_rf(garbage)
257+
with tempfile.TemporaryDirectory(
258+
prefix="garbage-", dir=path.parent
259+
) as garbage:
260+
path.replace(garbage)
262261
except OSError:
263262
# known races:
264263
# * other process did a cleanup at the same time

testing/test_pathlib.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,26 @@ def test_long_path_during_cleanup(tmp_path):
351351
assert not os.path.isdir(extended_path)
352352

353353

354+
def test_permission_denied_during_cleanup(tmp_path):
355+
"""
356+
Ensure that deleting a numbered dir does not fail because of missing file
357+
permission bits (#7940).
358+
"""
359+
path = tmp_path / "temp-1"
360+
p = path / "ham" / "spam" / "eggs"
361+
p.parent.mkdir(parents=True)
362+
p.touch(mode=0)
363+
for p in p.parents:
364+
if p == path:
365+
break
366+
p.chmod(mode=0)
367+
368+
lock_path = get_lock_path(path)
369+
maybe_delete_a_numbered_dir(path)
370+
assert not path.exists()
371+
assert not lock_path.is_file()
372+
373+
354374
def test_get_extended_length_path_str():
355375
assert get_extended_length_path_str(r"c:\foo") == r"\\?\c:\foo"
356376
assert get_extended_length_path_str(r"\\share\foo") == r"\\?\UNC\share\foo"

0 commit comments

Comments
 (0)