Commits

imbolc  committed 78d248b

init

  • Participants

Comments (0)

Files changed (6)

+syntax: glob
+*.pyc
+*.swp
+*.egg-info/
+dist/
+update_pypi.sh
+Copyright (c) 2011 Imbolc.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+include README.rst LICENSE
+single_access
+=============
+
+Single access to run python script.
+
+Installation
+------------
+::
+
+    $ pip install single_access
+
+Usage
+-----
+::
+
+    from single_access import single_access, lock
+
+    @single_access
+    def main():
+        # try to lock this script file
+        ...
+
+or ::
+
+    @single_access(filename='/tmp/single_access_test.loc')
+    def main():
+        ...
+
+or ::
+
+    def main():
+        if not lock('/tmp/single_access_test.loc'):
+            return
+        ...
+
+Repository
+----------
+
+https://bitbucket.org/imbolc/single_access
+#!/usr/bin/env python
+from setuptools import setup
+import single_access
+
+setup(
+    name='single_access',
+    version=single_access.__version__,
+    description='Single access to run python script',
+    long_description=open('README.rst').read(),
+    author='Imbolc',
+    author_email='imbolc@imbolc.name',
+    url='https://bitbucket.org/imbolc/single_access',
+    packages= ['single_access'],
+    install_requires=[],
+    license='ISC',
+    classifiers=(
+        'Development Status :: 4 - Beta',
+        'Intended Audience :: Developers',
+        'Natural Language :: English',
+        'License :: OSI Approved :: ISC License (ISCL)',
+        'Programming Language :: Python',
+    ),
+)

File single_access/__init__.py

+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+__version__ = '0.0.1'
+
+import os
+import sys
+import fcntl
+
+
+def lock(filename):
+    '''
+    Open file in 'r+' mode and lock it.
+    Return file handler or None
+    '''
+    if not hasattr(lock, '_files'):
+        lock._files = {}
+    try:
+        if not os.path.isfile(filename):
+            open(filename, 'w').close()
+        f = open(filename, 'r+')
+        fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
+    except IOError, ex:
+        if ex[0] != 11:
+            raise
+        return None
+    lock._files[filename] = f
+    return file
+
+def single_access(func=None, filename=None):
+    '''
+    Decorator for single run access.
+    Usage:
+        @single_access
+        def main():
+            ...
+
+        @single_access(filename='/tmp/single_access_test.lock)
+        def main():
+            ...
+    '''
+    def _function_filename(func):
+        filename = sys.modules[func.__module__].__file__
+        filename = os.path.abspath(filename)
+        return filename
+
+    def decorator(func):
+        lock_filename = filename or _function_filename(func)
+        def wrapper(*args, **kwargs):
+            if lock(lock_filename):
+                return func(*args, **kwargs)
+            sys.stderr.write('Can\'t lock file: %s\n' % lock_filename)
+        return wrapper
+
+    if func:
+        return decorator(func)
+    else:
+        return decorator