def page(
render: HTMLRenderer[T],
) -> Callable[[MaybeAsyncFunc[P, T]], Callable[P, Coroutine[None, None, Response]]]:
"""
Decorator that converts a FastAPI route's return value into HTML.
Arguments:
render: The render function converting the route's return value to HTML.
"""
def decorator(func: MaybeAsyncFunc[P, T]) -> Callable[P, Coroutine[None, None, Response]]:
@wraps(func) # type: ignore[arg-type]
async def wrapper(*args: P.args, __page_request: Request, **kwargs: P.kwargs) -> T | Response:
result = await execute_maybe_sync_func(func, *args, **kwargs)
if isinstance(result, Response):
return result
response = get_response(kwargs)
rendered: str | Response = await execute_maybe_sync_func(
render, result, context=kwargs, request=__page_request
)
return (
HTMLResponse(rendered, headers=None if response is None else response.headers)
if isinstance(rendered, str)
else rendered
)
return append_to_signature(
wrapper, # type: ignore[arg-type]
inspect.Parameter(
"__page_request",
inspect.Parameter.KEYWORD_ONLY,
annotation=Request,
),
)
return decorator