98
96
:ivar unlock: A callable which will unlock the lock.
101
def __init__(self, unlock, token=None):
99
def __init__(self, unlock):
102
100
self.unlock = unlock
105
102
def __repr__(self):
106
103
return "LogicalLockResult(%s)" % (self.unlock)
111
def __exit__(self, exc_type, exc_val, exc_tb):
112
# If there was an error raised, prefer the original one
115
except BaseException:
121
107
def cant_unlock_not_held(locked_object):
122
108
"""An attempt to unlock failed because the object was not locked.
124
This provides a policy point from which we can generate either a warning or
110
This provides a policy point from which we can generate either a warning
127
113
# This is typically masking some other error and called from a finally
128
114
# block, so it's useful to have the option not to generate a new error
344
340
self._read_lock = None
347
344
_lock_classes.append(('fcntl', _fcntl_WriteLock, _fcntl_ReadLock))
347
if have_pywin32 and sys.platform == 'win32':
348
win32file_CreateFile = win32file.CreateFileW
350
class _w32c_FileLock(_OSLock):
352
def _open(self, filename, access, share, cflags, pymode):
353
self.filename = osutils.realpath(filename)
355
self._handle = win32file_CreateFile(filename, access, share,
356
None, win32file.OPEN_ALWAYS,
357
win32file.FILE_ATTRIBUTE_NORMAL, None)
358
except pywintypes.error as e:
359
if e.args[0] == winerror.ERROR_ACCESS_DENIED:
360
raise errors.LockFailed(filename, e)
361
if e.args[0] == winerror.ERROR_SHARING_VIOLATION:
362
raise errors.LockContention(filename, e)
364
fd = win32file._open_osfhandle(self._handle, cflags)
365
self.f = os.fdopen(fd, pymode)
373
class _w32c_ReadLock(_w32c_FileLock):
374
def __init__(self, filename):
375
super(_w32c_ReadLock, self).__init__()
376
self._open(filename, win32file.GENERIC_READ,
377
win32file.FILE_SHARE_READ, os.O_RDONLY, "rb")
379
def temporary_write_lock(self):
380
"""Try to grab a write lock on the file.
382
On platforms that support it, this will upgrade to a write lock
383
without unlocking the file.
384
Otherwise, this will release the read lock, and try to acquire a
387
:return: A token which can be used to switch back to a read lock.
389
# I can't find a way to upgrade a read lock to a write lock without
390
# unlocking first. So here, we do just that.
393
wlock = _w32c_WriteLock(self.filename)
394
except errors.LockError:
395
return False, _w32c_ReadLock(self.filename)
399
class _w32c_WriteLock(_w32c_FileLock):
400
def __init__(self, filename):
401
super(_w32c_WriteLock, self).__init__()
403
win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
406
def restore_read_lock(self):
407
"""Restore the original ReadLock."""
408
# For win32 we had to completely let go of the original lock, so we
409
# just unlock and create a new read lock.
411
return _w32c_ReadLock(self.filename)
414
_lock_classes.append(('pywin32', _w32c_WriteLock, _w32c_ReadLock))
350
417
if have_ctypes_win32:
351
from ctypes.wintypes import DWORD, LPWSTR
352
LPSECURITY_ATTRIBUTES = ctypes.c_void_p # used as NULL no need to declare
353
HANDLE = ctypes.c_int # rather than unsigned as in ctypes.wintypes
418
from ctypes.wintypes import DWORD, LPCSTR, LPCWSTR
419
LPSECURITY_ATTRIBUTES = ctypes.c_void_p # used as NULL no need to declare
420
HANDLE = ctypes.c_int # rather than unsigned as in ctypes.wintypes
354
421
_function_name = "CreateFileW"
356
423
# CreateFile <http://msdn.microsoft.com/en-us/library/aa363858.aspx>
357
424
_CreateFile = ctypes.WINFUNCTYPE(
358
HANDLE, # return value
360
DWORD, # dwDesiredAccess
362
LPSECURITY_ATTRIBUTES, # lpSecurityAttributes
363
DWORD, # dwCreationDisposition
364
DWORD, # dwFlagsAndAttributes
365
HANDLE # hTemplateFile
425
HANDLE, # return value
427
DWORD, # dwDesiredAccess
429
LPSECURITY_ATTRIBUTES, # lpSecurityAttributes
430
DWORD, # dwCreationDisposition
431
DWORD, # dwFlagsAndAttributes
432
HANDLE # hTemplateFile
366
433
)((_function_name, ctypes.windll.kernel32))
368
435
INVALID_HANDLE_VALUE = -1
381
448
def _open(self, filename, access, share, cflags, pymode):
382
449
self.filename = osutils.realpath(filename)
383
450
handle = _CreateFile(filename, access, share, None, OPEN_ALWAYS,
384
FILE_ATTRIBUTE_NORMAL, 0)
451
FILE_ATTRIBUTE_NORMAL, 0)
385
452
if handle in (INVALID_HANDLE_VALUE, 0):
386
453
e = ctypes.WinError()
387
454
if e.args[0] == ERROR_ACCESS_DENIED: