1   
  2   
  3   
  4   
  5   
  6   
  7  """ 
  8  Cross-platform (posix/nt) API for flock-style file locking. 
  9   
 10  Synopsis: 
 11   
 12     import portalocker 
 13     file = open(\"somefile\", \"r+\") 
 14     portalocker.lock(file, portalocker.LOCK_EX) 
 15     file.seek(12) 
 16     file.write(\"foo\") 
 17     file.close() 
 18   
 19  If you know what you're doing, you may choose to 
 20   
 21     portalocker.unlock(file) 
 22   
 23  before closing the file, but why? 
 24   
 25  Methods: 
 26   
 27     lock( file, flags ) 
 28     unlock( file ) 
 29   
 30  Constants: 
 31   
 32     LOCK_EX 
 33     LOCK_SH 
 34     LOCK_NB 
 35   
 36  I learned the win32 technique for locking files from sample code 
 37  provided by John Nielsen <nielsenjf@my-deja.com> in the documentation 
 38  that accompanies the win32 modules. 
 39   
 40  Author: Jonathan Feinberg <jdf@pobox.com> 
 41  Version: $Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp $ 
 42  """ 
 43   
 44  import logging 
 45  import platform 
 46  logger = logging.getLogger("web2py") 
 47   
 48  os_locking = None 
 49  try: 
 50      import google.appengine 
 51      os_locking = 'gae' 
 52  except: 
 53      try: 
 54          import fcntl 
 55          os_locking = 'posix' 
 56      except: 
 57          try: 
 58              import win32con 
 59              import win32file 
 60              import pywintypes 
 61              os_locking = 'windows' 
 62          except: 
 63              pass 
 64   
 65  if os_locking == 'windows': 
 66      LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK 
 67      LOCK_SH = 0   
 68      LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY 
 69   
 70       
 71   
 72      __overlapped = pywintypes.OVERLAPPED() 
 73   
 74 -    def lock(file, flags): 
  75          hfile = win32file._get_osfhandle(file.fileno()) 
 76          win32file.LockFileEx(hfile, flags, 0, 0x7fff0000, __overlapped) 
  77   
 79          hfile = win32file._get_osfhandle(file.fileno()) 
 80          win32file.UnlockFileEx(hfile, 0, 0x7fff0000, __overlapped) 
  81   
 82   
 83  elif os_locking == 'posix': 
 84      LOCK_EX = fcntl.LOCK_EX 
 85      LOCK_SH = fcntl.LOCK_SH 
 86      LOCK_NB = fcntl.LOCK_NB 
 87   
 88 -    def lock(file, flags): 
  89          fcntl.flock(file.fileno(), flags) 
  90   
 92          fcntl.flock(file.fileno(), fcntl.LOCK_UN) 
  93   
 94   
 95  else: 
 96      if platform.system() == 'Windows': 
 97          logger.error('no file locking, you must install the win32 extensions from: http://sourceforge.net/projects/pywin32/files/') 
 98      elif os_locking != 'gae': 
 99          logger.debug('no file locking, this will cause problems') 
100   
101      LOCK_EX = None 
102      LOCK_SH = None 
103      LOCK_NB = None 
104   
105 -    def lock(file, flags): 
 107   
110   
111   
113 -    def __init__(self, filename, mode='rb'): 
 114          self.filename = filename 
115          self.mode = mode 
116          self.file = None 
117          if 'r' in mode: 
118              self.file = open(filename, mode) 
119              lock(self.file, LOCK_SH) 
120          elif 'w' in mode or 'a' in mode: 
121              self.file = open(filename, mode.replace('w', 'a')) 
122              lock(self.file, LOCK_EX) 
123              if not 'a' in mode: 
124                  self.file.seek(0) 
125                  self.file.truncate() 
126          else: 
127              raise RuntimeError("invalid LockedFile(...,mode)") 
 128   
129 -    def read(self, size=None): 
 131   
134   
137   
141   
143          if not self.file is None: 
144              unlock(self.file) 
145              self.file.close() 
146              self.file = None 
 147   
149          if not self.file is None: 
150              self.close()