Source code for debug_toolbar.litestar.panels.static_files

"""Static files panel for displaying configured static file locations."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, ClassVar

from debug_toolbar.core.panel import Panel

if TYPE_CHECKING:
    from debug_toolbar.core.context import RequestContext


def _static_directories(handler: Any) -> list[str] | None:
    """Return the configured directories for a static file handler, or None.

    Litestar's ``create_static_files_router`` builds its handlers as closures
    over a ``StaticFiles`` instance, so the only way to recover the configured
    directories is to inspect that closure.
    """
    fn = getattr(handler, "fn", None)
    if fn is None or not getattr(fn, "__closure__", None):
        return None

    for name, cell in zip(fn.__code__.co_freevars, fn.__closure__, strict=True):
        if name != "static_files":
            continue
        directories = getattr(cell.cell_contents, "directories", None)
        if not directories:
            return None
        return [str(directory) for directory in directories]

    return None


def collect_static_files_metadata(app: Any, context: RequestContext) -> None:
    """Collect configured static file mount points from a Litestar app.

    Args:
        app: The Litestar application.
        context: The request context to populate.
    """
    mounts: list[dict[str, Any]] = []
    seen_paths: set[str] = set()

    for route in getattr(app, "routes", []):
        for handler in getattr(route, "route_handlers", None) or []:
            directories = _static_directories(handler)
            if directories is None:
                continue

            url_path = route.path.split("{")[0].rstrip("/") or "/"
            if url_path in seen_paths:
                break
            seen_paths.add(url_path)
            mounts.append({"url_path": url_path, "directories": directories})
            break

    mounts.sort(key=lambda mount: mount["url_path"])
    context.metadata["static_files"] = mounts


[docs] class StaticFilesPanel(Panel): """Panel displaying where an app's static files are served from. Shows the URL path and folder(s) on disk for every static file mount registered on the application (e.g. via ``create_static_files_router``). It does not track which static files a specific page actually loaded. """ panel_id: ClassVar[str] = "StaticFilesPanel" title: ClassVar[str] = "Static files" template: ClassVar[str] = "panels/static_files.html" has_content: ClassVar[bool] = True nav_title: ClassVar[str] = "Static files"
[docs] async def generate_stats(self, context: RequestContext) -> dict[str, Any]: """Generate static file mount statistics.""" mounts = context.metadata.get("static_files", []) if not mounts: return {"mounts": [], "message": "No static files configured"} return {"mounts": mounts, "mount_count": len(mounts)}
[docs] def get_nav_subtitle(self) -> str: """Get the navigation subtitle.""" return ""