[Twisted-Python] @inlinecallbacks and AlreadyCalledError in test cases

Brad Milne brad.milne at devx.runthered.com
Mon Apr 4 19:39:05 MDT 2011


Hi all

I have recently started switching to trial.unittest from python's own. The
trouble I'm experiencing is when a timeout occurs in my test, it errbacks().
Then the @inlineCallbacks decorator sees the error and errbacks(). But then
a second @inlineCallback in the chain subsequently sees *that* errback and
tries to errback itself. This results in AlreadyCalledError.

In the test setup, various services are started. These are tracked and then
shutdown again in the teardown. Also, there is some polling that happens as
part of the tests (waiting on db activities, for example). These use
deferLater calls, which are also tracked and torn down in the teardown.

I've tried _suppressAlreadyCalled in various places to no avail.

Below is a simple example that shows the problem.

Many thanks
Brad


<code>

from twisted.trial.unittest import TestCase

from twisted.internet import task, reactor

from twisted.internet.defer import inlineCallbacks


#import twisted

#twisted.internet.base.DelayedCall.debug = True

#twisted.internet.defer.setDebugging(True)


class Test1(TestCase):



    def setUp(self):

        # timeout test in 1 second

        self.timeout = 1

        self.jobs = []

        self.addCleanup(self._tearDown)



    def _tearDown(self):

        for d in self.jobs:

            if d and not d.called:

                d.cancel()



    @inlineCallbacks

    def _waitForChange(self):

        # do stuff

        d = task.deferLater(reactor, 0.5, lambda : None)

        self.jobs.append(d)

        yield d

        self.jobs.remove(d)

        # do more stuff



    @inlineCallbacks

    def testHere(self):

        # do stuff

        yield self._waitForChange()

        # do more stuff


    # This one passes OK

    #def testHere(self):

    #   return self._waitForChange()


if __name__ == "__main__":

    import sys

    from twisted.scripts import trial

    sys.argv.extend([sys.argv[0]])

    trial.run()

</code>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20110405/cd2f964c/attachment.html>


More information about the Twisted-Python mailing list