Index: third_party/twisted_8_1/twisted/internet/task.py |
diff --git a/third_party/twisted_8_1/twisted/internet/task.py b/third_party/twisted_8_1/twisted/internet/task.py |
deleted file mode 100644 |
index 526d555c4a0ea2ecbc7c5527f8ff3f1c7bef30ca..0000000000000000000000000000000000000000 |
--- a/third_party/twisted_8_1/twisted/internet/task.py |
+++ /dev/null |
@@ -1,420 +0,0 @@ |
-# -*- test-case-name: twisted.test.test_task -*- |
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories. |
-# See LICENSE for details. |
- |
-""" |
-Scheduling utility methods and classes. |
- |
-@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>} |
-""" |
- |
-__metaclass__ = type |
- |
-import time |
- |
-from zope.interface import implements |
- |
-from twisted.python import reflect |
- |
-from twisted.internet import base, defer |
-from twisted.internet.interfaces import IReactorTime |
- |
- |
-class LoopingCall: |
- """Call a function repeatedly. |
- |
- If C{f} returns a deferred, rescheduling will not take place until the |
- deferred has fired. The result value is ignored. |
- |
- @ivar f: The function to call. |
- @ivar a: A tuple of arguments to pass the function. |
- @ivar kw: A dictionary of keyword arguments to pass to the function. |
- @ivar clock: A provider of |
- L{twisted.internet.interfaces.IReactorTime}. The default is |
- L{twisted.internet.reactor}. Feel free to set this to |
- something else, but it probably ought to be set *before* |
- calling L{start}. |
- |
- @type _lastTime: C{float} |
- @ivar _lastTime: The time at which this instance most recently scheduled |
- itself to run. |
- """ |
- |
- call = None |
- running = False |
- deferred = None |
- interval = None |
- _lastTime = 0.0 |
- starttime = None |
- |
- def __init__(self, f, *a, **kw): |
- self.f = f |
- self.a = a |
- self.kw = kw |
- from twisted.internet import reactor |
- self.clock = reactor |
- |
- |
- def start(self, interval, now=True): |
- """Start running function every interval seconds. |
- |
- @param interval: The number of seconds between calls. May be |
- less than one. Precision will depend on the underlying |
- platform, the available hardware, and the load on the system. |
- |
- @param now: If True, run this call right now. Otherwise, wait |
- until the interval has elapsed before beginning. |
- |
- @return: A Deferred whose callback will be invoked with |
- C{self} when C{self.stop} is called, or whose errback will be |
- invoked when the function raises an exception or returned a |
- deferred that has its errback invoked. |
- """ |
- assert not self.running, ("Tried to start an already running " |
- "LoopingCall.") |
- if interval < 0: |
- raise ValueError, "interval must be >= 0" |
- self.running = True |
- d = self.deferred = defer.Deferred() |
- self.starttime = self.clock.seconds() |
- self._lastTime = self.starttime |
- self.interval = interval |
- if now: |
- self() |
- else: |
- self._reschedule() |
- return d |
- |
- def stop(self): |
- """Stop running function. |
- """ |
- assert self.running, ("Tried to stop a LoopingCall that was " |
- "not running.") |
- self.running = False |
- if self.call is not None: |
- self.call.cancel() |
- self.call = None |
- d, self.deferred = self.deferred, None |
- d.callback(self) |
- |
- def __call__(self): |
- def cb(result): |
- if self.running: |
- self._reschedule() |
- else: |
- d, self.deferred = self.deferred, None |
- d.callback(self) |
- |
- def eb(failure): |
- self.running = False |
- d, self.deferred = self.deferred, None |
- d.errback(failure) |
- |
- self.call = None |
- d = defer.maybeDeferred(self.f, *self.a, **self.kw) |
- d.addCallback(cb) |
- d.addErrback(eb) |
- |
- |
- def _reschedule(self): |
- """ |
- Schedule the next iteration of this looping call. |
- """ |
- if self.interval == 0: |
- self.call = self.clock.callLater(0, self) |
- return |
- |
- currentTime = self.clock.seconds() |
- # Find how long is left until the interval comes around again. |
- untilNextTime = (self._lastTime - currentTime) % self.interval |
- # Make sure it is in the future, in case more than one interval worth |
- # of time passed since the previous call was made. |
- nextTime = max( |
- self._lastTime + self.interval, currentTime + untilNextTime) |
- # If the interval falls on the current time exactly, skip it and |
- # schedule the call for the next interval. |
- if nextTime == currentTime: |
- nextTime += self.interval |
- self._lastTime = nextTime |
- self.call = self.clock.callLater(nextTime - currentTime, self) |
- |
- |
- def __repr__(self): |
- if hasattr(self.f, 'func_name'): |
- func = self.f.func_name |
- if hasattr(self.f, 'im_class'): |
- func = self.f.im_class.__name__ + '.' + func |
- else: |
- func = reflect.safe_repr(self.f) |
- |
- return 'LoopingCall<%r>(%s, *%s, **%s)' % ( |
- self.interval, func, reflect.safe_repr(self.a), |
- reflect.safe_repr(self.kw)) |
- |
- |
- |
-class SchedulerStopped(Exception): |
- """ |
- The operation could not complete because the scheduler was stopped in |
- progress or was already stopped. |
- """ |
- |
- |
- |
-class _Timer(object): |
- MAX_SLICE = 0.01 |
- def __init__(self): |
- self.end = time.time() + self.MAX_SLICE |
- |
- |
- def __call__(self): |
- return time.time() >= self.end |
- |
- |
- |
-_EPSILON = 0.00000001 |
-def _defaultScheduler(x): |
- from twisted.internet import reactor |
- return reactor.callLater(_EPSILON, x) |
- |
- |
- |
-class Cooperator(object): |
- """ |
- Cooperative task scheduler. |
- """ |
- |
- def __init__(self, |
- terminationPredicateFactory=_Timer, |
- scheduler=_defaultScheduler, |
- started=True): |
- """ |
- Create a scheduler-like object to which iterators may be added. |
- |
- @param terminationPredicateFactory: A no-argument callable which will |
- be invoked at the beginning of each step and should return a |
- no-argument callable which will return False when the step should be |
- terminated. The default factory is time-based and allows iterators to |
- run for 1/100th of a second at a time. |
- |
- @param scheduler: A one-argument callable which takes a no-argument |
- callable and should invoke it at some future point. This will be used |
- to schedule each step of this Cooperator. |
- |
- @param started: A boolean which indicates whether iterators should be |
- stepped as soon as they are added, or if they will be queued up until |
- L{Cooperator.start} is called. |
- """ |
- self.iterators = [] |
- self._metarator = iter(()) |
- self._terminationPredicateFactory = terminationPredicateFactory |
- self._scheduler = scheduler |
- self._delayedCall = None |
- self._stopped = False |
- self._started = started |
- |
- |
- def coiterate(self, iterator, doneDeferred=None): |
- """ |
- Add an iterator to the list of iterators I am currently running. |
- |
- @return: a Deferred that will fire when the iterator finishes. |
- """ |
- if doneDeferred is None: |
- doneDeferred = defer.Deferred() |
- if self._stopped: |
- doneDeferred.errback(SchedulerStopped()) |
- return doneDeferred |
- self.iterators.append((iterator, doneDeferred)) |
- self._reschedule() |
- return doneDeferred |
- |
- |
- def _tasks(self): |
- terminator = self._terminationPredicateFactory() |
- while self.iterators: |
- for i in self._metarator: |
- yield i |
- if terminator(): |
- return |
- self._metarator = iter(self.iterators) |
- |
- |
- def _tick(self): |
- """ |
- Run one scheduler tick. |
- """ |
- self._delayedCall = None |
- for taskObj in self._tasks(): |
- iterator, doneDeferred = taskObj |
- try: |
- result = iterator.next() |
- except StopIteration: |
- self.iterators.remove(taskObj) |
- doneDeferred.callback(iterator) |
- except: |
- self.iterators.remove(taskObj) |
- doneDeferred.errback() |
- else: |
- if isinstance(result, defer.Deferred): |
- self.iterators.remove(taskObj) |
- def cbContinue(result, taskObj=taskObj): |
- self.coiterate(*taskObj) |
- result.addCallbacks(cbContinue, doneDeferred.errback) |
- self._reschedule() |
- |
- |
- _mustScheduleOnStart = False |
- def _reschedule(self): |
- if not self._started: |
- self._mustScheduleOnStart = True |
- return |
- if self._delayedCall is None and self.iterators: |
- self._delayedCall = self._scheduler(self._tick) |
- |
- |
- def start(self): |
- """ |
- Begin scheduling steps. |
- """ |
- self._stopped = False |
- self._started = True |
- if self._mustScheduleOnStart: |
- del self._mustScheduleOnStart |
- self._reschedule() |
- |
- |
- def stop(self): |
- """ |
- Stop scheduling steps. Errback the completion Deferreds of all |
- iterators which have been added and forget about them. |
- """ |
- self._stopped = True |
- for iterator, doneDeferred in self.iterators: |
- doneDeferred.errback(SchedulerStopped()) |
- self.iterators = [] |
- if self._delayedCall is not None: |
- self._delayedCall.cancel() |
- self._delayedCall = None |
- |
- |
- |
-_theCooperator = Cooperator() |
-def coiterate(iterator): |
- """ |
- Cooperatively iterate over the given iterator, dividing runtime between it |
- and all other iterators which have been passed to this function and not yet |
- exhausted. |
- """ |
- return _theCooperator.coiterate(iterator) |
- |
- |
- |
-class Clock: |
- """ |
- Provide a deterministic, easily-controlled implementation of |
- L{IReactorTime.callLater}. This is commonly useful for writing |
- deterministic unit tests for code which schedules events using this API. |
- """ |
- implements(IReactorTime) |
- |
- rightNow = 0.0 |
- |
- def __init__(self): |
- self.calls = [] |
- |
- def seconds(self): |
- """ |
- Pretend to be time.time(). This is used internally when an operation |
- such as L{IDelayedCall.reset} needs to determine a a time value |
- relative to the current time. |
- |
- @rtype: C{float} |
- @return: The time which should be considered the current time. |
- """ |
- return self.rightNow |
- |
- |
- def callLater(self, when, what, *a, **kw): |
- """ |
- See L{twisted.internet.interfaces.IReactorTime.callLater}. |
- """ |
- dc = base.DelayedCall(self.seconds() + when, |
- what, a, kw, |
- self.calls.remove, |
- lambda c: None, |
- self.seconds) |
- self.calls.append(dc) |
- self.calls.sort(lambda a, b: cmp(a.getTime(), b.getTime())) |
- return dc |
- |
- def getDelayedCalls(self): |
- """ |
- See L{twisted.internet.interfaces.IReactorTime.getDelayedCalls} |
- """ |
- return self.calls |
- |
- def advance(self, amount): |
- """ |
- Move time on this clock forward by the given amount and run whatever |
- pending calls should be run. |
- |
- @type amount: C{float} |
- @param amount: The number of seconds which to advance this clock's |
- time. |
- """ |
- self.rightNow += amount |
- while self.calls and self.calls[0].getTime() <= self.seconds(): |
- call = self.calls.pop(0) |
- call.called = 1 |
- call.func(*call.args, **call.kw) |
- |
- |
- def pump(self, timings): |
- """ |
- Advance incrementally by the given set of times. |
- |
- @type timings: iterable of C{float} |
- """ |
- for amount in timings: |
- self.advance(amount) |
- |
- |
-def deferLater(clock, delay, callable, *args, **kw): |
- """ |
- Call the given function after a certain period of time has passed. |
- |
- @type clock: L{IReactorTime} provider |
- @param clock: The object which will be used to schedule the delayed |
- call. |
- |
- @type delay: C{float} or C{int} |
- @param delay: The number of seconds to wait before calling the function. |
- |
- @param callable: The object to call after the delay. |
- |
- @param *args: The positional arguments to pass to C{callable}. |
- |
- @param **kw: The keyword arguments to pass to C{callable}. |
- |
- @rtype: L{defer.Deferred} |
- |
- @return: A deferred that fires with the result of the callable when the |
- specified time has elapsed. |
- """ |
- d = defer.Deferred() |
- d.addCallback(lambda ignored: callable(*args, **kw)) |
- clock.callLater(delay, d.callback, None) |
- return d |
- |
- |
- |
-__all__ = [ |
- 'LoopingCall', |
- |
- 'Clock', |
- |
- 'SchedulerStopped', 'Cooperator', 'coiterate', |
- |
- 'deferLater', |
- ] |