Check if `path` is deletable based on whether the lock file is expired.
(path: Path, consider_lock_dead_if_created_before: float)
| 305 | |
| 306 | |
| 307 | def ensure_deletable(path: Path, consider_lock_dead_if_created_before: float) -> bool: |
| 308 | """Check if `path` is deletable based on whether the lock file is expired.""" |
| 309 | if path.is_symlink(): |
| 310 | return False |
| 311 | lock = get_lock_path(path) |
| 312 | try: |
| 313 | if not lock.is_file(): |
| 314 | return True |
| 315 | except OSError: |
| 316 | # we might not have access to the lock file at all, in this case assume |
| 317 | # we don't have access to the entire directory (#7491). |
| 318 | return False |
| 319 | try: |
| 320 | lock_time = lock.stat().st_mtime |
| 321 | except Exception: |
| 322 | return False |
| 323 | else: |
| 324 | if lock_time < consider_lock_dead_if_created_before: |
| 325 | # We want to ignore any errors while trying to remove the lock such as: |
| 326 | # - PermissionDenied, like the file permissions have changed since the lock creation; |
| 327 | # - FileNotFoundError, in case another pytest process got here first; |
| 328 | # and any other cause of failure. |
| 329 | with contextlib.suppress(OSError): |
| 330 | lock.unlink() |
| 331 | return True |
| 332 | return False |
| 333 | |
| 334 | |
| 335 | def try_cleanup(path: Path, consider_lock_dead_if_created_before: float) -> None: |