Force remove a path by killing processes that have it locked. Args: path: Path to remove (file or directory) max_retries: Maximum number of retry attempts Returns: True if path was successfully removed
(path: Path, max_retries: int = 3)
| 209 | |
| 210 | |
| 211 | def force_remove_path(path: Path, max_retries: int = 3) -> bool: |
| 212 | """Force remove a path by killing processes that have it locked. |
| 213 | |
| 214 | Args: |
| 215 | path: Path to remove (file or directory) |
| 216 | max_retries: Maximum number of retry attempts |
| 217 | |
| 218 | Returns: |
| 219 | True if path was successfully removed |
| 220 | """ |
| 221 | import shutil |
| 222 | |
| 223 | if not path.exists(): |
| 224 | return True |
| 225 | |
| 226 | print(f"Attempting to remove locked path: {path}") |
| 227 | |
| 228 | for attempt in range(max_retries): |
| 229 | try: |
| 230 | # Try to remove directly first |
| 231 | if path.is_dir(): |
| 232 | shutil.rmtree(path) |
| 233 | else: |
| 234 | path.unlink() |
| 235 | |
| 236 | print(f"✓ Successfully removed: {path}") |
| 237 | return True |
| 238 | |
| 239 | except (OSError, PermissionError) as e: |
| 240 | print(f"Attempt {attempt + 1}/{max_retries}: Failed to remove {path}: {e}") |
| 241 | |
| 242 | if attempt < max_retries - 1: |
| 243 | # Find and kill locking processes |
| 244 | print(" Searching for processes locking the path...") |
| 245 | locking_pids = find_processes_locking_path(path) |
| 246 | |
| 247 | if locking_pids: |
| 248 | print(f" Found {len(locking_pids)} process(es) locking the path") |
| 249 | kill_processes(locking_pids, force=True) |
| 250 | else: |
| 251 | print(" No locking processes found") |
| 252 | |
| 253 | # On Windows, try using system commands as fallback |
| 254 | if platform.system() == "Windows": |
| 255 | print(" Trying Windows-specific removal...") |
| 256 | try: |
| 257 | if path.is_dir(): |
| 258 | result = subprocess.run( |
| 259 | ["cmd", "/c", "rmdir", "/S", "/Q", str(path)], |
| 260 | capture_output=True, |
| 261 | text=True, |
| 262 | timeout=30, |
| 263 | ) |
| 264 | else: |
| 265 | result = subprocess.run( |
| 266 | ["cmd", "/c", "del", "/F", "/Q", str(path)], |
| 267 | capture_output=True, |
| 268 | text=True, |
no test coverage detected