13
13
class LockError(Exception):
16
class WindowsExclFile(object):
18
def __init__(self, path, timeout=20):
26
self._handle = w.CreateFile(path,
27
w.GENERIC_READ|w.GENERIC_WRITE, # Open for reading and writing
29
None, # No security attributes
30
w.OPEN_ALWAYS, # If file does not exist, create it
31
w.FILE_ATTRIBUTE_NORMAL, #Normal attributes
32
None, #No template file
35
except pywintypes.error, err:
36
if getattr(err, 'args', [-1])[0] in (0x20, 0x21):
42
def seek(self, amt, frm=0):
44
if frm not in (0, 1, 2):
45
raise ValueError('Invalid from for seek: %s'%frm)
46
frm = {0:w.FILE_BEGIN, 1: w.FILE_CURRENT, 2:w.FILE_END}[frm]
49
w.SetFilePointer(self._handle, amt, frm)
53
return w.SetFilePointer(self._handle, 0, w.FILE_CURRENT)
57
w.FlushFileBuffers(self._handle)
60
if self._handle is not None:
63
w.CloseHandle(self._handle)
66
def read(self, bytes=-1):
68
sz = w.GetFileSize(self._handle)
69
max = sz - self.tell()
70
if bytes < 0: bytes = max
71
bytes = min(max, bytes)
74
hr, ans = w.ReadFile(self._handle, bytes, None)
76
raise IOError('Error reading file: %s'%hr)
79
def readlines(self, sizehint=-1):
80
return self.read().splitlines()
82
def write(self, bytes):
83
if isinstance(bytes, unicode):
84
bytes = bytes.encode('utf-8')
86
w.WriteFile(self._handle, bytes, None)
88
def truncate(self, size=None):
95
w.SetEndOfFile(self._handle)
103
return self._handle is None
16
106
class ExclusiveFile(object):
18
def __init__(self, path, timeout=10):
108
def __init__(self, path, timeout=15):
20
110
self.timeout = timeout
22
112
def __enter__(self):
23
self.file = open(self.path, 'a+b')
113
self.file = WindowsExclFile(self.path, self.timeout) if iswindows else open(self.path, 'a+b')
25
115
timeout = self.timeout
27
name = ('Local\\'+(__appname__+self.file.name).replace('\\', '_'))[:201]
28
while self.timeout < 0 or timeout >= 0:
29
self.mutex = win32event.CreateMutex(None, False, name)
30
if win32api.GetLastError() != winerror.ERROR_ALREADY_EXISTS: break
34
117
while self.timeout < 0 or timeout >= 0:
36
119
fcntl.lockf(self.file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)