Commits

Jason R. Coombs  committed 67befe0

Added timedelta support to FileLock parameters

  • Participants
  • Parent commits cadb4c8
  • Tags 1.1

Comments (0)

Files changed (3)

File yg/lockfile/__init__.py

 import os
 import time
 import functools
+import numbers
+import datetime
 
 import zc.lockfile
 
+from . import timing
+from .py26compat import total_seconds
+
 class FileLockTimeout(Exception):
     pass
 
         """
         Construct a FileLock. Specify the file to lock and optionally
         the maximum timeout and the delay between each attempt to lock.
+
+        Timeout and delay can be given in numeric seconds or as
+        `datetime.timedelta` objects.
         """
         self.lockfile = lockfile
+        if isinstance(timeout, numbers.Number):
+            timeout = datetime.timedelta(seconds=timeout)
+        if isinstance(delay, numbers.Number):
+            delay = datetime.timedelta(seconds=delay)
         self.timeout = timeout
         self.delay = delay
 
         Errors opening the lock file (other than if it exists) are
         passed through.
         """
-        start_time = time.time()
+        stopwatch = timing.Stopwatch()
         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
+                timeout_expired = stopwatch.split() >= self.timeout
                 if timeout_expired:
                     raise FileLockTimeout()
-                time.sleep(self.delay)
+                time.sleep(total_seconds(self.delay))
 
     def is_locked(self):
         return hasattr(self, 'lock')

File yg/lockfile/py26compat.py

+# copied from jaraco.compat:py26compat
+from __future__ import division
+
+def total_seconds(td):
+	"""
+	Python 2.7 adds a total_seconds method to timedelta objects.
+	See http://docs.python.org/library/datetime.html#datetime.timedelta.total_seconds
+	"""
+	try:
+		result = td.total_seconds()
+	except AttributeError:
+		result = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
+	return result

File yg/lockfile/timing.py

+# copied from jaraco.util.timing
+
+from __future__ import unicode_literals
+
+import datetime
+
+class Stopwatch(object):
+	"""
+	A simple stopwatch which starts automatically.
+
+	>>> w = Stopwatch()
+	>>> _1_sec = datetime.timedelta(seconds=1)
+	>>> w.split() < _1_sec
+	True
+	>>> import time
+	>>> time.sleep(1.0)
+	>>> w.split() >= _1_sec
+	True
+	>>> w.stop() >= _1_sec
+	True
+	>>> w.reset()
+	>>> w.start()
+	>>> w.split() < _1_sec
+	True
+	"""
+	def __init__(self):
+		self.reset()
+		self.start()
+
+	def reset(self):
+		self.elapsed = datetime.timedelta(0)
+		if hasattr(self, 'start_time'):
+			del self.start_time
+
+	def start(self):
+		self.start_time = datetime.datetime.now()
+
+	def stop(self):
+		stop_time = datetime.datetime.now()
+		self.elapsed += stop_time - self.start_time
+		del self.start_time
+		return self.elapsed
+
+	def split(self):
+		local_duration = datetime.datetime.now() - self.start_time
+		return self.elapsed + local_duration
+
+	# context manager support
+	__enter__ = start
+
+	def __exit__(self, exc_type, exc_value, traceback):
+		self.stop()