Skip to content

Commit d380771

Browse files
authored
Fix tmp_path regression introduced in 7.3.0 (#10911)
The problem is that we would loop over all directories of the basetemp directory searching for dead symlinks, for each test, which would compound over the test session run. Doing the cleanup just once, at the end of the session, fixes the problem. Fix #10896
1 parent b893d2a commit d380771

File tree

3 files changed

+13
-13
lines changed

3 files changed

+13
-13
lines changed

changelog/10896.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed performance regression related to :fixture:`tmp_path` and the new :confval:`tmp_path_retention_policy` option.

src/_pytest/pathlib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ def cleanup_candidates(root: Path, prefix: str, keep: int) -> Iterator[Path]:
353353
yield path
354354

355355

356-
def cleanup_dead_symlink(root: Path):
356+
def cleanup_dead_symlinks(root: Path):
357357
for left_dir in root.iterdir():
358358
if left_dir.is_symlink():
359359
if not left_dir.resolve().exists():
@@ -371,7 +371,7 @@ def cleanup_numbered_dir(
371371
for path in root.glob("garbage-*"):
372372
try_cleanup(path, consider_lock_dead_if_created_before)
373373

374-
cleanup_dead_symlink(root)
374+
cleanup_dead_symlinks(root)
375375

376376

377377
def make_numbered_dir_with_cleanup(

src/_pytest/tmpdir.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from .pathlib import make_numbered_dir
2929
from .pathlib import make_numbered_dir_with_cleanup
3030
from .pathlib import rm_rf
31-
from .pathlib import cleanup_dead_symlink
31+
from .pathlib import cleanup_dead_symlinks
3232
from _pytest.compat import final, get_user_id
3333
from _pytest.config import Config
3434
from _pytest.config import ExitCode
@@ -289,31 +289,30 @@ def tmp_path(
289289

290290
del request.node.stash[tmppath_result_key]
291291

292-
# remove dead symlink
293-
basetemp = tmp_path_factory._basetemp
294-
if basetemp is None:
295-
return
296-
cleanup_dead_symlink(basetemp)
297-
298292

299293
def pytest_sessionfinish(session, exitstatus: Union[int, ExitCode]):
300294
"""After each session, remove base directory if all the tests passed,
301295
the policy is "failed", and the basetemp is not specified by a user.
302296
"""
303297
tmp_path_factory: TempPathFactory = session.config._tmp_path_factory
304-
if tmp_path_factory._basetemp is None:
298+
basetemp = tmp_path_factory._basetemp
299+
if basetemp is None:
305300
return
301+
306302
policy = tmp_path_factory._retention_policy
307303
if (
308304
exitstatus == 0
309305
and policy == "failed"
310306
and tmp_path_factory._given_basetemp is None
311307
):
312-
passed_dir = tmp_path_factory._basetemp
313-
if passed_dir.exists():
308+
if basetemp.is_dir():
314309
# We do a "best effort" to remove files, but it might not be possible due to some leaked resource,
315310
# permissions, etc, in which case we ignore it.
316-
rmtree(passed_dir, ignore_errors=True)
311+
rmtree(basetemp, ignore_errors=True)
312+
313+
# Remove dead symlinks.
314+
if basetemp.is_dir():
315+
cleanup_dead_symlinks(basetemp)
317316

318317

319318
@hookimpl(tryfirst=True, hookwrapper=True)

0 commit comments

Comments
 (0)