<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">from __future__ import annotations

import html
import inspect
import sys
import traceback
import typing

from starlette._utils import is_async_callable
from starlette.concurrency import run_in_threadpool
from starlette.requests import Request
from starlette.responses import HTMLResponse, PlainTextResponse, Response
from starlette.types import ASGIApp, Message, Receive, Scope, Send

STYLES = """
p {
    color: #211c1c;
}
.traceback-container {
    border: 1px solid #038BB8;
}
.traceback-title {
    background-color: #038BB8;
    color: lemonchiffon;
    padding: 12px;
    font-size: 20px;
    margin-top: 0px;
}
.frame-line {
    padding-left: 10px;
    font-family: monospace;
}
.frame-filename {
    font-family: monospace;
}
.center-line {
    background-color: #038BB8;
    color: #f9f6e1;
    padding: 5px 0px 5px 5px;
}
.lineno {
    margin-right: 5px;
}
.frame-title {
    font-weight: unset;
    padding: 10px 10px 10px 10px;
    background-color: #E4F4FD;
    margin-right: 10px;
    color: #191f21;
    font-size: 17px;
    border: 1px solid #c7dce8;
}
.collapse-btn {
    float: right;
    padding: 0px 5px 1px 5px;
    border: solid 1px #96aebb;
    cursor: pointer;
}
.collapsed {
  display: none;
}
.source-code {
  font-family: courier;
  font-size: small;
  padding-bottom: 10px;
}
"""

JS = """
&lt;script type="text/javascript"&gt;
    function collapse(element){
        const frameId = element.getAttribute("data-frame-id");
        const frame = document.getElementById(frameId);

        if (frame.classList.contains("collapsed")){
            element.innerHTML = "&amp;#8210;";
            frame.classList.remove("collapsed");
        } else {
            element.innerHTML = "+";
            frame.classList.add("collapsed");
        }
    }
&lt;/script&gt;
"""

TEMPLATE = """
&lt;html&gt;
    &lt;head&gt;
        &lt;style type='text/css'&gt;
            {styles}
        &lt;/style&gt;
        &lt;title&gt;Starlette Debugger&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;500 Server Error&lt;/h1&gt;
        &lt;h2&gt;{error}&lt;/h2&gt;
        &lt;div class="traceback-container"&gt;
            &lt;p class="traceback-title"&gt;Traceback&lt;/p&gt;
            &lt;div&gt;{exc_html}&lt;/div&gt;
        &lt;/div&gt;
        {js}
    &lt;/body&gt;
&lt;/html&gt;
"""

FRAME_TEMPLATE = """
&lt;div&gt;
    &lt;p class="frame-title"&gt;File &lt;span class="frame-filename"&gt;{frame_filename}&lt;/span&gt;,
    line &lt;i&gt;{frame_lineno}&lt;/i&gt;,
    in &lt;b&gt;{frame_name}&lt;/b&gt;
    &lt;span class="collapse-btn" data-frame-id="{frame_filename}-{frame_lineno}" onclick="collapse(this)"&gt;{collapse_button}&lt;/span&gt;
    &lt;/p&gt;
    &lt;div id="{frame_filename}-{frame_lineno}" class="source-code {collapsed}"&gt;{code_context}&lt;/div&gt;
&lt;/div&gt;
"""  # noqa: E501

LINE = """
&lt;p&gt;&lt;span class="frame-line"&gt;
&lt;span class="lineno"&gt;{lineno}.&lt;/span&gt; {line}&lt;/span&gt;&lt;/p&gt;
"""

CENTER_LINE = """
&lt;p class="center-line"&gt;&lt;span class="frame-line center-line"&gt;
&lt;span class="lineno"&gt;{lineno}.&lt;/span&gt; {line}&lt;/span&gt;&lt;/p&gt;
"""


