Example #1
0
def deferredGenerator(f):
    """
    deferredGenerator and waitForDeferred help you write Deferred-using code
    that looks like a regular sequential function. If your code has a minimum
    requirement of Python 2.5, consider the use of L{inlineCallbacks} instead,
    which can accomplish the same thing in a more concise manner.

    There are two important functions involved: waitForDeferred, and
    deferredGenerator.  They are used together, like this::

        def thingummy():
            thing = waitForDeferred(makeSomeRequestResultingInDeferred())
            yield thing
            thing = thing.getResult()
            print thing #the result! hoorj!
        thingummy = deferredGenerator(thingummy)

    waitForDeferred returns something that you should immediately yield; when
    your generator is resumed, calling thing.getResult() will either give you
    the result of the Deferred if it was a success, or raise an exception if it
    was a failure.  Calling C{getResult} is B{absolutely mandatory}.  If you do
    not call it, I{your program will not work}.

    deferredGenerator takes one of these waitForDeferred-using generator
    functions and converts it into a function that returns a Deferred. The
    result of the Deferred will be the last value that your generator yielded
    unless the last value is a waitForDeferred instance, in which case the
    result will be C{None}.  If the function raises an unhandled exception, the
    Deferred will errback instead.  Remember that 'return result' won't work;
    use 'yield result; return' in place of that.

    Note that not yielding anything from your generator will make the Deferred
    result in None. Yielding a Deferred from your generator is also an error
    condition; always yield waitForDeferred(d) instead.

    The Deferred returned from your deferred generator may also errback if your
    generator raised an exception.  For example::

        def thingummy():
            thing = waitForDeferred(makeSomeRequestResultingInDeferred())
            yield thing
            thing = thing.getResult()
            if thing == 'I love Twisted':
                # will become the result of the Deferred
                yield 'TWISTED IS GREAT!'
                return
            else:
                # will trigger an errback
                raise Exception('DESTROY ALL LIFE')
        thingummy = deferredGenerator(thingummy)

    Put succinctly, these functions connect deferred-using code with this 'fake
    blocking' style in both directions: waitForDeferred converts from a
    Deferred to the 'blocking' style, and deferredGenerator converts from the
    'blocking' style to a Deferred.
    """
    def unwindGenerator(*args, **kwargs):
        return _deferGenerator(f(*args, **kwargs), Deferred())
    return mergeFunctionMetadata(f, unwindGenerator)
Example #2
0
def inlineCallbacks(f):
    """
    WARNING: this function will not work in Python 2.4 and earlier!

    inlineCallbacks helps you write Deferred-using code that looks like a
    regular sequential function. This function uses features of Python 2.5
    generators.  If you need to be compatible with Python 2.4 or before, use
    the L{deferredGenerator} function instead, which accomplishes the same
    thing, but with somewhat more boilerplate.  For example::

        def thingummy():
            thing = yield makeSomeRequestResultingInDeferred()
            print thing #the result! hoorj!
        thingummy = inlineCallbacks(thingummy)

    When you call anything that results in a Deferred, you can simply yield it;
    your generator will automatically be resumed when the Deferred's result is
    available. The generator will be sent the result of the Deferred with the
    'send' method on generators, or if the result was a failure, 'throw'.

    Your inlineCallbacks-enabled generator will return a Deferred object, which
    will result in the return value of the generator (or will fail with a
    failure object if your generator raises an unhandled exception). Note that
    you can't use 'return result' to return a value; use 'returnValue(result)'
    instead. Falling off the end of the generator, or simply using 'return'
    will cause the Deferred to have a result of None.

    The Deferred returned from your deferred generator may errback if your
    generator raised an exception::

        def thingummy():
            thing = yield makeSomeRequestResultingInDeferred()
            if thing == 'I love Twisted':
                # will become the result of the Deferred
                returnValue('TWISTED IS GREAT!')
            else:
                # will trigger an errback
                raise Exception('DESTROY ALL LIFE')
        thingummy = inlineCallbacks(thingummy)
    """
    def unwindGenerator(*args, **kwargs):
        return _inlineCallbacks(None, f(*args, **kwargs), Deferred())
    return mergeFunctionMetadata(f, unwindGenerator)
Example #3
0
    def deprecationDecorator(function):
        """
        Decorator that marks C{function} as deprecated.
        """
        warningString = getDeprecationWarningString(function, version)

        def deprecatedFunction(*args, **kwargs):
            warn(
                warningString,
                DeprecationWarning,
                stacklevel=2)
            return function(*args, **kwargs)

        deprecatedFunction = mergeFunctionMetadata(
            function, deprecatedFunction)
        _appendToDocstring(deprecatedFunction,
                           _getDeprecationDocstring(version))
        deprecatedFunction.deprecatedVersion = version
        return deprecatedFunction