def _do(request, input, as_exception=False):
    """
    Send the provided input to the asynchronous request handler for *request*.
    If ``as_exception`` is truthy, throw it into the generator as an exception,
    otherwise it's just sent.
    """
    if request._in_do:
        # Let's not enter some bizarre stack recursion that can cause all sorts
        # of badness today, shall we? Put off the next _do till the next
        # engine cycle.
        request.connection.engine.callback(_do, request, input, as_exception)
        return

    try:
        request._in_do = True

        while True:
            errored = False

            with request._context as app:
                # Make sure we're connected.
                if not request.connection.connected:
                    try:
                        # Bubble up an error so the user's code can do something
                        # about this.
                        request._gen.throw(RequestClosed())
                    except RequestClosed:
                        # Don't react at all to our own exception.
                        pass
                    except Exception:
                        # Just log any other exception. The request is already
                        # closed, so there's not a lot *else* to do.
                        log.exception("Error while cleaning up closed "
                                      "asynchronous request: %s %s" %
                                      (request.method, request.url))
                    finally:
                        _cleanup(request)
                        return

                try:
                    if as_exception:
                        output = request._gen.throw(input)
                    else:
                        output = request._gen.send(input)

                except __HOLE__:
                    # We've run out of content. Setting output to Finished
                    # tells the output handler to close up and go home.
                    output = Finished

                except HTTPException as err:
                    if request._started:
                        log.exception("Error while handling asynchronous "
                                      "request: %s %s" % (request.method,
                                                          request.url))
                        request.connection.close(False)
                        _cleanup(request)
                        return

                    errored = True
                    request._tb = traceback.format_exc()

                    err_handler = getattr(app, "handle_%d" % err.status, None)
                    if err_handler:
                        output = err_handler(request, err)
                    else:
                        output = error(err.message, err.status, err.headers,
                            request=request)

                except HTTPTransparentRedirect as err:
                    if request._started:
                        log.exception("HTTPTransparentRedirect sent to already "
                                      "started request: %s %s" %
                                      (request.method, request.url))
                        request.connection.close(False)
                        _cleanup(request)
                        return

                    errored = True
                    output = err
                    request._tb = traceback.format_exc()

                except Exception as err:
                    if request._started:
                        log.exception("Error while handling asynchronous "
                                      "request: %s %s" % (request.method,
                                                          request.url))
                        request.connection.close(False)
                        _cleanup(request)
                        return

                    errored = True
                    request._tb = traceback.format_exc()

                    try:
                        output = app.handle_500(request, err)
                    except Exception:
                        # There's an error with the handle_500 function.
                        log.exception("There was a problem handling a request, and a "
                                      "problem running Application.handle_500 for %r."
                                        % app)

                        output = error(500, request=request)

            # Did we error?
            if errored:
                # Clear the rule data, because errors don't care about it.
                request._rule_content_type = None
                request._rule_headers = None

                _async_finish(request, output)
                return

            # Returning a list of Callback instances is the only way to control
            # exactly what you're waiting for.
            if not isinstance(output, _WaitList) and \
                    isinstance(output, (tuple, list)) and \
                    all(isinstance(x, Callback) for x in output):
                output = _WaitList(output)

            # Now that we're out of the request context, let's see what we've got to
            # work with.
            if isinstance(output, _Sleeper):
                # Just sleep.
                request.connection.engine.defer(output[0], _do, request, None)

            elif isinstance(output, Callback):
                # Shove the callback onto its own waiting list.
                request._unhandled.remove(output)
                request._waiting.append(output)

            elif isinstance(output, _WaitList):
                # Push the WaitList onto the waiting list.
                if output.timeout:
                    output.timeout = request.connection.engine.defer(output.timeout, _wait_timeout, request)
                request._waiting.append(output)

            elif isinstance(output, _Receiver):
                # Push the Receiver onto the waiting list.
                if output[1]:
                    output.timeout = request.connection.engine.defer(output[1], _receive_timeout, request)

                output.ref = ref = weakref.ref(request)
                receivers.setdefault(output[0], []).append(ref)
                request._waiting.append(output)

            else:
                # We've received some content, so write it out.
                if request._writer(request, output) is Again:
                    input = None
                    as_exception = False
                    continue

            # We *have* to continue if we don't want to break.
            break

    finally:
        if hasattr(request, "_in_do"):
            request._in_do = False
dataset/ETHPy150Open ecdavis/pants/pants/web/asynchronous.py/_do