class ServerErrorMiddleware:
    """
    Handles returning 500 responses when a server error occurs.

    If 'debug' is set, then traceback responses will be returned,
    otherwise the designated 'handler' will be called.

    This middleware class should generally be used to wrap *everything*
    else up, so that unhandled exceptions anywhere in the stack
    always result in an appropriate 500 response.
    """

    def __init__(
        self,
        app: ASGIApp,
        handler: typing.Callable[[Request, Exception], typing.Any] | None = None,
        debug: bool = False,
    ) -&gt; None:
        self.app = app
        self.handler = handler
        self.debug = debug

    async def __call__(self, scope: Scope, receive: Receive, send: Send) -&gt; None:
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        response_started = False

        async def _send(message: Message) -&gt; None:
            nonlocal response_started, send

            if message["type"] == "http.response.start":
                response_started = True
            await send(message)

        try:
            await self.app(scope, receive, _send)
        except Exception as exc:
            request = Request(scope)
            if self.debug:
                # In debug mode, return traceback responses.
                response = self.debug_response(request, exc)
            elif self.handler is None:
                # Use our default 500 error handler.
                response = self.error_response(request, exc)
            else:
                # Use an installed 500 error handler.
                if is_async_callable(self.handler):
                    response = await self.handler(request, exc)
                else:
                    response = await run_in_threadpool(self.handler, request, exc)

            if not response_started:
                await response(scope, receive, send)

            # We always continue to raise the exception.
            # This allows servers to log the error, or allows test clients
            # to optionally raise the error within the test case.
            raise exc

    def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -&gt; str:
        values = {
            # HTML escape - line could contain &lt; or &gt;
            "line": html.escape(line).replace(" ", "&amp;nbsp"),
            "lineno": (frame_lineno - frame_index) + index,
        }

        if index != frame_index:
            return LINE.format(**values)
        return CENTER_LINE.format(**values)

    def generate_frame_html(self, frame: inspect.FrameInfo, is_collapsed: bool) -&gt; str:
        code_context = "".join(
            self.format_line(
                index,
                line,
                frame.lineno,
                frame.index,  # type: ignore[arg-type]
            )
            for index, line in enumerate(frame.code_context or [])
        )

        values = {
            # HTML escape - filename could contain &lt; or &gt;, especially if it's a virtual
            # file e.g. &lt;stdin&gt; in the REPL
            "frame_filename": html.escape(frame.filename),
            "frame_lineno": frame.lineno,
            # HTML escape - if you try very hard it's possible to name a function with &lt;
            # or &gt;
            "frame_name": html.escape(frame.function),
            "code_context": code_context,
            "collapsed": "collapsed" if is_collapsed else "",
            "collapse_button": "+" if is_collapsed else "&amp;#8210;",
        }
        return FRAME_TEMPLATE.format(**values)

    def generate_html(self, exc: Exception, limit: int = 7) -&gt; str:
        traceback_obj = traceback.TracebackException.from_exception(exc, capture_locals=True)

        exc_html = ""
        is_collapsed = False
        exc_traceback = exc.__traceback__
        if exc_traceback is not None:
            frames = inspect.getinnerframes(exc_traceback, limit)
            for frame in reversed(frames):
                exc_html += self.generate_frame_html(frame, is_collapsed)
                is_collapsed = True

        if sys.version_info &gt;= (3, 13):  # pragma: no cover
            exc_type_str = traceback_obj.exc_type_str
        else:  # pragma: no cover
            exc_type_str = traceback_obj.exc_type.__name__

        # escape error class and text
        error = f"{html.escape(exc_type_str)}: {html.escape(str(traceback_obj))}"

        return TEMPLATE.format(styles=STYLES, js=JS, error=error, exc_html=exc_html)

    def generate_plain_text(self, exc: Exception) -&gt; str:
        return "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))

    def debug_response(self, request: Request, exc: Exception) -&gt; Response:
        accept = request.headers.get("accept", "")

        if "text/html" in accept:
            content = self.generate_html(exc)
            return HTMLResponse(content, status_code=500)
        content = self.generate_plain_text(exc)
        return PlainTextResponse(content, status_code=500)

    def error_response(self, request: Request, exc: Exception) -&gt; Response:
        return PlainTextResponse("Internal Server Error", status_code=500)
</pre></body></html>