Skip to content

Commit 4a37779

Browse files
committed
Improve temp_file fixture cleanup on Windows
Enhances the temp_file pytest fixture to handle delayed file handle release on Windows by retrying file deletion with a short delay. This prevents test failures due to locked files and provides more robust cleanup across platforms.
1 parent 5bc7949 commit 4a37779

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

tests/tools/file_editor/conftest.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import os
2+
import sys
13
import tempfile
4+
import time
25
from pathlib import Path
36

47
import pytest
@@ -14,11 +17,28 @@
1417
def temp_file():
1518
"""Create a temporary file for testing."""
1619
with tempfile.NamedTemporaryFile(delete=False) as f:
17-
yield Path(f.name)
18-
try:
19-
Path(f.name).unlink()
20-
except FileNotFoundError:
21-
pass
20+
file_path = Path(f.name)
21+
yield file_path
22+
# On Windows, files may be locked briefly after handles are closed.
23+
# This is due to Windows file system behavior where file handles may not be
24+
# immediately released, opportunistic locks (oplocks), or background processes
25+
# like File Explorer holding handles. See:
26+
# - https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-opbatch-ack-close-pending
27+
# - https://learn.microsoft.com/en-us/answers/questions/5559106/file-explorer-is-opening-files-and-folders-prevent
28+
# Retry deletion with a small delay if it fails
29+
max_retries = 5 if sys.platform == "win32" else 1
30+
for attempt in range(max_retries):
31+
try:
32+
if file_path.exists():
33+
file_path.unlink()
34+
break
35+
except (FileNotFoundError, PermissionError):
36+
if attempt < max_retries - 1:
37+
time.sleep(0.1) # Small delay before retry
38+
elif attempt == max_retries - 1:
39+
# Last attempt failed, but don't fail the test
40+
# The file will be cleaned up by the OS eventually
41+
pass
2242

2343

2444
@pytest.fixture

0 commit comments

Comments
 (0)