Commits

Jason R. Coombs committed 59fb191 Draft

FileLock has been moved to the yg.locking package

  • Participants
  • Parent commits f469495
  • Branches default

Comments (0)

Files changed (4)

File eggmonster/concurrency.py

-#!/usr/bin/env python
-
-"""
-Cross-platform file lock context
-"""
-
-import os
-import time
-import functools
-
-import zc.lockfile
-
-class FileLockTimeout(Exception):
-    pass
-
-class FileLock(object):
-    """
-    A cross-platform locking file context.
-
-    May be used in a with statement to provide system-level concurrency
-    protection.
-
-    This class relies on zc.lockfile for the underlying locking.
-
-    This class is not threadsafe.
-    """
-
-    def __init__(self, lockfile, timeout=10, delay=.05):
-        """
-        Construct a FileLock. Specify the file to lock and optionally
-        the maximum timeout and the delay between each attempt to lock.
-        """
-        self.lockfile = lockfile
-        self.timeout = timeout
-        self.delay = delay
-
-    def acquire(self):
-        """
-        Attempt to acquire the lock every `delay` seconds until the
-        lock is acquired or until `timeout` has expired.
-
-        Raises FileLockTimeout if the timeout is exceeded.
-
-        Errors opening the lock file (other than if it exists) are
-        passed through.
-        """
-        start_time = time.time()
-        attempt = functools.partial(zc.lockfile.LockFile, self.lockfile)
-        while True:
-            try:
-                self.lock = attempt()
-                break
-            except zc.lockfile.LockError:
-                timeout_expired = time.time()-start_time >= self.timeout
-                if timeout_expired:
-                    raise FileLockTimeout()
-                time.sleep(self.delay)
-
-    def is_locked(self):
-        return hasattr(self, 'lock')
-
-    def release(self):
-        """
-        Release the lock and delete the lockfile.
-        """
-        if self.is_locked():
-            self.lock.close()
-            del self.lock
-            os.remove(self.lockfile)
-
-    def __enter__(self):
-        """
-        Acquire the lock unless we already have it.
-        """
-        if not self.is_locked():
-            self.acquire()
-        return self
-
-    def __exit__(self, type, value, traceback):
-        self.release()
-
-    def __del__(self):
-        """
-        Release the lock on destruction.
-        """
-        self.release()

File eggmonster/packages.py

 
 from setuptools.command import easy_install
 import pkg_resources
+from yg.locking import FileLock
 
-from .concurrency import FileLock
 from . import emenv
 
 InstallLock = functools.partial(FileLock,

File eggmonster/test/test_concurrency.py

-import os
-import subprocess
-import itertools
-import tempfile
-import time
-import sys
-
-import py.test
-
-from eggmonster.concurrency import FileLock, FileLockTimeout
-
-def test_FileLock_basic():
-    tfile, filename = tempfile.mkstemp()
-    os.close(tfile)
-    os.remove(filename)
-    l = FileLock(filename)
-    l2 = FileLock(filename, timeout=0.2)
-    assert not l.is_locked()
-    l.acquire()
-    assert l.is_locked()
-    l.release()
-    assert not l.is_locked()
-    with l:
-        assert os.path.isfile(filename)
-        py.test.raises(FileLockTimeout, l2.acquire)
-    assert not l.is_locked()
-    l2.acquire()
-    assert l2.is_locked()
-    l2.release()
-
-def lines(stream):
-    """
-    I can't figure out how to get the subprocess module to feed me
-    line-buffered output from a sub-process, so I grab the output byte
-    by byte and assemble it into lines.
-    """
-    buf = ''
-    while True:
-        dat = stream.read(1)
-        if dat:
-            buf += dat
-            if dat == '\n':
-                yield buf
-                buf = ''
-        if not dat and buf:
-            yield buf
-        if not dat:
-            break
-
-def test_FileLock_process_killed():
-    """
-    If a subprocess fails to release the lock, it should be released
-    and available for another process to take it.
-    """
-    tfile, filename = tempfile.mkstemp()
-    os.close(tfile)
-    os.remove(filename)
-    cmd = [sys.executable, '-u', '-c', 'from eggmonster.concurrency '
-        'import FileLock; import time; l = FileLock(%(filename)r); '
-        'l.acquire(); print "acquired", l.lockfile; '
-        '[time.sleep(1) for x in xrange(10)]' % vars()]
-    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
-    out = itertools.takewhile(lambda l: 'acquired' not in l,
-        lines(proc.stdout))
-    tuple(out) # wait for 'acquired' to be printed by subprocess
-
-    l = FileLock(filename, timeout=0.2)
-    py.test.raises(FileLockTimeout, l.acquire)
-    proc.kill()
-    time.sleep(.5)
-    l.acquire(); l.release()
     packages=setuptools.find_packages(),
     install_requires=[
         "PyYAML >= 3.0.9",
-        "zc.lockfile==1.0",
+        "yg.locking",
         ] + py26_reqs,
     extras_require=dict(
         server = [