--- /dev/null
+# -*- coding: utf-8 -*-\r
+# https://github.com/dmfrey/FileLock\r
+\r
+import os\r
+import time\r
+import errno\r
+\r
+class FileLockException(Exception):\r
+ pass\r
+\r
+class FileLock:\r
+ """ A file locking mechanism that has context-manager support so\r
+ you can use it in a with statement. This should be relatively cross\r
+ compatible as it doesn't rely on msvcrt or fcntl for the locking.\r
+ """\r
+\r
+ def __init__(self, file_name, timeout=10, delay=.05):\r
+ """ Prepare the file locker. Specify the file to lock and optionally\r
+ the maximum timeout and the delay between each attempt to lock.\r
+ """\r
+ self.is_locked = False\r
+ self.lockfile = os.path.join(os.getcwd(), "%s.lock" % file_name)\r
+ self.file_name = file_name\r
+ self.timeout = timeout\r
+ self.delay = delay\r
+\r
+\r
+ def acquire(self):\r
+ """ Acquire the lock, if possible. If the lock is in use, it check again\r
+ every `wait` seconds. It does this until it either gets the lock or\r
+ exceeds `timeout` number of seconds, in which case it throws\r
+ an exception.\r
+ """\r
+ start_time = time.time()\r
+ while True:\r
+ try:\r
+ self.fd = os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR)\r
+ break;\r
+ except OSError as e:\r
+ if e.errno != errno.EEXIST:\r
+ raise\r
+ if (time.time() - start_time) >= self.timeout:\r
+ raise FileLockException("Timeout occured.")\r
+ time.sleep(self.delay)\r
+ self.is_locked = True\r
+\r
+\r
+ def release(self):\r
+ """ Get rid of the lock by deleting the lockfile.\r
+ When working in a `with` statement, this gets automatically\r
+ called at the end.\r
+ """\r
+ if self.is_locked:\r
+ os.close(self.fd)\r
+ os.unlink(self.lockfile)\r
+ self.is_locked = False\r
+\r
+\r
+ def __enter__(self):\r
+ """ Activated when used in the with statement.\r
+ Should automatically acquire a lock to be used in the with block.\r
+ """\r
+ if not self.is_locked:\r
+ self.acquire()\r
+ return self\r
+\r
+\r
+ def __exit__(self, type, value, traceback):\r
+ """ Activated at the end of the with statement.\r
+ It automatically releases the lock if it isn't locked.\r
+ """\r
+ if self.is_locked:\r
+ self.release()\r
+\r
+\r
+ def __del__(self):\r
+ """ Make sure that the FileLock instance doesn't leave a lockfile\r
+ lying around.\r
+ """\r
+ self.release()\r