def _inlineCallbacks(result, g, status):
    """
    Carry out the work of L{inlineCallbacks}.

    Iterate the generator produced by an C{@}L{inlineCallbacks}-decorated
    function, C{g}, C{send()}ing it the results of each value C{yield}ed by
    that generator, until a L{Deferred} is yielded, at which point a callback
    is added to that L{Deferred} to call this function again.

    @param result: The last result seen by this generator.  Note that this is
        never a L{Deferred} - by the time this function is invoked, the
        L{Deferred} has been called back and this will be a particular result
        at a point in its callback chain.

    @param g: a generator object returned by calling a function or method
        decorated with C{@}L{inlineCallbacks}

    @param status: a L{_CancellationStatus} tracking the current status of C{g}
    """
    # This function is complicated by the need to prevent unbounded recursion
    # arising from repeatedly yielding immediately ready deferreds.  This while
    # loop and the waiting variable solve that by manually unfolding the
    # recursion.

    waiting = [True, # waiting for result?
               None] # result

    while 1:
        try:
            # Send the last result back as the result of the yield expression.
            isFailure = isinstance(result, failure.Failure)
            if isFailure:
                result = result.throwExceptionIntoGenerator(g)
            else:
                result = g.send(result)
        except StopIteration as e:
            # fell off the end, or "return" statement
            status.deferred.callback(getattr(e, "value", None))
            return
        except _DefGen_Return as e:
            # returnValue() was called; time to give a result to the original
            # Deferred.  First though, let's try to identify the potentially
            # confusing situation which results when returnValue() is
            # accidentally invoked from a different function, one that wasn't
            # decorated with @inlineCallbacks.

            # The traceback starts in this frame (the one for
            # _inlineCallbacks); the next one down should be the application
            # code.
            appCodeTrace = exc_info()[2].tb_next
            if isFailure:
                # If we invoked this generator frame by throwing an exception
                # into it, then throwExceptionIntoGenerator will consume an
                # additional stack frame itself, so we need to skip that too.
                appCodeTrace = appCodeTrace.tb_next
            # Now that we've identified the frame being exited by the
            # exception, let's figure out if returnValue was called from it
            # directly.  returnValue itself consumes a stack frame, so the
            # application code will have a tb_next, but it will *not* have a
            # second tb_next.
            if appCodeTrace.tb_next.tb_next:
                # If returnValue was invoked non-local to the frame which it is
                # exiting, identify the frame that ultimately invoked
                # returnValue so that we can warn the user, as this behavior is
                # confusing.
                ultimateTrace = appCodeTrace
                while ultimateTrace.tb_next.tb_next:
                    ultimateTrace = ultimateTrace.tb_next
                filename = ultimateTrace.tb_frame.f_code.co_filename
                lineno = ultimateTrace.tb_lineno
                warnings.warn_explicit(
                    "returnValue() in %r causing %r to exit: "
                    "returnValue should only be invoked by functions decorated "
                    "with inlineCallbacks" % (
                        ultimateTrace.tb_frame.f_code.co_name,
                        appCodeTrace.tb_frame.f_code.co_name),
                    DeprecationWarning, filename, lineno)
            status.deferred.callback(e.value)
            return
        except:
            status.deferred.errback()
            return

        if isinstance(result, Deferred):
            # a deferred was yielded, get the result.
            def gotResult(r):
                if waiting[0]:
                    waiting[0] = False
                    waiting[1] = r
                else:
                    # We are not waiting for deferred result any more
                    _inlineCallbacks(r, g, status)

            result.addBoth(gotResult)
            if waiting[0]:
                # Haven't called back yet, set flag so that we get reinvoked
                # and return from the loop
                waiting[0] = False
                status.waitingOn = result
                return

            result = waiting[1]
            # Reset waiting to initial values for next loop.  gotResult uses
            # waiting, but this isn't a problem because gotResult is only
            # executed once, and if it hasn't been executed yet, the return
            # branch above would have been taken.

            waiting[0] = True
            waiting[1] = None

    Carry out the work of L{inlineCallbacks}.

    Iterate the generator produced by an C{@}L{inlineCallbacks}-decorated
    function, C{g}, C{send()}ing it the results of each value C{yield}ed by
    that generator, until a L{Deferred} is yielded, at which point a callback
    is added to that L{Deferred} to call this function again.

    @param result: The last result seen by this generator.  Note that this is
        never a L{Deferred} - by the time this function is invoked, the
        L{Deferred} has been called back and this will be a particular result
        at a point in its callback chain.

    @param g: a generator object returned by calling a function or method
        decorated with C{@}L{inlineCallbacks}

    @param status: a L{_CancellationStatus} tracking the current status of C{g}
    
stackoverflow/venv/lib/python3.6/site-packages/twisted/internet/defer.py