Block current greenlet for Deferred, waiting until result is not a Deferred or a failure is encountered

def waitForDeferred(d, result=None):
    """Block current greenlet for Deferred, waiting until result is not a Deferred or a failure is encountered"""
    from twisted.internet import reactor
    assert reactor.greenlet != getcurrent(), "can't invoke this in the reactor greenlet"
    if result is None:
        result = AsyncResult()

    def cb(res):
        if isinstance(res, defer.Deferred):
            waitForDeferred(res, result)
        else:
            result.set(res)

    def eb(res):
        result.set_exception(res)

    d.addCallbacks(cb, eb)
    try:
        return result.get()
    except failure.Failure, ex:
        ex.raiseException()