Files
optuna-dashboard/optuna_dashboard/_bottle_util.py
T

54 lines
1.8 KiB
Python

from __future__ import annotations
import base64
import functools
import json
import logging
import traceback
from typing import Any
from typing import Callable
from typing import cast
from typing import Dict
from typing import TypeVar
from typing import Union
from bottle import BaseResponse
from bottle import HTTPError
from bottle import response
BottleViewReturn = Union[str, bytes, Dict[str, Any], BaseResponse]
BottleView = TypeVar("BottleView", bound=Callable[..., BottleViewReturn])
BottleAPIView = TypeVar("BottleAPIView", bound=Callable[..., Dict[str, Any]])
logger = logging.getLogger(__name__)
def json_api_view(view: BottleAPIView) -> BottleAPIView:
@functools.wraps(view)
def decorated(*args: list[Any], **kwargs: dict[str, Any]) -> BottleViewReturn:
try:
response.content_type = "application/json"
response_body = view(*args, **kwargs)
return response_body
except HTTPError as e:
response.status = e.status_code
return json.dumps({"reason": str(e.body)})
except Exception as e:
response.status = 500
response.content_type = "application/json"
stacktrace = "\n".join(traceback.format_tb(e.__traceback__))
logger.error(f"Exception: {e}\n{stacktrace}")
return json.dumps({"reason": "internal server error"})
return cast(BottleAPIView, decorated)
def parse_data_uri(data_uri: str) -> tuple[str, bytes]:
prefix, a = data_uri.split(":", 1)
if prefix != "data":
raise ValueError("data url must start with 'data:' prefix")
mediatype_with_suffix, base64_data = a.split(",", 1)
mediatype = mediatype_with_suffix.split(";", 1)[0]
data = base64.standard_b64decode(base64_data)
return mediatype, data