Called if a function decorated with :func:`yieldefer` is invoked.

def _yielddefer(function, *args, **kwargs):
    """
    Called if a function decorated with :func:`yieldefer` is invoked.
    """
    try:
        retval = function(*args, **kwargs)
    except:
        return defer.fail()
    
    if isinstance(retval, defer.Deferred):
        return retval
    
    if not (hasattr(retval, '__iter__') and 
            hasattr(retval, 'next') and 
            hasattr(retval, 'send') and 
            hasattr(retval, 'throw')):
        return defer.succeed(retval)
    
    iterator = retval
    
    
    def maybe_deferred(val):
        # We don't want exceptions to become twisted failures
        # because exceptions thrown by the generator methods
        # indicate exceptions thrown by the code _between_ the
        # yield statements or it indicates the end of the 
        # iteration.
        if isinstance(val, defer.Deferred):
            return val
        else:
            return defer.succeed(val)
    
    def success(value):
        try:
            d = maybe_deferred(iterator.send(value))
            d.addCallbacks(success, fail)
            return d
        except StopIteration:
            return None
        except defer._DefGen_Return as e:
            return e.value
    
    def fail(failure):
        try:
            d = maybe_deferred(failure.throwExceptionIntoGenerator(iterator))
            #d = iterator.throw(failure.value)
            d.addCallbacks(success, fail)
            return d
        except StopIteration:
            return None
        except defer._DefGen_Return as e:
            return e.value
        
    try:
        d = maybe_deferred(iterator.next())
        d.addCallbacks(success, fail)
    except StopIteration:
        d = defer.succeed(None)
    except defer._DefGen_Return as e:
        d = defer.succeed(e.value)
    except:
        d = defer.fail()
        
    return d