from functools import wraps import logging from typing import Callable, ParamSpec, Tuple, Union from werkzeug.wrappers.response import Response from .error import error logger = logging.getLogger(__name__) # Decorator type hinting is hard. # What a view can return (str or Response or (Response, xxx)) ViewReturn = Union[ str, Response, Tuple[str | Response, int] ] # View signature (*arg, **kwargs -> (str or Response or (Response, xxx)) P = ParamSpec('P') ViewCallable = Callable[P, ViewReturn] # Return the exception template or response if an exception occured def exception_handler( file: str, /, json: bool = False, post_redirect: str | None = None ) -> Callable[[ViewCallable], ViewCallable]: def outer(function: ViewCallable, /) -> ViewCallable: @wraps(function) def wrapper(*args, **kwargs) -> ViewReturn: try: return function(*args, **kwargs) # Catch SQLite errors as database errors except Exception as e: return error( e, file, json=json, post_redirect=post_redirect, **kwargs, ) return wrapper return outer