_windows.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from __future__ import annotations
  2. import os
  3. import sys
  4. from contextlib import suppress
  5. from errno import EACCES
  6. from pathlib import Path
  7. from typing import cast
  8. from ._api import BaseFileLock
  9. from ._util import ensure_directory_exists, raise_on_not_writable_file
  10. if sys.platform == "win32": # pragma: win32 cover
  11. import msvcrt
  12. class WindowsFileLock(BaseFileLock):
  13. """Uses the :func:`msvcrt.locking` function to hard lock the lock file on Windows systems."""
  14. def _acquire(self) -> None:
  15. raise_on_not_writable_file(self.lock_file)
  16. ensure_directory_exists(self.lock_file)
  17. flags = (
  18. os.O_RDWR # open for read and write
  19. | os.O_CREAT # create file if not exists
  20. | os.O_TRUNC # truncate file if not empty
  21. )
  22. try:
  23. fd = os.open(self.lock_file, flags, self._context.mode)
  24. except OSError as exception:
  25. if exception.errno != EACCES: # has no access to this lock
  26. raise
  27. else:
  28. try:
  29. msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
  30. except OSError as exception:
  31. os.close(fd) # close file first
  32. if exception.errno != EACCES: # file is already locked
  33. raise
  34. else:
  35. self._context.lock_file_fd = fd
  36. def _release(self) -> None:
  37. fd = cast(int, self._context.lock_file_fd)
  38. self._context.lock_file_fd = None
  39. msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
  40. os.close(fd)
  41. with suppress(OSError): # Probably another instance of the application hat acquired the file lock.
  42. Path(self.lock_file).unlink()
  43. else: # pragma: win32 no cover
  44. class WindowsFileLock(BaseFileLock):
  45. """Uses the :func:`msvcrt.locking` function to hard lock the lock file on Windows systems."""
  46. def _acquire(self) -> None:
  47. raise NotImplementedError
  48. def _release(self) -> None:
  49. raise NotImplementedError
  50. __all__ = [
  51. "WindowsFileLock",
  52. ]