Check if `path` is deletable based on whether the lock file is expired.
(path: Path, consider_lock_dead_if_created_before: float)
| 290 | |
| 291 | |
| 292 | def ensure_deletable(path: Path, consider_lock_dead_if_created_before: float) -> bool: |
| 293 | """Check if `path` is deletable based on whether the lock file is expired.""" |
| 294 | if path.is_symlink(): |
| 295 | return False |
| 296 | lock = get_lock_path(path) |
| 297 | try: |
| 298 | if not lock.is_file(): |
| 299 | return True |
| 300 | except OSError: |
| 301 | # we might not have access to the lock file at all, in this case assume |
| 302 | # we don't have access to the entire directory (#7491). |
| 303 | return False |
| 304 | try: |
| 305 | lock_time = lock.stat().st_mtime |
| 306 | except Exception: |
| 307 | return False |
| 308 | else: |
| 309 | if lock_time < consider_lock_dead_if_created_before: |
| 310 | # We want to ignore any errors while trying to remove the lock such as: |
| 311 | # - PermissionDenied, like the file permissions have changed since the lock creation; |
| 312 | # - FileNotFoundError, in case another pytest process got here first; |
| 313 | # and any other cause of failure. |
| 314 | with contextlib.suppress(OSError): |
| 315 | lock.unlink() |
| 316 | return True |
| 317 | return False |
| 318 | |
| 319 | |
| 320 | def try_cleanup(path: Path, consider_lock_dead_if_created_before: float) -> None: |