3 Pf$ @sdZddlmZddlZddlZddlZddlZddlZeedsJej e_ eej dsbej j ej _ dddd d d d d dddddg ZGdddeZGdddeZGdddeZGdd d eZGdd d eZGdd d eZGdd d eZGdd d eZGdddeZGdddeZddZd dZd!dZd"dZd(d#dZeed$rjd%d&l m!Z"e"j#Z$nd%d'l m%Z&e&j'Z$e$Z(dS))a 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 )absolute_importNcurrent_threadget_nameError LockError LockTimeout AlreadyLocked LockFailed UnlockError NotLocked NotMyLock LinkFileLock MkdirFileLockSQLiteFileLockLockBaselockedc@seZdZdZdS)rzw Base class for other exceptions. >>> try: ... raise Error ... except Exception: ... pass N)__name__ __module__ __qualname____doc__rr/usr/lib/python3.6/__init__.pyrJsc@seZdZdZdS)rz Base class for error arising from attempts to acquire the lock. >>> try: ... raise LockError ... except Error: ... pass N)rrrrrrrrrVsc@seZdZdZdS)rzRaised when lock creation fails within a user-defined period of time. >>> try: ... raise LockTimeout ... except LockError: ... pass N)rrrrrrrrrbsc@seZdZdZdS)rzSome other thread/process is locking the file. >>> try: ... raise AlreadyLocked ... except LockError: ... pass N)rrrrrrrrrmsc@seZdZdZdS)r zLock file creation failed for some other reason. >>> try: ... raise LockFailed ... except LockError: ... pass N)rrrrrrrrr xsc@seZdZdZdS)r z Base class for errors arising from attempts to release the lock. >>> try: ... raise UnlockError ... except Error: ... pass N)rrrrrrrrr sc@seZdZdZdS)r zRaised when an attempt is made to unlock an unlocked file. >>> try: ... raise NotLocked ... except UnlockError: ... pass N)rrrrrrrrr sc@seZdZdZdS)r zRaised when an attempt is made to unlock a file someone else locked. >>> try: ... raise NotMyLock ... except UnlockError: ... pass N)rrrrrrrrr sc@s>eZdZddZdddZddZdd Zd d Zd d ZdS) _SharedBasecCs ||_dS)N)path)selfrrrr__init__sz_SharedBase.__init__NcCs tddS)a 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. zimplement in subclassN)NotImplemented)rtimeoutrrracquiresz_SharedBase.acquirecCs tddS)zX Release the lock. If the file is not locked, raise NotLocked. zimplement in subclassN)r)rrrrreleasesz_SharedBase.releasecCs |j|S)z* Context manager support. )r)rrrr __enter__sz_SharedBase.__enter__cGs |jdS)z* Context manager support. N)r)rZ_excrrr__exit__sz_SharedBase.__exit__cCsd|jj|jfS)Nz<%s: %r>) __class__rr)rrrr__repr__sz_SharedBase.__repr__)N) rrrrrrr r!r#rrrrrs  rcsBeZdZdZdfdd ZddZdd Zd d Zd d ZZ S)rz.Base class for platform-specific lock classes.TNcstt|j|tjj|d|_tj|_ tj |_ |rbt j }t|dt|}d|d@|_nd|_tjj|j}tjj|d|j |j|j t|jf|_||_dS)zi >>> lock = LockBase('somefile') >>> lock = LockBase('somefile', threaded=False) z.lockidentz-%xlz %s%s.%s%sN)superrrosrabspathZ lock_filesocketZ gethostnameZhostnamegetpidpid threadingrgetattrhashZtnamedirnamejoin unique_namer)rrthreadedrtr$r/)r"rrrs    zLockBase.__init__cCs tddS)z9 Tell whether or not the file is locked. zimplement in subclassN)r)rrrr is_lockedszLockBase.is_lockedcCs tddS)zA Return True if this object is locking the file. zimplement in subclassN)r)rrrr i_am_lockingszLockBase.i_am_lockingcCs tddS)zN Remove a lock. Useful if a locking thread failed to unlock. zimplement in subclassN)r)rrrr break_lockszLockBase.break_lockcCsd|jj|j|jfS)Nz<%s: %r -- %r>)r"rr1r)rrrrr#s zLockBase.__repr__)TN) rrrrrr4r5r6r# __classcell__rr)r"rrs !cOsRtjd|tddt|dts.|dd}t|dkrH| rHd|d<|||S)Nz1Import from %s module instead of lockfile package) stacklevelrTr2)warningswarnDeprecationWarning isinstancestrlen)clsmodargskwdsrrr _fl_helper s   rEcOs ddlm}t|jdf||S)zFactory function provided for backwards compatibility. Do not use in new code. Instead, import LinkLockFile from the lockfile.linklockfile module. r:) linklockfilezlockfile.linklockfile)r%rFrE LinkLockFile)rCrDrFrrrr s  cOs ddlm}t|jdf||S)zFactory function provided for backwards compatibility. Do not use in new code. Instead, import MkdirLockFile from the lockfile.mkdirlockfile module. r:) mkdirlockfilezlockfile.mkdirlockfile)r%rHrE MkdirLockFile)rCrDrHrrrr%s  cOs ddlm}t|jdf||S)zFactory function provided for backwards compatibility. Do not use in new code. Instead, import SQLiteLockFile from the lockfile.mkdirlockfile module. r:)sqlitelockfilezlockfile.sqlitelockfile)r%rJrEZSQLiteLockFile)rCrDrJrrrr0s  csfdd}|S)aDecorator 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(...): ... cstjfdd}|S)Nc s.td}|jz ||S|jXdS)N)r)FileLockrr)rCkwargslock)funcrrrrwrapperHs   z&locked..decor..wrapper) functoolswraps)rNrO)rr)rNrdecorGszlocked..decorr)rrrRr)rrrr;s  linkr:)rF)rH)N))rZ __future__rrPr'r)r,r;hasattrZ currentThreadrZThreadZgetNamer__all__ Exceptionrrrrr r r r objectrrrEr rrrr%rFZ_llfrGZLockFilerHZ_mlfrIrKrrrr4sF            -: