Skip to content

Commit

Permalink
Merge loopincall-deferred-deprecate-8116: Deprecate LoopingCall.defer…
Browse files Browse the repository at this point in the history
…red.

Author: adiroiban, hawkowl
Reviewer: hawkowl, glyph
Fixes: twisted#8116

git-svn-id: svn://svn.twistedmatrix.com/svn/Twisted/trunk@46566 bbbe8e31-12d6-0310-92fd-ac37d47ddeeb
  • Loading branch information
adiroiban committed Dec 25, 2015
1 parent 0b29cce commit 0cdcf60
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 36 deletions.
80 changes: 50 additions & 30 deletions docs/core/howto/time.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,68 +42,88 @@ call:

.. code-block:: python
from twisted.internet import task
from twisted.internet import reactor
def f(s):
return "This will run 3.5 seconds after it was scheduled: %s" % s
d = task.deferLater(reactor, 3.5, f, "hello, world")
def called(result):
print result
d.addCallback(called)
# f() will only be called if the event loop is started.
reactor.run()
If we want a task to run every X seconds repeatedly, we can use :api:`twisted.internet.task.LoopingCall <twisted.internet.task.LoopingCall>`:

.. code-block:: python
If we want a task to run every X seconds repeatedly, we can
use :api:`twisted.internet.task.LoopingCall <twisted.internet.task.LoopingCall>` :
from twisted.internet import task
from twisted.internet import reactor
loopTimes = 3
failInTheEnd = False
_loopCounter = 0
def runEverySecond():
"""
Called at ever loop interval.
"""
global _loopCounter
if _loopCounter < loopTimes:
_loopCounter += 1
print 'A new second has passed.'
return
.. code-block:: python
if failInTheEnd:
raise Exception('Failure during loop execution.')
from twisted.internet import task
from twisted.internet import reactor
def runEverySecond():
print "a second has passed"
l = task.LoopingCall(runEverySecond)
l.start(1.0) # call every second
# l.stop() will stop the looping calls
reactor.run()
# We looped enough times.
loop.stop()
return
def cbLoopDone(result):
"""
Called when loop was stopped with success.
"""
print "Loop done."
reactor.stop()
If we want to cancel a task that we've scheduled:
def ebLoopFailed(failure):
"""
Called when loop execution failed.
"""
print failure.getBriefTraceback()
reactor.stop()
loop = task.LoopingCall(runEverySecond)
# Start looping every 1 second.
loopDeferred = loop.start(1.0)
# Add callbacks for stop and failure.
loopDeferred.addCallback(cbLoopDone)
loopDeferred.addErrback(ebLoopFailed)
reactor.run()
If we want to cancel a task that we've scheduled:

.. code-block:: python
from twisted.internet import reactor
def f():
print "I'll never run."
callID = reactor.callLater(5, f)
callID.cancel()
reactor.run()
As with all reactor-based code, in order for scheduling to work the reactor must be started using ``reactor.run()`` .


26 changes: 20 additions & 6 deletions twisted/internet/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

from twisted.python import log
from twisted.python import reflect
from twisted.python.deprecate import deprecated
from twisted.python.failure import Failure
from twisted.python.versions import Version

from twisted.internet import base, defer
from twisted.internet.interfaces import IReactorTime
Expand Down Expand Up @@ -57,7 +59,7 @@ class LoopingCall:

call = None
running = False
deferred = None
_deferred = None
interval = None
_runAtStart = False
starttime = None
Expand All @@ -69,6 +71,16 @@ def __init__(self, f, *a, **kw):
from twisted.internet import reactor
self.clock = reactor

@property
@deprecated(
Version("Twisted", 16, 0, 0), 'the deferred returned by start()')
def deferred(self):
"""
DEPRECATED. Deferred fired when loop stops or fails.
Use the
"""
return self._deferred

def withCount(cls, countCallable):
"""
Expand Down Expand Up @@ -167,15 +179,17 @@ def start(self, interval, now=True):
if interval < 0:
raise ValueError("interval must be >= 0")
self.running = True
d = self.deferred = defer.Deferred()
# Loop might fail to start and then self._deferred will be cleared.
# This why the local C{deferred} variable is used.
deferred = self._deferred = defer.Deferred()
self.starttime = self.clock.seconds()
self.interval = interval
self._runAtStart = now
if now:
self()
else:
self._scheduleFrom(self.starttime)
return d
return deferred

def stop(self):
"""Stop running function.
Expand All @@ -186,7 +200,7 @@ def stop(self):
if self.call is not None:
self.call.cancel()
self.call = None
d, self.deferred = self.deferred, None
d, self._deferred = self._deferred, None
d.callback(self)

def reset(self):
Expand All @@ -208,12 +222,12 @@ def cb(result):
if self.running:
self._scheduleFrom(self.clock.seconds())
else:
d, self.deferred = self.deferred, None
d, self._deferred = self._deferred, None
d.callback(self)

def eb(failure):
self.running = False
d, self.deferred = self.deferred, None
d, self._deferred = self._deferred, None
d.errback(failure)

self.call = None
Expand Down
19 changes: 19 additions & 0 deletions twisted/test/test_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,25 @@ def test_reprMethod(self):
"LoopingCall<None>(TestableLoopingCall.__init__, *(), **{})")


def test_deferredDeprecation(self):
"""
L{LoopingCall.deferred} is deprecated.
"""
loop = task.LoopingCall(lambda: None)

loop.deferred

message = (
'twisted.internet.task.LoopingCall.deferred was deprecated in '
'Twisted 16.0.0; '
'please use the deferred returned by start() instead'
)
warnings = self.flushWarnings([self.test_deferredDeprecation])
self.assertEqual(1, len(warnings))
self.assertEqual(DeprecationWarning, warnings[0]['category'])
self.assertEqual(message, warnings[0]['message'])



class ReactorLoopTests(unittest.TestCase):
# Slightly inferior tests which exercise interactions with an actual
Expand Down
1 change: 1 addition & 0 deletions twisted/topfiles/8116.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
twisted.internet.task.LoopingCall.deferred is now deprecated. Use the deferred returned by twisted.internet.task.LoopingCall.start()

0 comments on commit 0cdcf60

Please sign in to comment.