Skip to content

Commit

Permalink
buildbot.util.eventual - move, test, document
Browse files Browse the repository at this point in the history
Move buildbot.eventual to buildbot.util.eventual, create succinct
unit tests, and add documentation.
  • Loading branch information
Dustin J. Mitchell committed Feb 21, 2010
1 parent 33e52d4 commit c3863e9
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 75 deletions.
70 changes: 0 additions & 70 deletions buildbot/broken_test/unit/test_eventual.py

This file was deleted.

2 changes: 1 addition & 1 deletion buildbot/db.py
Expand Up @@ -53,7 +53,7 @@
from buildbot.buildrequest import BuildRequest
from buildbot.process.properties import Properties
from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE
from buildbot.eventual import eventually
from buildbot.util.eventual import eventually

TABLES = [
# the schema here is defined as version 1
Expand Down
2 changes: 1 addition & 1 deletion buildbot/process/builder.py
Expand Up @@ -11,7 +11,7 @@
from buildbot.status.progress import Expectations
from buildbot.status.builder import RETRY
from buildbot.process.properties import Properties
from buildbot.eventual import eventually
from buildbot.util.eventual import eventually

(ATTACHING, # slave attached, still checking hostinfo/etc
IDLE, # idle, available for use
Expand Down
2 changes: 1 addition & 1 deletion buildbot/schedulers/manager.py
Expand Up @@ -39,7 +39,7 @@
from twisted.python import log
from buildbot import loop
from buildbot.util import defaultdict
from buildbot.eventual import eventually
from buildbot.util.eventual import eventually

class SchedulerManager(loop.MultiServiceLoop):
def __init__(self, master, db, change_svc):
Expand Down
2 changes: 1 addition & 1 deletion buildbot/status/builder.py
Expand Up @@ -6,7 +6,7 @@
from twisted.internet import reactor, defer, threads
from twisted.protocols import basic
from buildbot.process.properties import Properties
from buildbot.eventual import eventually
from buildbot.util.eventual import eventually

import weakref
import os, shutil, sys, re, urllib, itertools
Expand Down
93 changes: 93 additions & 0 deletions buildbot/test/unit/test_eventual.py
@@ -0,0 +1,93 @@
from twisted.trial import unittest
from twisted.internet import defer
from twisted.python import log

from buildbot.util import eventual

class Eventually(unittest.TestCase):

def setUp(self):
# reset the queue to its base state
eventual._theSimpleQueue = eventual._SimpleCallQueue()
self.old_log_err = log.err
self.results = []

def tearDown(self):
log.err = self.old_log_err
return eventual.flushEventualQueue()

# utility callback
def cb(self, *args, **kwargs):
r = args
if kwargs: r = r + (kwargs,)
self.results.append(r)

# flush the queue and assert results
def assertResults(self, exp):
d = eventual.flushEventualQueue()
def cb(_):
self.assertEqual(self.results, exp)
d.addCallback(cb)
return d

## tests

def test_eventually_calls(self):
eventual.eventually(self.cb)
return self.assertResults([()])

def test_eventually_args(self):
eventual.eventually(self.cb, 1, 2, a='a')
return self.assertResults([(1, 2, dict(a='a'))])

def test_eventually_err(self):
# monkey-patch log.err; this is restored by tearDown
log.err = lambda : self.results.append("err")
def cb_fails():
raise RuntimeError("should not cause test failure")
eventual.eventually(cb_fails)
return self.assertResults(['err'])

def test_eventually_butNotNow(self):
eventual.eventually(self.cb, 1)
self.failIf(self.results != [])
return self.assertResults([(1,)])

def test_eventually_order(self):
eventual.eventually(self.cb, 1)
eventual.eventually(self.cb, 2)
eventual.eventually(self.cb, 3)
return self.assertResults([(1,), (2,), (3,)])

def test_flush_waitForChainedEventuallies(self):
def chain(n):
self.results.append(n)
if n <= 0: return
eventual.eventually(chain, n-1)
chain(3)
# (the flush this tests is implicit in assertResults)
return self.assertResults([3, 2, 1, 0])

def test_flush_waitForTreeEventuallies(self):
# a more complex set of eventualities
def tree(n):
self.results.append(n)
if n <= 0: return
eventual.eventually(tree, n-1)
eventual.eventually(tree, n-1)
tree(2)
# (the flush this tests is implicit in assertResults)
return self.assertResults([2, 1, 1, 0, 0, 0, 0])

def test_flush_duringTurn(self):
testd = defer.Deferred()
def cb():
d = eventual.flushEventualQueue()
d.addCallback(testd.callback)
eventual.eventually(cb)
return testd

def test_fireEventually_call(self):
d = eventual.fireEventually(13)
d.addCallback(self.cb)
return self.assertResults([(13,)])
File renamed without changes.
1 change: 0 additions & 1 deletion buildbot/eventual.py → buildbot/util/eventual.py
Expand Up @@ -5,7 +5,6 @@
from twisted.python import log

class _SimpleCallQueue(object):
# XXX TODO: merge epsilon.cooperator in, and make this more complete.
def __init__(self):
self._events = []
self._flushObservers = []
Expand Down
29 changes: 29 additions & 0 deletions docs/developer.texinfo
Expand Up @@ -12,6 +12,7 @@ described here.

@menu
* Buildmaster Service Hierarchy::
* Utilities::
* The Event Loop::
* String Types::
* Subscription Interfaces::
Expand All @@ -24,6 +25,34 @@ described here.

TODO

@node Utilities
@section Utilities

@menu
* buildbot.util.eventual::
@end menu

@node buildbot.util.eventual
@subsection buildbot.util.eventual

This package provides a simple way to say "please do this later":

@example
from buildbot.util.eventual import eventually
def do_what_I_say(what, where):
# ...
eventually(do_what_I_say, "clean up", "your bedroom")
@end example

The package defines "later" as "next time the reactor has control", so this is
a good way to avoid long loops that block other activity in the reactor.
Callables given to @code{eventually} are guaranteed to be called in the same
order as the calls to @code{eventually}. Any errors from the callable are
logged, but will not affect other callables.

If you need a deferred that will fire "later", use @code{fireEventually}. This
function returns a deferred that will not errback.

@node The Event Loop
@section The Event Loop

Expand Down

0 comments on commit c3863e9

Please sign in to comment.