Commit 9012188f authored by SVN-Git Migration's avatar SVN-Git Migration

Imported Upstream version 0.4~ds0

parent 8159a6ee
from portalocker import * from portalocker import lock, unlock, LOCK_EX, LOCK_SH, LOCK_NB, LockException
from utils import * from utils import Lock, AlreadyLocked
__all__ = [
'lock',
'unlock',
'LOCK_EX',
'LOCK_SH',
'LOCK_NB',
'LockException',
'Lock',
'AlreadyLocked',
]
...@@ -61,16 +61,17 @@ __all__ = [ ...@@ -61,16 +61,17 @@ __all__ = [
import os import os
class LockException(Exception): class LockException(Exception):
# Error codes: # Error codes:
LOCK_FAILED = 1 LOCK_FAILED = 1
if os.name == 'nt': if os.name == 'nt': # pragma: no cover
import win32con import win32con
import win32file import win32file
import pywintypes import pywintypes
LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
LOCK_SH = 0 # the default LOCK_SH = 0 # the default
LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
# is there any reason not to reuse the following structure? # is there any reason not to reuse the following structure?
__overlapped = pywintypes.OVERLAPPED() __overlapped = pywintypes.OVERLAPPED()
...@@ -79,50 +80,64 @@ elif os.name == 'posix': ...@@ -79,50 +80,64 @@ elif os.name == 'posix':
LOCK_EX = fcntl.LOCK_EX LOCK_EX = fcntl.LOCK_EX
LOCK_SH = fcntl.LOCK_SH LOCK_SH = fcntl.LOCK_SH
LOCK_NB = fcntl.LOCK_NB LOCK_NB = fcntl.LOCK_NB
else: else: # pragma: no cover
raise RuntimeError, 'PortaLocker only defined for nt and posix platforms' raise RuntimeError('PortaLocker only defined for nt and posix platforms')
if os.name == 'nt':
def lock(file, flags): def nt_lock(file, flags): # pragma: no cover
hfile = win32file._get_osfhandle(file.fileno()) hfile = win32file._get_osfhandle(file.fileno())
try: try:
win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped) win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped)
except pywintypes.error, exc_value: except pywintypes.error, exc_value:
# error: (33, 'LockFileEx', 'The process cannot access the file because another process has locked a portion of the file.') # error: (33, 'LockFileEx', 'The process cannot access the file
if exc_value[0] == 33: # because another process has locked a portion of the file.')
raise LockException(LockException.LOCK_FAILED, exc_value[2]) if exc_value[0] == 33:
else: raise LockException(LockException.LOCK_FAILED, exc_value[2])
# Q: Are there exceptions/codes we should be dealing with here? else:
raise # Q: Are there exceptions/codes we should be dealing with
# here?
def unlock(file): raise
hfile = win32file._get_osfhandle(file.fileno())
try:
win32file.UnlockFileEx(hfile, 0, -0x10000, __overlapped) def nt_unlock(file): # pragma: no cover
except pywintypes.error, exc_value: hfile = win32file._get_osfhandle(file.fileno())
if exc_value[0] == 158: try:
# error: (158, 'UnlockFileEx', 'The segment is already unlocked.') win32file.UnlockFileEx(hfile, 0, -0x10000, __overlapped)
# To match the 'posix' implementation, silently ignore this error except pywintypes.error, exc_value:
pass if exc_value[0] == 158:
else: # error: (158, 'UnlockFileEx', 'The segment is already '
# Q: Are there exceptions/codes we should be dealing with here? # 'unlocked.')
raise # 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, 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': elif os.name == 'posix':
def lock(file, flags): lock = posix_lock
try: unlock = posix_unlock
fcntl.flock(file.fileno(), flags) else: # pragma: no cover
except IOError, exc_value: raise RuntimeError('Your os %r is unsupported.' % os.name)
# The exception code varies on different systems so we'll catch
# every IO error
raise LockException(*exc_value)
def unlock(file):
fcntl.flock(file.fileno(), fcntl.LOCK_UN)
if __name__ == '__main__': if __name__ == '__main__': # pragma: no cover
from time import time, strftime, localtime from time import time, strftime, localtime
import sys import sys
import portalocker import portalocker
...@@ -131,7 +146,7 @@ if __name__ == '__main__': ...@@ -131,7 +146,7 @@ if __name__ == '__main__':
portalocker.lock(log, portalocker.LOCK_EX) portalocker.lock(log, portalocker.LOCK_EX)
timestamp = strftime('%m/%d/%Y %H:%M:%S\n', localtime(time())) timestamp = strftime('%m/%d/%Y %H:%M:%S\n', localtime(time()))
log.write( timestamp ) log.write(timestamp)
print 'Wrote lines. Hit enter to release lock.' print 'Wrote lines. Hit enter to release lock.'
dummy = sys.stdin.readline() dummy = sys.stdin.readline()
......
...@@ -11,21 +11,18 @@ __all__ = [ ...@@ -11,21 +11,18 @@ __all__ = [
'AlreadyLocked', 'AlreadyLocked',
] ]
class AlreadyLocked(Exception): class AlreadyLocked(Exception):
pass pass
class Lock(object): class Lock(object):
def __init__( def __init__(
self, self, filename, mode='a', truncate=0, timeout=DEFAULT_TIMEOUT,
filename, check_interval=DEFAULT_CHECK_INTERVAL, fail_when_locked=True):
mode='a',
truncate=0,
timeout=DEFAULT_TIMEOUT,
check_interval=DEFAULT_CHECK_INTERVAL,
fail_when_locked=True,
):
'''Lock manager with build-in timeout '''Lock manager with build-in timeout
filename -- filename filename -- filename
mode -- the open mode, 'a' or 'ab' should be used for writing 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 -- use truncate to emulate 'w' mode, None is disabled, 0 is
...@@ -34,7 +31,7 @@ class Lock(object): ...@@ -34,7 +31,7 @@ class Lock(object):
check_interval -- check interval while waiting check_interval -- check interval while waiting
fail_when_locked -- after the initial lock failed, return an error fail_when_locked -- after the initial lock failed, return an error
or lock the file or lock the file
fail_when_locked is useful when multiple threads/processes can race 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 when creating a file. If set to true than the system will wait till
the lock was acquired and then return an AlreadyLocked exception. the lock was acquired and then return an AlreadyLocked exception.
...@@ -53,7 +50,8 @@ class Lock(object): ...@@ -53,7 +50,8 @@ class Lock(object):
assert 'w' not in mode, 'Mode "w" clears the file before locking' assert 'w' not in mode, 'Mode "w" clears the file before locking'
def acquire(self, timeout=None, check_interval=None, fail_when_locked=None): def acquire(
self, timeout=None, check_interval=None, fail_when_locked=None):
'''Acquire the locked filehandle''' '''Acquire the locked filehandle'''
if timeout is None: if timeout is None:
timeout = self.timeout timeout = self.timeout
...@@ -83,15 +81,17 @@ class Lock(object): ...@@ -83,15 +81,17 @@ class Lock(object):
# Try again # Try again
try: try:
fh = self._get_lock(fh)
# We've got the lock, now return an error if # We already tried to the get the lock
# fail_when_locked is True or break if not # If fail_when_locked is true, then stop trying
if fail_when_locked: if fail_when_locked:
self._release_lock()
raise AlreadyLocked(*exception) raise AlreadyLocked(*exception)
else:
else: # pragma: no cover
# We've got the lock
fh = self._get_lock(fh)
break break
except portalocker.LockException: except portalocker.LockException:
pass pass
...@@ -112,7 +112,7 @@ class Lock(object): ...@@ -112,7 +112,7 @@ class Lock(object):
def _get_lock(self, fh): def _get_lock(self, fh):
''' '''
Try to lock the given filehandle Try to lock the given filehandle
returns LockException if it fails''' returns LockException if it fails'''
portalocker.lock(fh, LOCK_METHOD) portalocker.lock(fh, LOCK_METHOD)
return fh return fh
...@@ -140,4 +140,3 @@ class Lock(object): ...@@ -140,4 +140,3 @@ class Lock(object):
def __exit__(self, type, value, tb): def __exit__(self, type, value, tb):
if self.fh: if self.fh:
self.fh.close() self.fh.close()
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand
import sys import sys
author = 'Rick van Hattem'
email = 'Rick.van.Hattem@Fawo.nl'
version = '0.4'
desc = '''Wraps the portalocker recipe for easy usage'''
extra = {} extra = {}
if sys.version_info >= (3, 0): if sys.version_info >= (3, 0):
extra.update(use_2to3=True) extra.update(use_2to3=True)
try:
from setuptools import setup, find_packages
except ImportError:
from distutils.core import setup, find_packages
author = 'Rick van Hattem' class PyTest(TestCommand):
email = 'Rick.van.Hattem@Fawo.nl' def finalize_options(self):
version = '0.3' TestCommand.finalize_options(self)
desc = '''Wraps the portalocker recipe for easy usage''' self.test_args = ['tests']
self.test_suite = True
setup(name='portalocker', def run_tests(self):
version=version, #import here, cause outside the eggs aren't loaded
description=desc, import pytest
long_description=open('README.rest').read(), errno = pytest.main(self.test_args)
classifiers=[ sys.exit(errno)
'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='https://github.com/WoLpH/portalocker',
license='PSF',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
zip_safe=False,
platforms=['any'],
test_suite='nose.collector',
**extra
)
setup(
name='portalocker',
version=version,
description=desc,
long_description=open('README.rest').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='https://github.com/WoLpH/portalocker',
license='PSF',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
zip_safe=False,
platforms=['any'],
cmdclass={'test': PyTest},
**extra
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment