portalocker-0.5.5/0000755000076500000240000000000012640764025014127 5ustar rickstaff00000000000000portalocker-0.5.5/CHANGELOG0000644000076500000240000000106112327733504015337 0ustar rickstaff000000000000000.1: * Initial release 0.2: * Added `Lock` class to help prevent cache race conditions 0.3: * Now actually returning the file descriptor from the `Lock` class 0.4: * Fixing a few bugs, added coveralls support, switched to py.test and added 100% test coverage. - Fixing exception thrown when fail_when_locked is true - Fixing exception "Lock object has no attribute '_release_lock'" when fail_when_locked is true due to the call to Lock._release_lock() which fails because _release_lock is not defined. 0.5: * Python 3 support portalocker-0.5.5/LICENSE0000644000076500000240000000456312327732301015136 0ustar rickstaff00000000000000PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python. 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement. portalocker-0.5.5/MANIFEST.in0000644000076500000240000000006612327732301015661 0ustar rickstaff00000000000000include CHANGELOG include README.rest include LICENSE portalocker-0.5.5/PKG-INFO0000644000076500000240000000674712640764025015242 0ustar rickstaff00000000000000Metadata-Version: 1.1 Name: portalocker Version: 0.5.5 Summary: Wraps the portalocker recipe for easy usage Home-page: https://github.com/WoLpH/portalocker Author: Rick van Hattem Author-email: wolph@wol.ph License: PSF Description: ############################################ portalocker - Cross-platform locking library ############################################ .. image:: https://travis-ci.org/WoLpH/portalocker.svg?branch=master :alt: Test Status :target: https://travis-ci.org/WoLpH/portalocker .. image:: https://coveralls.io/repos/WoLpH/portalocker/badge.svg?branch=master :alt: Coverage Status :target: https://coveralls.io/r/WoLpH/portalocker?branch=master .. image:: https://landscape.io/github/WoLpH/portalocker/master/landscape.png :target: https://landscape.io/github/WoLpH/portalocker/master :alt: Code Health Overview -------- Portalocker is a library to provide an easy API to file locking. Originally created as a Python Recipe by Jonathan Feinberg and Lowell Alleman http://code.activestate.com/recipes/65203-portalocker-cross-platform-posixnt-api-for-flock-s/ The module is currently maintained by Rick van Hattem . The project resides at https://github.com/WoLpH/portalocker . Bugs and feature requests can be submitted there. Patches are also very welcome. Links ----- * Documentation - http://portalocker.readthedocs.org/en/latest/ * Source - https://github.com/WoLpH/portalocker * Bug reports - https://github.com/WoLpH/portalocker/issues * Package homepage - https://pypi.python.org/pypi/portalocker * My blog - http://w.wol.ph/ Examples -------- To make sure your cache generation scripts don't race, use the `Lock` class: >>> import portalocker >>> with portalocker.Lock('somefile', timeout=1) as fh: print >>fh, 'writing some stuff to my cache...' To customize the opening and locking a manual approach is also possible: >>> import portalocker >>> file = open('somefile', 'r+') >>> portalocker.lock(file, portalocker.LOCK_EX) >>> file.seek(12) >>> file.write('foo') >>> file.close() There is no explicit need to unlock the file as it is automatically unlocked after `file.close()`. If you still feel the need to manually unlock a file than you can do it like this: >>> portalocker.unlock(file) Do note that your data might still be in a buffer so it is possible that your data is not available until you `flush()` or `close()`. Changelog --------- See CHANGELOG file License ------- see the LICENSE file Keywords: locking,locks,with statement,windows,linux,unix Platform: any Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.1 portalocker-0.5.5/portalocker/0000755000076500000240000000000012640764025016454 5ustar rickstaff00000000000000portalocker-0.5.5/portalocker/__init__.py0000644000076500000240000000040412433134126020554 0ustar rickstaff00000000000000from .portalocker import lock, unlock, LOCK_EX, LOCK_SH, LOCK_NB, LockException from .utils import Lock, AlreadyLocked __all__ = [ 'lock', 'unlock', 'LOCK_EX', 'LOCK_SH', 'LOCK_NB', 'LockException', 'Lock', 'AlreadyLocked', ] portalocker-0.5.5/portalocker/portalocker.py0000644000076500000240000000715112614612652021356 0ustar rickstaff00000000000000# portalocker.py - Cross-platform (posix/nt) API for flock-style file locking. # Requires python 1.5.2 or better. '''Cross-platform (posix/nt) API for flock-style file locking. Synopsis: import portalocker file = open('somefile', 'r+') portalocker.lock(file, portalocker.LOCK_EX) file.seek(12) file.write('foo') file.close() If you know what you're doing, you may choose to portalocker.unlock(file) before closing the file, but why? Methods: lock( file, flags ) unlock( file ) Constants: LOCK_EX LOCK_SH LOCK_NB Exceptions: LockException Notes: For the 'nt' platform, this module requires the Python Extensions for Windows. Be aware that this may not work as expected on Windows 95/98/ME. History: I learned the win32 technique for locking files from sample code provided by John Nielsen in the documentation that accompanies the win32 modules. Author: Jonathan Feinberg , Lowell Alleman Version: $Id: portalocker.py 5474 2008-05-16 20:53:50Z lowell $ ''' __all__ = [ 'lock', 'unlock', 'LOCK_EX', 'LOCK_SH', 'LOCK_NB', 'LockException', ] import os class LockException(Exception): # Error codes: LOCK_FAILED = 1 if os.name == 'nt': # pragma: no cover import win32con import win32file import pywintypes import winerror LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK LOCK_SH = 0 # the default LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY # is there any reason not to reuse the following structure? __overlapped = pywintypes.OVERLAPPED() elif os.name == 'posix': import fcntl LOCK_EX = fcntl.LOCK_EX LOCK_SH = fcntl.LOCK_SH LOCK_NB = fcntl.LOCK_NB else: # pragma: no cover raise RuntimeError('PortaLocker only defined for nt and posix platforms') def nt_lock(file_, flags): # pragma: no cover hfile = win32file._get_osfhandle(file_.fileno()) try: win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped) except pywintypes.error as exc_value: # error: (33, 'LockFileEx', 'The process cannot access the file # because another process has locked a portion of the file.') if exc_value.winerror == winerror.ERROR_LOCK_VIOLATION: raise LockException(LockException.LOCK_FAILED, exc_value.strerror) else: # Q: Are there exceptions/codes we should be dealing with # here? raise def nt_unlock(file_): # pragma: no cover hfile = win32file._get_osfhandle(file_.fileno()) try: win32file.UnlockFileEx(hfile, 0, -0x10000, __overlapped) except pywintypes.error as exc_value: if exc_value.winerror == winerror.ERROR_NOT_LOCKED: # error: (158, 'UnlockFileEx', 'The segment is already ' # 'unlocked.') # To match the 'posix' implementation, silently ignore this # error pass else: # Q: Are there exceptions/codes we should be dealing with # here? raise def posix_lock(file_, flags): try: fcntl.flock(file_.fileno(), flags) except IOError as exc_value: # The exception code varies on different systems so we'll catch # every IO error raise LockException(exc_value) def posix_unlock(file_): fcntl.flock(file_.fileno(), fcntl.LOCK_UN) if os.name == 'nt': # pragma: no cover lock = nt_lock unlock = nt_unlock elif os.name == 'posix': lock = posix_lock unlock = posix_unlock else: # pragma: no cover raise RuntimeError('Your os %r is unsupported.' % os.name) portalocker-0.5.5/portalocker/utils.py0000644000076500000240000001015312640763562020173 0ustar rickstaff00000000000000 import time from . import portalocker DEFAULT_TIMEOUT = 5 DEFAULT_CHECK_INTERVAL = 0.25 LOCK_METHOD = portalocker.LOCK_EX | portalocker.LOCK_NB __all__ = [ 'Lock', 'AlreadyLocked', ] class AlreadyLocked(Exception): pass class Lock(object): def __init__( self, filename, mode='a', truncate=0, timeout=DEFAULT_TIMEOUT, check_interval=DEFAULT_CHECK_INTERVAL, fail_when_locked=True, flags=LOCK_METHOD): '''Lock manager with build-in timeout filename -- filename mode -- the open mode, 'a' or 'ab' should be used for writing truncate -- use truncate to emulate 'w' mode, None is disabled, 0 is truncate to 0 bytes timeout -- timeout when trying to acquire a lock check_interval -- check interval while waiting fail_when_locked -- after the initial lock failed, return an error or lock the file fail_when_locked is useful when multiple threads/processes can race when creating a file. If set to true than the system will wait till the lock was acquired and then return an AlreadyLocked exception. Note that the file is opened first and locked later. So using 'w' as mode will result in truncate _BEFORE_ the lock is checked. ''' self.fh = None self.filename = filename self.mode = mode self.truncate = truncate self.timeout = timeout self.check_interval = check_interval self.fail_when_locked = fail_when_locked self.flags = flags assert 'w' not in mode, 'Mode "w" clears the file before locking' def acquire( self, timeout=None, check_interval=None, fail_when_locked=None): '''Acquire the locked filehandle''' if timeout is None: timeout = self.timeout if timeout is None: timeout = 0 if check_interval is None: check_interval = self.check_interval if fail_when_locked is None: fail_when_locked = self.fail_when_locked # If we already have a filehandle, return it fh = self.fh if fh: return fh # Get a new filehandler fh = self._get_fh() try: # Try to lock fh = self._get_lock(fh) except portalocker.LockException as exception: # Try till the timeout is 0 while timeout > 0: # Wait a bit time.sleep(check_interval) timeout -= check_interval # Try again try: # We already tried to the get the lock # If fail_when_locked is true, then stop trying if fail_when_locked: raise AlreadyLocked(exception) else: # pragma: no cover # We've got the lock fh = self._get_lock(fh) break except portalocker.LockException: pass else: # We got a timeout... reraising raise portalocker.LockException(exception) # Prepare the filehandle (truncate if needed) fh = self._prepare_fh(fh) self.fh = fh return fh def _get_fh(self): '''Get a new filehandle''' return open(self.filename, self.mode) def _get_lock(self, fh): ''' Try to lock the given filehandle returns LockException if it fails''' portalocker.lock(fh, self.flags) return fh def _prepare_fh(self, fh, truncate=None): ''' Prepare the filehandle for usage If truncate is a number, the file will be truncated to that amount of bytes ''' if truncate is None: truncate = self.truncate if truncate is not None: fh.seek(truncate) fh.truncate(truncate) return fh def __enter__(self): self.fh = self.acquire() return self.fh def __exit__(self, type_, value, tb): if self.fh: self.fh.close() portalocker-0.5.5/portalocker.egg-info/0000755000076500000240000000000012640764025020146 5ustar rickstaff00000000000000portalocker-0.5.5/portalocker.egg-info/dependency_links.txt0000644000076500000240000000000112640764025024214 0ustar rickstaff00000000000000 portalocker-0.5.5/portalocker.egg-info/not-zip-safe0000644000076500000240000000000112433356431022372 0ustar rickstaff00000000000000 portalocker-0.5.5/portalocker.egg-info/pbr.json0000644000076500000240000000005712540330667021626 0ustar rickstaff00000000000000{"is_release": false, "git_version": "12a1dc5"}portalocker-0.5.5/portalocker.egg-info/PKG-INFO0000644000076500000240000000674712640764025021261 0ustar rickstaff00000000000000Metadata-Version: 1.1 Name: portalocker Version: 0.5.5 Summary: Wraps the portalocker recipe for easy usage Home-page: https://github.com/WoLpH/portalocker Author: Rick van Hattem Author-email: wolph@wol.ph License: PSF Description: ############################################ portalocker - Cross-platform locking library ############################################ .. image:: https://travis-ci.org/WoLpH/portalocker.svg?branch=master :alt: Test Status :target: https://travis-ci.org/WoLpH/portalocker .. image:: https://coveralls.io/repos/WoLpH/portalocker/badge.svg?branch=master :alt: Coverage Status :target: https://coveralls.io/r/WoLpH/portalocker?branch=master .. image:: https://landscape.io/github/WoLpH/portalocker/master/landscape.png :target: https://landscape.io/github/WoLpH/portalocker/master :alt: Code Health Overview -------- Portalocker is a library to provide an easy API to file locking. Originally created as a Python Recipe by Jonathan Feinberg and Lowell Alleman http://code.activestate.com/recipes/65203-portalocker-cross-platform-posixnt-api-for-flock-s/ The module is currently maintained by Rick van Hattem . The project resides at https://github.com/WoLpH/portalocker . Bugs and feature requests can be submitted there. Patches are also very welcome. Links ----- * Documentation - http://portalocker.readthedocs.org/en/latest/ * Source - https://github.com/WoLpH/portalocker * Bug reports - https://github.com/WoLpH/portalocker/issues * Package homepage - https://pypi.python.org/pypi/portalocker * My blog - http://w.wol.ph/ Examples -------- To make sure your cache generation scripts don't race, use the `Lock` class: >>> import portalocker >>> with portalocker.Lock('somefile', timeout=1) as fh: print >>fh, 'writing some stuff to my cache...' To customize the opening and locking a manual approach is also possible: >>> import portalocker >>> file = open('somefile', 'r+') >>> portalocker.lock(file, portalocker.LOCK_EX) >>> file.seek(12) >>> file.write('foo') >>> file.close() There is no explicit need to unlock the file as it is automatically unlocked after `file.close()`. If you still feel the need to manually unlock a file than you can do it like this: >>> portalocker.unlock(file) Do note that your data might still be in a buffer so it is possible that your data is not available until you `flush()` or `close()`. Changelog --------- See CHANGELOG file License ------- see the LICENSE file Keywords: locking,locks,with statement,windows,linux,unix Platform: any Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.1 portalocker-0.5.5/portalocker.egg-info/SOURCES.txt0000644000076500000240000000051712640764025022035 0ustar rickstaff00000000000000CHANGELOG LICENSE MANIFEST.in README.rst setup.cfg setup.py portalocker/__init__.py portalocker/portalocker.py portalocker/utils.py portalocker.egg-info/PKG-INFO portalocker.egg-info/SOURCES.txt portalocker.egg-info/dependency_links.txt portalocker.egg-info/not-zip-safe portalocker.egg-info/pbr.json portalocker.egg-info/top_level.txtportalocker-0.5.5/portalocker.egg-info/top_level.txt0000644000076500000240000000001412640764025022673 0ustar rickstaff00000000000000portalocker portalocker-0.5.5/README.rst0000644000076500000240000000435612640763775015641 0ustar rickstaff00000000000000############################################ portalocker - Cross-platform locking library ############################################ .. image:: https://travis-ci.org/WoLpH/portalocker.svg?branch=master :alt: Test Status :target: https://travis-ci.org/WoLpH/portalocker .. image:: https://coveralls.io/repos/WoLpH/portalocker/badge.svg?branch=master :alt: Coverage Status :target: https://coveralls.io/r/WoLpH/portalocker?branch=master .. image:: https://landscape.io/github/WoLpH/portalocker/master/landscape.png :target: https://landscape.io/github/WoLpH/portalocker/master :alt: Code Health Overview -------- Portalocker is a library to provide an easy API to file locking. Originally created as a Python Recipe by Jonathan Feinberg and Lowell Alleman http://code.activestate.com/recipes/65203-portalocker-cross-platform-posixnt-api-for-flock-s/ The module is currently maintained by Rick van Hattem . The project resides at https://github.com/WoLpH/portalocker . Bugs and feature requests can be submitted there. Patches are also very welcome. Links ----- * Documentation - http://portalocker.readthedocs.org/en/latest/ * Source - https://github.com/WoLpH/portalocker * Bug reports - https://github.com/WoLpH/portalocker/issues * Package homepage - https://pypi.python.org/pypi/portalocker * My blog - http://w.wol.ph/ Examples -------- To make sure your cache generation scripts don't race, use the `Lock` class: >>> import portalocker >>> with portalocker.Lock('somefile', timeout=1) as fh: print >>fh, 'writing some stuff to my cache...' To customize the opening and locking a manual approach is also possible: >>> import portalocker >>> file = open('somefile', 'r+') >>> portalocker.lock(file, portalocker.LOCK_EX) >>> file.seek(12) >>> file.write('foo') >>> file.close() There is no explicit need to unlock the file as it is automatically unlocked after `file.close()`. If you still feel the need to manually unlock a file than you can do it like this: >>> portalocker.unlock(file) Do note that your data might still be in a buffer so it is possible that your data is not available until you `flush()` or `close()`. Changelog --------- See CHANGELOG file License ------- see the LICENSE file portalocker-0.5.5/setup.cfg0000644000076500000240000000033512640764025015751 0ustar rickstaff00000000000000[metadata] description-file = README.rst [build_sphinx] source-dir = docs/ build-dir = docs/_build all_files = 1 [upload_sphinx] upload-dir = docs/_build/html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 portalocker-0.5.5/setup.py0000644000076500000240000000323012640763603015640 0ustar rickstaff00000000000000import sys import setuptools from setuptools.command.test import test as TestCommand __package_name__ = 'portalocker' __author__ = 'Rick van Hattem' __email__ = 'wolph@wol.ph' __version__ = '0.5.5' __description__ = '''Wraps the portalocker recipe for easy usage''' __url__ = 'https://github.com/WoLpH/portalocker' extra = {} if sys.version_info >= (3, 0): extra.update(use_2to3=True) class PyTest(TestCommand): def finalize_options(self): TestCommand.finalize_options(self) self.test_args = ['tests'] self.test_suite = True def run_tests(self): # import here, cause outside the eggs aren't loaded import pytest errno = pytest.main(self.test_args) sys.exit(errno) if __name__ == '__main__': setuptools.setup( name=__package_name__, version=__version__, description=__description__, long_description=open('README.rst').read(), classifiers=[ 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.1', ], keywords='locking, locks, with statement, windows, linux, unix', author=__author__, author_email=__email__, url=__url__, license='PSF', packages=setuptools.find_packages(exclude=['ez_setup', 'examples']), zip_safe=False, platforms=['any'], cmdclass={'test': PyTest}, **extra )