summaryrefslogtreecommitdiffstats
path: root/external_libs/python/lockfile-0.10.2/lockfile/__init__.py
diff options
context:
space:
mode:
authorDan Klein <danklei@cisco.com>2015-08-24 10:51:13 +0300
committerDan Klein <danklei@cisco.com>2015-08-24 10:51:13 +0300
commitd3f26ece7d4383df0b22fe9c3cb3e695381ec737 (patch)
treeba42ddb547d363e92b1846df8a8712433981ddac /external_libs/python/lockfile-0.10.2/lockfile/__init__.py
parent651a7d779551e193bd9dbadbe8b2a02bdab231b4 (diff)
Initial push to external_lib migration
Diffstat (limited to 'external_libs/python/lockfile-0.10.2/lockfile/__init__.py')
-rw-r--r--external_libs/python/lockfile-0.10.2/lockfile/__init__.py326
1 files changed, 326 insertions, 0 deletions
diff --git a/external_libs/python/lockfile-0.10.2/lockfile/__init__.py b/external_libs/python/lockfile-0.10.2/lockfile/__init__.py
new file mode 100644
index 00000000..d905af96
--- /dev/null
+++ b/external_libs/python/lockfile-0.10.2/lockfile/__init__.py
@@ -0,0 +1,326 @@
+"""
+lockfile.py - Platform-independent advisory file locks.
+
+Requires Python 2.5 unless you apply 2.4.diff
+Locking is done on a per-thread basis instead of a per-process basis.
+
+Usage:
+
+>>> lock = LockFile('somefile')
+>>> try:
+... lock.acquire()
+... except AlreadyLocked:
+... print 'somefile', 'is locked already.'
+... except LockFailed:
+... print 'somefile', 'can\\'t be locked.'
+... else:
+... print 'got lock'
+got lock
+>>> print lock.is_locked()
+True
+>>> lock.release()
+
+>>> lock = LockFile('somefile')
+>>> print lock.is_locked()
+False
+>>> with lock:
+... print lock.is_locked()
+True
+>>> print lock.is_locked()
+False
+
+>>> lock = LockFile('somefile')
+>>> # It is okay to lock twice from the same thread...
+>>> with lock:
+... lock.acquire()
+...
+>>> # Though no counter is kept, so you can't unlock multiple times...
+>>> print lock.is_locked()
+False
+
+Exceptions:
+
+ Error - base class for other exceptions
+ LockError - base class for all locking exceptions
+ AlreadyLocked - Another thread or process already holds the lock
+ LockFailed - Lock failed for some other reason
+ UnlockError - base class for all unlocking exceptions
+ AlreadyUnlocked - File was not locked.
+ NotMyLock - File was locked but not by the current thread/process
+"""
+
+from __future__ import absolute_import
+
+import sys
+import socket
+import os
+import threading
+import time
+import urllib
+import warnings
+import functools
+
+# Work with PEP8 and non-PEP8 versions of threading module.
+if not hasattr(threading, "current_thread"):
+ threading.current_thread = threading.currentThread
+if not hasattr(threading.Thread, "get_name"):
+ threading.Thread.get_name = threading.Thread.getName
+
+__all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked',
+ 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock',
+ 'LinkLockFile', 'MkdirLockFile', 'SQLiteLockFile',
+ 'LockBase', 'locked']
+
+class Error(Exception):
+ """
+ Base class for other exceptions.
+
+ >>> try:
+ ... raise Error
+ ... except Exception:
+ ... pass
+ """
+ pass
+
+class LockError(Error):
+ """
+ Base class for error arising from attempts to acquire the lock.
+
+ >>> try:
+ ... raise LockError
+ ... except Error:
+ ... pass
+ """
+ pass
+
+class LockTimeout(LockError):
+ """Raised when lock creation fails within a user-defined period of time.
+
+ >>> try:
+ ... raise LockTimeout
+ ... except LockError:
+ ... pass
+ """
+ pass
+
+class AlreadyLocked(LockError):
+ """Some other thread/process is locking the file.
+
+ >>> try:
+ ... raise AlreadyLocked
+ ... except LockError:
+ ... pass
+ """
+ pass
+
+class LockFailed(LockError):
+ """Lock file creation failed for some other reason.
+
+ >>> try:
+ ... raise LockFailed
+ ... except LockError:
+ ... pass
+ """
+ pass
+
+class UnlockError(Error):
+ """
+ Base class for errors arising from attempts to release the lock.
+
+ >>> try:
+ ... raise UnlockError
+ ... except Error:
+ ... pass
+ """
+ pass
+
+class NotLocked(UnlockError):
+ """Raised when an attempt is made to unlock an unlocked file.
+
+ >>> try:
+ ... raise NotLocked
+ ... except UnlockError:
+ ... pass
+ """
+ pass
+
+class NotMyLock(UnlockError):
+ """Raised when an attempt is made to unlock a file someone else locked.
+
+ >>> try:
+ ... raise NotMyLock
+ ... except UnlockError:
+ ... pass
+ """
+ pass
+
+class LockBase:
+ """Base class for platform-specific lock classes."""
+ def __init__(self, path, threaded=True, timeout=None):
+ """
+ >>> lock = LockBase('somefile')
+ >>> lock = LockBase('somefile', threaded=False)
+ """
+ self.path = path
+ self.lock_file = os.path.abspath(path) + ".lock"
+ self.hostname = socket.gethostname()
+ self.pid = os.getpid()
+ if threaded:
+ t = threading.current_thread()
+ # Thread objects in Python 2.4 and earlier do not have ident
+ # attrs. Worm around that.
+ ident = getattr(t, "ident", hash(t))
+ self.tname = "-%x" % (ident & 0xffffffff)
+ else:
+ self.tname = ""
+ dirname = os.path.dirname(self.lock_file)
+
+ # unique name is mostly about the current process, but must
+ # also contain the path -- otherwise, two adjacent locked
+ # files conflict (one file gets locked, creating lock-file and
+ # unique file, the other one gets locked, creating lock-file
+ # and overwriting the already existing lock-file, then one
+ # gets unlocked, deleting both lock-file and unique file,
+ # finally the last lock errors out upon releasing.
+ self.unique_name = os.path.join(dirname,
+ "%s%s.%s%s" % (self.hostname,
+ self.tname,
+ self.pid,
+ hash(self.path)))
+ self.timeout = timeout
+
+ def acquire(self, timeout=None):
+ """
+ Acquire the lock.
+
+ * If timeout is omitted (or None), wait forever trying to lock the
+ file.
+
+ * If timeout > 0, try to acquire the lock for that many seconds. If
+ the lock period expires and the file is still locked, raise
+ LockTimeout.
+
+ * If timeout <= 0, raise AlreadyLocked immediately if the file is
+ already locked.
+ """
+ raise NotImplemented("implement in subclass")
+
+ def release(self):
+ """
+ Release the lock.
+
+ If the file is not locked, raise NotLocked.
+ """
+ raise NotImplemented("implement in subclass")
+
+ def is_locked(self):
+ """
+ Tell whether or not the file is locked.
+ """
+ raise NotImplemented("implement in subclass")
+
+ def i_am_locking(self):
+ """
+ Return True if this object is locking the file.
+ """
+ raise NotImplemented("implement in subclass")
+
+ def break_lock(self):
+ """
+ Remove a lock. Useful if a locking thread failed to unlock.
+ """
+ raise NotImplemented("implement in subclass")
+
+ def __enter__(self):
+ """
+ Context manager support.
+ """
+ self.acquire()
+ return self
+
+ def __exit__(self, *_exc):
+ """
+ Context manager support.
+ """
+ self.release()
+
+ def __repr__(self):
+ return "<%s: %r -- %r>" % (self.__class__.__name__, self.unique_name,
+ self.path)
+
+def _fl_helper(cls, mod, *args, **kwds):
+ warnings.warn("Import from %s module instead of lockfile package" % mod,
+ DeprecationWarning, stacklevel=2)
+ # This is a bit funky, but it's only for awhile. The way the unit tests
+ # are constructed this function winds up as an unbound method, so it
+ # actually takes three args, not two. We want to toss out self.
+ if not isinstance(args[0], str):
+ # We are testing, avoid the first arg
+ args = args[1:]
+ if len(args) == 1 and not kwds:
+ kwds["threaded"] = True
+ return cls(*args, **kwds)
+
+def LinkFileLock(*args, **kwds):
+ """Factory function provided for backwards compatibility.
+
+ Do not use in new code. Instead, import LinkLockFile from the
+ lockfile.linklockfile module.
+ """
+ from . import linklockfile
+ return _fl_helper(linklockfile.LinkLockFile, "lockfile.linklockfile",
+ *args, **kwds)
+
+def MkdirFileLock(*args, **kwds):
+ """Factory function provided for backwards compatibility.
+
+ Do not use in new code. Instead, import MkdirLockFile from the
+ lockfile.mkdirlockfile module.
+ """
+ from . import mkdirlockfile
+ return _fl_helper(mkdirlockfile.MkdirLockFile, "lockfile.mkdirlockfile",
+ *args, **kwds)
+
+def SQLiteFileLock(*args, **kwds):
+ """Factory function provided for backwards compatibility.
+
+ Do not use in new code. Instead, import SQLiteLockFile from the
+ lockfile.mkdirlockfile module.
+ """
+ from . import sqlitelockfile
+ return _fl_helper(sqlitelockfile.SQLiteLockFile, "lockfile.sqlitelockfile",
+ *args, **kwds)
+
+def locked(path, timeout=None):
+ """Decorator which enables locks for decorated function.
+
+ Arguments:
+ - path: path for lockfile.
+ - timeout (optional): Timeout for acquiring lock.
+
+ Usage:
+ @locked('/var/run/myname', timeout=0)
+ def myname(...):
+ ...
+ """
+ def decor(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ lock = FileLock(path, timeout=timeout)
+ lock.acquire()
+ try:
+ return func(*args, **kwargs)
+ finally:
+ lock.release()
+ return wrapper
+ return decor
+
+if hasattr(os, "link"):
+ from . import linklockfile as _llf
+ LockFile = _llf.LinkLockFile
+else:
+ from . import mkdirlockfile as _mlf
+ LockFile = _mlf.MkdirLockFile
+
+FileLock = LockFile
+